mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
0b47a62ea6
arch/arm/mach-omap[12]. The patches have been reviewed and tested by everyone who showed interest which was one person that tested on OSK1 and Nokia 770, and we smoked out the bugs and also addressed all review comments. Any remaining problems can certainly be fixed in-tree. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmRuCyUACgkQQRCzN7AZ XXPZKxAAtrTAYiCqR4EuJWh+l1SiilazOJWI3CoR6z2QDW09T8VEpNSfVHkmxyDL FnZKmXsXAJl783Ial3hXfxXb7oxIHIRBU88C+aQN+4w4VxA4ujxV3uAoMA1SFFOL +wpGZIT9ReUpUf988wK31SitNB7frNygQosA7kOmhbMWxIUkNs5UYynSjNDrVTNJ oVf/e7VM2smbOqbZFhwFNfxu35Oe+ak4xREG4gX+00VtUPJfM85WcMqZNiVzVPcC 5Hw2nfW9w+ZQyoR1B+UQbeZkbw0Ibb4dpTM43Jij6VO0gKBy+9AsD0oeSih6BiIL irBlHYeAtvSmwxVLvlBGZmHBdB8o5tkf1DKvztYPVR+qgoRrY/3LCeSViCjJhNUT MNLIR1tTjVR/EouBo7SR4s8Xn/H38Fp3D/sCath/pajRH4446hos/Egh/is8N9Lv +OX/L4pO8OeKUiYyEgFkvaIH/L31OCX5ihPh5ErvVQEysYQ3MZGtEBLVgz4QMp7p U3SncOfy5VdNX46fDJfNUMsFfl+RKYPhihQ7zRkeJb+qAled7dabwaBCf0L+gKn8 DpN5rpePOlC0yfFpB0tftDsrrNanh0oZAKjRq9h8+/MbnNYUm9dEv1WeMcDJ17uD IhfB9gAcHRsDQd/Fc4btDB4GnfPli+CBMxkRWOV1eyMHriBf7Cw= =fMmV -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmRwuesACgkQYKtH/8kJ Uif76g/+LKRH+kW01pbLOo/AVabzH6Jb3QICFN4qeRvTkA3EyuxXMinOQFRvdLW5 E7MCZtOAio8Wm2Gg7kCSb32t13gPhFmyWZAIRVDuWxcSbBFlRkWF0h/rCv0Nq+Q3 Szkwbz3nAEZU5so/4sfPdddtN48DTdwVLux+5IeI1H9QRJyyAkH7OoS/Ll/E7Ubx MCeT+OuT9yTjvrX0jMt4mYHn09OxV174OIo9r3p66HR5TzqAmbEdrb4Hm9FN+wZd j/yNNVBp68As1Qo4u/CZPM9LAp77A3oZoMRGkWHyjxaHoYsCuUf1aPnjeSaYxCQN koLx4/3eZOgQk3l7yYlMIaQP0BkgDU4EZ6aLCON9VkanmqYicVPdXKaH1UGgf8xJ p2lWdDY1FODmmyAfkpI9hVyFsh5/JjEUMmGcl1tdD42nHOZyf3gLUW7BxhaxLzr5 XsLd6KQaSEaKYL5+v09FSUah8j9fA4qf42sr4ElX4pkzKvaGc35MLytZjoa4Ldrk OCtUVmdYK+C3xM3OO5CAzQaJKgskhPkU9UQLwVE5Vmye0mKqT0YPQitjvYgUrHw4 u+EekfBLyRme4WDQDPjgYBJQ2d5ufapYI9SZ1Xq1xPPsrjDW8r3if4fzUwB3Sd7Q RY4ojBprBsyezPJQJFsyJieVOL3hlZ9G3SnzGG7MJQ6nsypAwnc= =pBEM -----END PGP SIGNATURE----- Merge tag 'gpio-omap-descriptors-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio into soc/arm This removes all usage of global GPIO numbers from arch/arm/mach-omap[12]. The patches have been reviewed and tested by everyone who showed interest which was one person that tested on OSK1 and Nokia 770, and we smoked out the bugs and also addressed all review comments. Any remaining problems can certainly be fixed in-tree. * tag 'gpio-omap-descriptors-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: ARM/musb: omap2: Remove global GPIO numbers from TUSB6010 ARM: omap2: Rewrite WLAN quirk to use GPIO descriptors ARM: omap2: Get USB hub reset GPIO from descriptor ARM/gpio: Push OMAP2 quirk down into TWL4030 driver ARM: omap1: Exorcise the legacy GPIO header ARM: omap1: Make serial wakeup GPIOs use descriptors ARM: omap1: Fix up the Nokia 770 board device IRQs ARM/mmc: Convert old mmci-omap to GPIO descriptors Input: ads7846 - Convert to use software nodes ARM: omap1: Remove reliance on GPIO numbers from SX1 ARM: omap1: Remove reliance on GPIO numbers from PalmTE ARM: omap1: Drop header on AMS Delta ARM/mfd/gpio: Fixup TPS65010 regression on OMAP1 OSK1 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
247 lines
5.6 KiB
C
247 lines
5.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* linux/arch/arm/mach-omap1/serial.c
|
|
*
|
|
* OMAP1 serial support.
|
|
*/
|
|
#include <linux/gpio/machine.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/serial.h>
|
|
#include <linux/tty.h>
|
|
#include <linux/serial_8250.h>
|
|
#include <linux/serial_reg.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/io.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
|
|
#include "common.h"
|
|
#include "serial.h"
|
|
#include "mux.h"
|
|
#include "pm.h"
|
|
#include "soc.h"
|
|
|
|
static struct clk * uart1_ck;
|
|
static struct clk * uart2_ck;
|
|
static struct clk * uart3_ck;
|
|
|
|
static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
|
|
int offset)
|
|
{
|
|
offset <<= up->regshift;
|
|
return (unsigned int)__raw_readb(up->membase + offset);
|
|
}
|
|
|
|
static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
|
|
int value)
|
|
{
|
|
offset <<= p->regshift;
|
|
__raw_writeb(value, p->membase + offset);
|
|
}
|
|
|
|
/*
|
|
* Internal UARTs need to be initialized for the 8250 autoconfig to work
|
|
* properly. Note that the TX watermark initialization may not be needed
|
|
* once the 8250.c watermark handling code is merged.
|
|
*/
|
|
static void __init omap_serial_reset(struct plat_serial8250_port *p)
|
|
{
|
|
omap_serial_outp(p, UART_OMAP_MDR1,
|
|
UART_OMAP_MDR1_DISABLE); /* disable UART */
|
|
omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */
|
|
omap_serial_outp(p, UART_OMAP_MDR1,
|
|
UART_OMAP_MDR1_16X_MODE); /* enable UART */
|
|
|
|
if (!cpu_is_omap15xx()) {
|
|
omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
|
|
while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
|
|
}
|
|
}
|
|
|
|
static struct plat_serial8250_port serial_platform_data[] = {
|
|
{
|
|
.mapbase = OMAP1_UART1_BASE,
|
|
.irq = INT_UART1,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
},
|
|
{
|
|
.mapbase = OMAP1_UART2_BASE,
|
|
.irq = INT_UART2,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
},
|
|
{
|
|
.mapbase = OMAP1_UART3_BASE,
|
|
.irq = INT_UART3,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
},
|
|
{ },
|
|
};
|
|
|
|
static struct platform_device serial_device = {
|
|
.name = "serial8250",
|
|
.id = PLAT8250_DEV_PLATFORM,
|
|
.dev = {
|
|
.platform_data = serial_platform_data,
|
|
},
|
|
};
|
|
|
|
/*
|
|
* Note that on Innovator-1510 UART2 pins conflict with USB2.
|
|
* By default UART2 does not work on Innovator-1510 if you have
|
|
* USB OHCI enabled. To use UART2, you must disable USB2 first.
|
|
*/
|
|
void __init omap_serial_init(void)
|
|
{
|
|
int i;
|
|
|
|
if (cpu_is_omap15xx()) {
|
|
serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
|
|
serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
|
|
serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(serial_platform_data) - 1; i++) {
|
|
/* Static mapping, never released */
|
|
serial_platform_data[i].membase =
|
|
ioremap(serial_platform_data[i].mapbase, SZ_2K);
|
|
if (!serial_platform_data[i].membase) {
|
|
printk(KERN_ERR "Could not ioremap uart%i\n", i);
|
|
continue;
|
|
}
|
|
switch (i) {
|
|
case 0:
|
|
uart1_ck = clk_get(NULL, "uart1_ck");
|
|
if (IS_ERR(uart1_ck))
|
|
printk("Could not get uart1_ck\n");
|
|
else {
|
|
clk_prepare_enable(uart1_ck);
|
|
if (cpu_is_omap15xx())
|
|
clk_set_rate(uart1_ck, 12000000);
|
|
}
|
|
break;
|
|
case 1:
|
|
uart2_ck = clk_get(NULL, "uart2_ck");
|
|
if (IS_ERR(uart2_ck))
|
|
printk("Could not get uart2_ck\n");
|
|
else {
|
|
clk_prepare_enable(uart2_ck);
|
|
if (cpu_is_omap15xx())
|
|
clk_set_rate(uart2_ck, 12000000);
|
|
else
|
|
clk_set_rate(uart2_ck, 48000000);
|
|
}
|
|
break;
|
|
case 2:
|
|
uart3_ck = clk_get(NULL, "uart3_ck");
|
|
if (IS_ERR(uart3_ck))
|
|
printk("Could not get uart3_ck\n");
|
|
else {
|
|
clk_prepare_enable(uart3_ck);
|
|
if (cpu_is_omap15xx())
|
|
clk_set_rate(uart3_ck, 12000000);
|
|
}
|
|
break;
|
|
}
|
|
omap_serial_reset(&serial_platform_data[i]);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_OMAP_SERIAL_WAKE
|
|
|
|
static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id)
|
|
{
|
|
/* Need to do something with serial port right after wake-up? */
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/*
|
|
* Reroutes serial RX lines to GPIO lines for the duration of
|
|
* sleep to allow waking up the device from serial port even
|
|
* in deep sleep.
|
|
*/
|
|
void omap_serial_wake_trigger(int enable)
|
|
{
|
|
if (!cpu_is_omap16xx())
|
|
return;
|
|
|
|
if (uart1_ck != NULL) {
|
|
if (enable)
|
|
omap_cfg_reg(V14_16XX_GPIO37);
|
|
else
|
|
omap_cfg_reg(V14_16XX_UART1_RX);
|
|
}
|
|
if (uart2_ck != NULL) {
|
|
if (enable)
|
|
omap_cfg_reg(R9_16XX_GPIO18);
|
|
else
|
|
omap_cfg_reg(R9_16XX_UART2_RX);
|
|
}
|
|
if (uart3_ck != NULL) {
|
|
if (enable)
|
|
omap_cfg_reg(L14_16XX_GPIO49);
|
|
else
|
|
omap_cfg_reg(L14_16XX_UART3_RX);
|
|
}
|
|
}
|
|
|
|
static void __init omap_serial_set_port_wakeup(int idx)
|
|
{
|
|
struct gpio_desc *d;
|
|
int ret;
|
|
|
|
d = gpiod_get_index(NULL, "wakeup", idx, GPIOD_IN);
|
|
if (IS_ERR(d)) {
|
|
pr_err("Unable to get UART wakeup GPIO descriptor\n");
|
|
return;
|
|
}
|
|
ret = request_irq(gpiod_to_irq(d), &omap_serial_wake_interrupt,
|
|
IRQF_TRIGGER_RISING, "serial wakeup", NULL);
|
|
if (ret) {
|
|
gpiod_put(d);
|
|
pr_err("No interrupt for UART%d wake GPIO\n", idx + 1);
|
|
return;
|
|
}
|
|
enable_irq_wake(gpiod_to_irq(d));
|
|
}
|
|
|
|
|
|
int __init omap_serial_wakeup_init(void)
|
|
{
|
|
if (!cpu_is_omap16xx())
|
|
return 0;
|
|
|
|
if (uart1_ck != NULL)
|
|
omap_serial_set_port_wakeup(0);
|
|
if (uart2_ck != NULL)
|
|
omap_serial_set_port_wakeup(1);
|
|
if (uart3_ck != NULL)
|
|
omap_serial_set_port_wakeup(2);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_OMAP_SERIAL_WAKE */
|
|
|
|
static int __init omap_init(void)
|
|
{
|
|
if (!cpu_class_is_omap1())
|
|
return -ENODEV;
|
|
|
|
return platform_device_register(&serial_device);
|
|
}
|
|
arch_initcall(omap_init);
|