linux/arch/arm/mach-sa1100/neponset.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/arch/arm/mach-sa1100/neponset.c
   4 */
   5#include <linux/err.h>
   6#include <linux/gpio/driver.h>
   7#include <linux/gpio/gpio-reg.h>
   8#include <linux/init.h>
   9#include <linux/ioport.h>
  10#include <linux/irq.h>
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/platform_data/sa11x0-serial.h>
  14#include <linux/platform_device.h>
  15#include <linux/pm.h>
  16#include <linux/serial_core.h>
  17#include <linux/slab.h>
  18#include <linux/smc91x.h>
  19
  20#include <asm/mach-types.h>
  21#include <asm/mach/map.h>
  22#include <asm/hardware/sa1111.h>
  23#include <asm/sizes.h>
  24
  25#include <mach/hardware.h>
  26#include <mach/assabet.h>
  27#include <mach/neponset.h>
  28#include <mach/irqs.h>
  29
  30#define NEP_IRQ_SMC91X  0
  31#define NEP_IRQ_USAR    1
  32#define NEP_IRQ_SA1111  2
  33#define NEP_IRQ_NR      3
  34
  35#define WHOAMI          0x00
  36#define LEDS            0x10
  37#define SWPK            0x20
  38#define IRR             0x24
  39#define KP_Y_IN         0x80
  40#define KP_X_OUT        0x90
  41#define NCR_0           0xa0
  42#define MDM_CTL_0       0xb0
  43#define MDM_CTL_1       0xb4
  44#define AUD_CTL         0xc0
  45
  46#define IRR_ETHERNET    (1 << 0)
  47#define IRR_USAR        (1 << 1)
  48#define IRR_SA1111      (1 << 2)
  49
  50#define NCR_NGPIO       7
  51
  52#define MDM_CTL0_RTS1   (1 << 0)
  53#define MDM_CTL0_DTR1   (1 << 1)
  54#define MDM_CTL0_RTS2   (1 << 2)
  55#define MDM_CTL0_DTR2   (1 << 3)
  56#define MDM_CTL0_NGPIO  4
  57
  58#define MDM_CTL1_CTS1   (1 << 0)
  59#define MDM_CTL1_DSR1   (1 << 1)
  60#define MDM_CTL1_DCD1   (1 << 2)
  61#define MDM_CTL1_CTS2   (1 << 3)
  62#define MDM_CTL1_DSR2   (1 << 4)
  63#define MDM_CTL1_DCD2   (1 << 5)
  64#define MDM_CTL1_NGPIO  6
  65
  66#define AUD_SEL_1341    (1 << 0)
  67#define AUD_MUTE_1341   (1 << 1)
  68#define AUD_NGPIO       2
  69
  70extern void sa1110_mb_disable(void);
  71
  72#define to_neponset_gpio_chip(x) container_of(x, struct neponset_gpio_chip, gc)
  73
  74static const char *neponset_ncr_names[] = {
  75        "gp01_off", "tp_power", "ms_power", "enet_osc",
  76        "spi_kb_wk_up", "a0vpp", "a1vpp"
  77};
  78
  79static const char *neponset_mdmctl0_names[] = {
  80        "rts3", "dtr3", "rts1", "dtr1",
  81};
  82
  83static const char *neponset_mdmctl1_names[] = {
  84        "cts3", "dsr3", "dcd3", "cts1", "dsr1", "dcd1"
  85};
  86
  87static const char *neponset_aud_names[] = {
  88        "sel_1341", "mute_1341",
  89};
  90
  91struct neponset_drvdata {
  92        void __iomem *base;
  93        struct platform_device *sa1111;
  94        struct platform_device *smc91x;
  95        unsigned irq_base;
  96        struct gpio_chip *gpio[4];
  97};
  98
  99static struct neponset_drvdata *nep;
 100
 101void neponset_ncr_frob(unsigned int mask, unsigned int val)
 102{
 103        struct neponset_drvdata *n = nep;
 104        unsigned long m = mask, v = val;
 105
 106        if (nep)
 107                n->gpio[0]->set_multiple(n->gpio[0], &m, &v);
 108        else
 109                WARN(1, "nep unset\n");
 110}
 111EXPORT_SYMBOL(neponset_ncr_frob);
 112
 113static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
 114{
 115        struct neponset_drvdata *n = nep;
 116        unsigned long mask, val = 0;
 117
 118        if (!n)
 119                return;
 120
 121        if (port->mapbase == _Ser1UTCR0) {
 122                mask = MDM_CTL0_RTS2 | MDM_CTL0_DTR2;
 123
 124                if (!(mctrl & TIOCM_RTS))
 125                        val |= MDM_CTL0_RTS2;
 126
 127                if (!(mctrl & TIOCM_DTR))
 128                        val |= MDM_CTL0_DTR2;
 129        } else if (port->mapbase == _Ser3UTCR0) {
 130                mask = MDM_CTL0_RTS1 | MDM_CTL0_DTR1;
 131
 132                if (!(mctrl & TIOCM_RTS))
 133                        val |= MDM_CTL0_RTS1;
 134
 135                if (!(mctrl & TIOCM_DTR))
 136                        val |= MDM_CTL0_DTR1;
 137        }
 138
 139        n->gpio[1]->set_multiple(n->gpio[1], &mask, &val);
 140}
 141
 142static u_int neponset_get_mctrl(struct uart_port *port)
 143{
 144        void __iomem *base = nep->base;
 145        u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
 146        u_int mdm_ctl1;
 147
 148        if (!base)
 149                return ret;
 150
 151        mdm_ctl1 = readb_relaxed(base + MDM_CTL_1);
 152        if (port->mapbase == _Ser1UTCR0) {
 153                if (mdm_ctl1 & MDM_CTL1_DCD2)
 154                        ret &= ~TIOCM_CD;
 155                if (mdm_ctl1 & MDM_CTL1_CTS2)
 156                        ret &= ~TIOCM_CTS;
 157                if (mdm_ctl1 & MDM_CTL1_DSR2)
 158                        ret &= ~TIOCM_DSR;
 159        } else if (port->mapbase == _Ser3UTCR0) {
 160                if (mdm_ctl1 & MDM_CTL1_DCD1)
 161                        ret &= ~TIOCM_CD;
 162                if (mdm_ctl1 & MDM_CTL1_CTS1)
 163                        ret &= ~TIOCM_CTS;
 164                if (mdm_ctl1 & MDM_CTL1_DSR1)
 165                        ret &= ~TIOCM_DSR;
 166        }
 167
 168        return ret;
 169}
 170
 171static struct sa1100_port_fns neponset_port_fns = {
 172        .set_mctrl      = neponset_set_mctrl,
 173        .get_mctrl      = neponset_get_mctrl,
 174};
 175
 176/*
 177 * Install handler for Neponset IRQ.  Note that we have to loop here
 178 * since the ETHERNET and USAR IRQs are level based, and we need to
 179 * ensure that the IRQ signal is deasserted before returning.  This
 180 * is rather unfortunate.
 181 */
 182static void neponset_irq_handler(struct irq_desc *desc)
 183{
 184        struct neponset_drvdata *d = irq_desc_get_handler_data(desc);
 185        unsigned int irr;
 186
 187        while (1) {
 188                /*
 189                 * Acknowledge the parent IRQ.
 190                 */
 191                desc->irq_data.chip->irq_ack(&desc->irq_data);
 192
 193                /*
 194                 * Read the interrupt reason register.  Let's have all
 195                 * active IRQ bits high.  Note: there is a typo in the
 196                 * Neponset user's guide for the SA1111 IRR level.
 197                 */
 198                irr = readb_relaxed(d->base + IRR);
 199                irr ^= IRR_ETHERNET | IRR_USAR;
 200
 201                if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
 202                        break;
 203
 204                /*
 205                 * Since there is no individual mask, we have to
 206                 * mask the parent IRQ.  This is safe, since we'll
 207                 * recheck the register for any pending IRQs.
 208                 */
 209                if (irr & (IRR_ETHERNET | IRR_USAR)) {
 210                        desc->irq_data.chip->irq_mask(&desc->irq_data);
 211
 212                        /*
 213                         * Ack the interrupt now to prevent re-entering
 214                         * this neponset handler.  Again, this is safe
 215                         * since we'll check the IRR register prior to
 216                         * leaving.
 217                         */
 218                        desc->irq_data.chip->irq_ack(&desc->irq_data);
 219
 220                        if (irr & IRR_ETHERNET)
 221                                generic_handle_irq(d->irq_base + NEP_IRQ_SMC91X);
 222
 223                        if (irr & IRR_USAR)
 224                                generic_handle_irq(d->irq_base + NEP_IRQ_USAR);
 225
 226                        desc->irq_data.chip->irq_unmask(&desc->irq_data);
 227                }
 228
 229                if (irr & IRR_SA1111)
 230                        generic_handle_irq(d->irq_base + NEP_IRQ_SA1111);
 231        }
 232}
 233
 234/* Yes, we really do not have any kind of masking or unmasking */
 235static void nochip_noop(struct irq_data *irq)
 236{
 237}
 238
 239static struct irq_chip nochip = {
 240        .name = "neponset",
 241        .irq_ack = nochip_noop,
 242        .irq_mask = nochip_noop,
 243        .irq_unmask = nochip_noop,
 244};
 245
 246static int neponset_init_gpio(struct gpio_chip **gcp,
 247        struct device *dev, const char *label, void __iomem *reg,
 248        unsigned num, bool in, const char *const * names)
 249{
 250        struct gpio_chip *gc;
 251
 252        gc = gpio_reg_init(dev, reg, -1, num, label, in ? 0xffffffff : 0,
 253                           readl_relaxed(reg), names, NULL, NULL);
 254        if (IS_ERR(gc))
 255                return PTR_ERR(gc);
 256
 257        *gcp = gc;
 258
 259        return 0;
 260}
 261
 262static struct sa1111_platform_data sa1111_info = {
 263        .disable_devs   = SA1111_DEVID_PS2_MSE,
 264};
 265
 266static int neponset_probe(struct platform_device *dev)
 267{
 268        struct neponset_drvdata *d;
 269        struct resource *nep_res, *sa1111_res, *smc91x_res;
 270        struct resource sa1111_resources[] = {
 271                DEFINE_RES_MEM(0x40000000, SZ_8K),
 272                { .flags = IORESOURCE_IRQ },
 273        };
 274        struct platform_device_info sa1111_devinfo = {
 275                .parent = &dev->dev,
 276                .name = "sa1111",
 277                .id = 0,
 278                .res = sa1111_resources,
 279                .num_res = ARRAY_SIZE(sa1111_resources),
 280                .data = &sa1111_info,
 281                .size_data = sizeof(sa1111_info),
 282                .dma_mask = 0xffffffffUL,
 283        };
 284        struct resource smc91x_resources[] = {
 285                DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS,
 286                        0x02000000, "smc91x-regs"),
 287                DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000,
 288                        0x02000000, "smc91x-attrib"),
 289                { .flags = IORESOURCE_IRQ },
 290        };
 291        struct smc91x_platdata smc91x_platdata = {
 292                .flags = SMC91X_USE_8BIT | SMC91X_IO_SHIFT_2 | SMC91X_NOWAIT,
 293        };
 294        struct platform_device_info smc91x_devinfo = {
 295                .parent = &dev->dev,
 296                .name = "smc91x",
 297                .id = 0,
 298                .res = smc91x_resources,
 299                .num_res = ARRAY_SIZE(smc91x_resources),
 300                .data = &smc91x_platdata,
 301                .size_data = sizeof(smc91x_platdata),
 302        };
 303        int ret, irq;
 304
 305        if (nep)
 306                return -EBUSY;
 307
 308        irq = ret = platform_get_irq(dev, 0);
 309        if (ret < 0)
 310                goto err_alloc;
 311
 312        nep_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 313        smc91x_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
 314        sa1111_res = platform_get_resource(dev, IORESOURCE_MEM, 2);
 315        if (!nep_res || !smc91x_res || !sa1111_res) {
 316                ret = -ENXIO;
 317                goto err_alloc;
 318        }
 319
 320        d = kzalloc(sizeof(*d), GFP_KERNEL);
 321        if (!d) {
 322                ret = -ENOMEM;
 323                goto err_alloc;
 324        }
 325
 326        d->base = ioremap(nep_res->start, SZ_4K);
 327        if (!d->base) {
 328                ret = -ENOMEM;
 329                goto err_ioremap;
 330        }
 331
 332        if (readb_relaxed(d->base + WHOAMI) != 0x11) {
 333                dev_warn(&dev->dev, "Neponset board detected, but wrong ID: %02x\n",
 334                         readb_relaxed(d->base + WHOAMI));
 335                ret = -ENODEV;
 336                goto err_id;
 337        }
 338
 339        ret = irq_alloc_descs(-1, IRQ_BOARD_START, NEP_IRQ_NR, -1);
 340        if (ret <= 0) {
 341                dev_err(&dev->dev, "unable to allocate %u irqs: %d\n",
 342                        NEP_IRQ_NR, ret);
 343                if (ret == 0)
 344                        ret = -ENOMEM;
 345                goto err_irq_alloc;
 346        }
 347
 348        d->irq_base = ret;
 349
 350        irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip,
 351                handle_simple_irq);
 352        irq_clear_status_flags(d->irq_base + NEP_IRQ_SMC91X, IRQ_NOREQUEST | IRQ_NOPROBE);
 353        irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip,
 354                handle_simple_irq);
 355        irq_clear_status_flags(d->irq_base + NEP_IRQ_USAR, IRQ_NOREQUEST | IRQ_NOPROBE);
 356        irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip);
 357
 358        irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 359        irq_set_chained_handler_and_data(irq, neponset_irq_handler, d);
 360
 361        /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */
 362        writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0);
 363
 364        neponset_init_gpio(&d->gpio[0], &dev->dev, "neponset-ncr",
 365                           d->base + NCR_0, NCR_NGPIO, false,
 366                           neponset_ncr_names);
 367        neponset_init_gpio(&d->gpio[1], &dev->dev, "neponset-mdm-ctl0",
 368                           d->base + MDM_CTL_0, MDM_CTL0_NGPIO, false,
 369                           neponset_mdmctl0_names);
 370        neponset_init_gpio(&d->gpio[2], &dev->dev, "neponset-mdm-ctl1",
 371                           d->base + MDM_CTL_1, MDM_CTL1_NGPIO, true,
 372                           neponset_mdmctl1_names);
 373        neponset_init_gpio(&d->gpio[3], &dev->dev, "neponset-aud-ctl",
 374                           d->base + AUD_CTL, AUD_NGPIO, false,
 375                           neponset_aud_names);
 376
 377        /*
 378         * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
 379         * something on the Neponset activates this IRQ on sleep (eth?)
 380         */
 381#if 0
 382        enable_irq_wake(irq);
 383#endif
 384
 385        dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n",
 386                 d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
 387        nep = d;
 388
 389        sa1100_register_uart_fns(&neponset_port_fns);
 390
 391        /* Ensure that the memory bus request/grant signals are setup */
 392        sa1110_mb_disable();
 393
 394        sa1111_resources[0].parent = sa1111_res;
 395        sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111;
 396        sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111;
 397        d->sa1111 = platform_device_register_full(&sa1111_devinfo);
 398
 399        smc91x_resources[0].parent = smc91x_res;
 400        smc91x_resources[1].parent = smc91x_res;
 401        smc91x_resources[2].start = d->irq_base + NEP_IRQ_SMC91X;
 402        smc91x_resources[2].end = d->irq_base + NEP_IRQ_SMC91X;
 403        d->smc91x = platform_device_register_full(&smc91x_devinfo);
 404
 405        platform_set_drvdata(dev, d);
 406
 407        return 0;
 408
 409 err_irq_alloc:
 410 err_id:
 411        iounmap(d->base);
 412 err_ioremap:
 413        kfree(d);
 414 err_alloc:
 415        return ret;
 416}
 417
 418static int neponset_remove(struct platform_device *dev)
 419{
 420        struct neponset_drvdata *d = platform_get_drvdata(dev);
 421        int irq = platform_get_irq(dev, 0);
 422
 423        if (!IS_ERR(d->sa1111))
 424                platform_device_unregister(d->sa1111);
 425        if (!IS_ERR(d->smc91x))
 426                platform_device_unregister(d->smc91x);
 427        irq_set_chained_handler(irq, NULL);
 428        irq_free_descs(d->irq_base, NEP_IRQ_NR);
 429        nep = NULL;
 430        iounmap(d->base);
 431        kfree(d);
 432
 433        return 0;
 434}
 435
 436#ifdef CONFIG_PM_SLEEP
 437static int neponset_resume(struct device *dev)
 438{
 439        struct neponset_drvdata *d = dev_get_drvdata(dev);
 440        int i, ret = 0;
 441
 442        for (i = 0; i < ARRAY_SIZE(d->gpio); i++) {
 443                ret = gpio_reg_resume(d->gpio[i]);
 444                if (ret)
 445                        break;
 446        }
 447
 448        return ret;
 449}
 450
 451static const struct dev_pm_ops neponset_pm_ops = {
 452        .resume_noirq = neponset_resume,
 453        .restore_noirq = neponset_resume,
 454};
 455#define PM_OPS &neponset_pm_ops
 456#else
 457#define PM_OPS NULL
 458#endif
 459
 460static struct platform_driver neponset_device_driver = {
 461        .probe          = neponset_probe,
 462        .remove         = neponset_remove,
 463        .driver         = {
 464                .name   = "neponset",
 465                .pm     = PM_OPS,
 466        },
 467};
 468
 469static int __init neponset_init(void)
 470{
 471        return platform_driver_register(&neponset_device_driver);
 472}
 473
 474subsys_initcall(neponset_init);
 475