diff --git a/arch/arm/boot/dts/nintendo3ds.dtsi b/arch/arm/boot/dts/nintendo3ds.dtsi index 1b30e3045b80b5..05c473cfb55dbf 100755 --- a/arch/arm/boot/dts/nintendo3ds.dtsi +++ b/arch/arm/boot/dts/nintendo3ds.dtsi @@ -125,6 +125,20 @@ interrupt-controller; #interrupt-cells = <2>; + + txrc_ir_hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "IR_TXRC"; + }; + + rx_ir_hog { + gpio-hog; + gpios = <5 0>; + input; + line-name = "IR_RXD"; + }; }; gpio4: gpio-controller@10147028 { @@ -241,7 +255,7 @@ interrupts = ; - sc16is750: infrared@4d { + sc16is7xx: infrared@4d { compatible = "nxp,sc16is750"; reg = <0x4d>; clocks = <&irclk>; @@ -250,6 +264,18 @@ gpio-controller; #gpio-cells = <2>; + + /* + * The SC16IS7X0 is connected to a ROHM RPM841 IrDA module + * This module has a PWDOWN input that needs to be + * kept low if we want data to come through + */ + pwdown_low_hog { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "PWDOWN"; + }; }; }; diff --git a/arch/arm/boot/dts/nintendo3ds_ktr.dts b/arch/arm/boot/dts/nintendo3ds_ktr.dts index 0ff4cabde180ae..a25af67ea15b03 100644 --- a/arch/arm/boot/dts/nintendo3ds_ktr.dts +++ b/arch/arm/boot/dts/nintendo3ds_ktr.dts @@ -52,3 +52,13 @@ bootargs = "keep_bootcon fbcon=rotate:1"; }; }; + +&sc16is7xx { + /* + * The new3DS has a SC16IS760 UART + * Override the default choice of SC16IS750 + * It doesn't make much of a difference since you + * can't really use the fast mode via I2C but w/e + */ + compatible = "nxp,sc16is760"; +}; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index f86ec2d2635b7c..c2df48df184979 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1161,15 +1161,11 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, { struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; - u8 state = sc16is7xx_port_read(port, SC16IS7XX_IOSTATE_REG); - if (val) - state |= BIT(offset); - else - state &= ~BIT(offset); - sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state); sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset), BIT(offset)); + sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), + val ? BIT(offset) : 0); return 0; } @@ -1240,25 +1236,6 @@ static int sc16is7xx_probe(struct device *dev, } sched_set_fifo(s->kworker_task); -#ifdef CONFIG_GPIOLIB - if (devtype->nr_gpio) { - /* Setup GPIO cotroller */ - s->gpio.owner = THIS_MODULE; - s->gpio.parent = dev; - s->gpio.label = dev_name(dev); - s->gpio.direction_input = sc16is7xx_gpio_direction_input; - s->gpio.get = sc16is7xx_gpio_get; - s->gpio.direction_output = sc16is7xx_gpio_direction_output; - s->gpio.set = sc16is7xx_gpio_set; - s->gpio.base = -1; - s->gpio.ngpio = devtype->nr_gpio; - s->gpio.can_sleep = 1; - ret = gpiochip_add_data(&s->gpio, s); - if (ret) - goto out_thread; - } -#endif - /* reset device, purging any pending irq / data */ regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT, SC16IS7XX_IOCONTROL_SRESET_BIT); @@ -1279,7 +1256,7 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.line = sc16is7xx_alloc_line(); if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) { ret = -ENOMEM; - goto out_ports; + goto out_thread; } /* Disable all interrupts */ @@ -1324,6 +1301,25 @@ static int sc16is7xx_probe(struct device *dev, s->p[u].irda_mode = true; } +#ifdef CONFIG_GPIOLIB + if (devtype->nr_gpio) { + /* Setup GPIO cotroller */ + s->gpio.owner = THIS_MODULE; + s->gpio.parent = dev; + s->gpio.label = dev_name(dev); + s->gpio.direction_input = sc16is7xx_gpio_direction_input; + s->gpio.get = sc16is7xx_gpio_get; + s->gpio.direction_output = sc16is7xx_gpio_direction_output; + s->gpio.set = sc16is7xx_gpio_set; + s->gpio.base = -1; + s->gpio.ngpio = devtype->nr_gpio; + s->gpio.can_sleep = 1; + ret = gpiochip_add_data(&s->gpio, s); + if (ret) + goto out_ports; + } +#endif + /* * Setup interrupt. We first try to acquire the IRQ line as level IRQ. * If that succeeds, we can allow sharing the interrupt as well. @@ -1343,18 +1339,18 @@ static int sc16is7xx_probe(struct device *dev, if (!ret) return 0; +#ifdef CONFIG_GPIOLIB + if (devtype->nr_gpio) + gpiochip_remove(&s->gpio); + out_ports: +#endif for (i--; i >= 0; i--) { uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); clear_bit(s->p[i].port.line, &sc16is7xx_lines); } -#ifdef CONFIG_GPIOLIB - if (devtype->nr_gpio) - gpiochip_remove(&s->gpio); - out_thread: -#endif kthread_stop(s->kworker_task); out_clk: