From 2c3c1048746a4622d8c89a29670120dc8fab93c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:49:45 +0200 Subject: Adding upstream version 6.1.76. Signed-off-by: Daniel Baumann --- arch/arm/mach-omap2/usb-tusb6010.c | 231 +++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 arch/arm/mach-omap2/usb-tusb6010.c (limited to 'arch/arm/mach-omap2/usb-tusb6010.c') diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c new file mode 100644 index 000000000..a0c4c42e5 --- /dev/null +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * linux/arch/arm/mach-omap2/usb-tusb6010.c + * + * Copyright (C) 2006 Nokia Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gpmc.h" + +static u8 async_cs, sync_cs; +static unsigned refclk_psec; + +static struct gpmc_settings tusb_async = { + .wait_on_read = true, + .wait_on_write = true, + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, +}; + +static struct gpmc_settings tusb_sync = { + .burst_read = true, + .burst_write = true, + .sync_read = true, + .sync_write = true, + .wait_on_read = true, + .wait_on_write = true, + .burst_len = GPMC_BURST_16, + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, +}; + +/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ + +static int tusb_set_async_mode(unsigned sysclk_ps) +{ + struct gpmc_device_timings dev_t; + struct gpmc_timings t; + unsigned t_acsnh_advnh = sysclk_ps + 3000; + + memset(&dev_t, 0, sizeof(dev_t)); + + dev_t.t_ceasu = 8 * 1000; + dev_t.t_avdasu = t_acsnh_advnh - 7000; + dev_t.t_ce_avd = 1000; + dev_t.t_avdp_r = t_acsnh_advnh; + dev_t.t_oeasu = t_acsnh_advnh + 1000; + dev_t.t_oe = 300; + dev_t.t_cez_r = 7000; + dev_t.t_cez_w = dev_t.t_cez_r; + dev_t.t_avdp_w = t_acsnh_advnh; + dev_t.t_weasu = t_acsnh_advnh + 1000; + dev_t.t_wpl = 300; + dev_t.cyc_aavdh_we = 1; + + gpmc_calc_timings(&t, &tusb_async, &dev_t); + + return gpmc_cs_set_timings(async_cs, &t, &tusb_async); +} + +static int tusb_set_sync_mode(unsigned sysclk_ps) +{ + struct gpmc_device_timings dev_t; + struct gpmc_timings t; + unsigned t_scsnh_advnh = sysclk_ps + 3000; + + memset(&dev_t, 0, sizeof(dev_t)); + + dev_t.clk = 11100; + dev_t.t_bacc = 1000; + dev_t.t_ces = 1000; + dev_t.t_ceasu = 8 * 1000; + dev_t.t_avdasu = t_scsnh_advnh - 7000; + dev_t.t_ce_avd = 1000; + dev_t.t_avdp_r = t_scsnh_advnh; + dev_t.cyc_aavdh_oe = 3; + dev_t.cyc_oe = 5; + dev_t.t_ce_rdyz = 7000; + dev_t.t_avdp_w = t_scsnh_advnh; + dev_t.cyc_aavdh_we = 3; + dev_t.cyc_wpl = 6; + + gpmc_calc_timings(&t, &tusb_sync, &dev_t); + + return gpmc_cs_set_timings(sync_cs, &t, &tusb_sync); +} + +/* tusb driver calls this when it changes the chip's clocking */ +int tusb6010_platform_retime(unsigned is_refclk) +{ + static const char error[] = + KERN_ERR "tusb6010 %s retime error %d\n"; + + unsigned sysclk_ps; + int status; + + if (!refclk_psec) + return -ENODEV; + + sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; + + status = tusb_set_async_mode(sysclk_ps); + if (status < 0) { + printk(error, "async", status); + goto done; + } + status = tusb_set_sync_mode(sysclk_ps); + if (status < 0) + printk(error, "sync", status); +done: + return status; +} +EXPORT_SYMBOL_GPL(tusb6010_platform_retime); + +static struct resource tusb_resources[] = { + /* Order is significant! The start/end fields + * are updated during setup.. + */ + { /* Asynchronous access */ + .flags = IORESOURCE_MEM, + }, + { /* Synchronous access */ + .flags = IORESOURCE_MEM, + }, + { /* IRQ */ + .name = "mc", + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 tusb_dmamask = ~(u32)0; + +static struct platform_device tusb_device = { + .name = "musb-tusb", + .id = -1, + .dev = { + .dma_mask = &tusb_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(tusb_resources), + .resource = tusb_resources, +}; + + +/* this may be called only from board-*.c setup code */ +int __init +tusb6010_setup_interface(struct musb_hdrc_platform_data *data, + unsigned ps_refclk, unsigned waitpin, + unsigned async, unsigned sync, + unsigned irq, unsigned dmachan) +{ + int status; + static char error[] __initdata = + KERN_ERR "tusb6010 init error %d, %d\n"; + + /* ASYNC region, primarily for PIO */ + status = gpmc_cs_request(async, SZ_16M, (unsigned long *) + &tusb_resources[0].start); + if (status < 0) { + printk(error, 1, status); + return status; + } + tusb_resources[0].end = tusb_resources[0].start + 0x9ff; + tusb_async.wait_pin = waitpin; + async_cs = async; + + status = gpmc_cs_program_settings(async_cs, &tusb_async); + if (status < 0) + return status; + + /* SYNC region, primarily for DMA */ + status = gpmc_cs_request(sync, SZ_16M, (unsigned long *) + &tusb_resources[1].start); + if (status < 0) { + printk(error, 2, status); + return status; + } + tusb_resources[1].end = tusb_resources[1].start + 0x9ff; + tusb_sync.wait_pin = waitpin; + sync_cs = sync; + + status = gpmc_cs_program_settings(sync_cs, &tusb_sync); + if (status < 0) + return status; + + /* IRQ */ + status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq"); + if (status < 0) { + printk(error, 3, status); + return status; + } + tusb_resources[2].start = gpio_to_irq(irq); + + /* set up memory timings ... can speed them up later */ + if (!ps_refclk) { + printk(error, 4, status); + return -ENODEV; + } + refclk_psec = ps_refclk; + status = tusb6010_platform_retime(1); + if (status < 0) { + printk(error, 5, status); + return status; + } + + /* finish device setup ... */ + if (!data) { + printk(error, 6, status); + return -ENODEV; + } + tusb_device.dev.platform_data = data; + + /* so far so good ... register the device */ + status = platform_device_register(&tusb_device); + if (status < 0) { + printk(error, 7, status); + return status; + } + return 0; +} -- cgit v1.2.3