0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/delay.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/io.h>
0015 #include <linux/gpio/driver.h>
0016 #include <linux/slab.h>
0017 #include <linux/bitops.h>
0018
0019 #include <linux/mfd/janz.h>
0020
0021 #define DRV_NAME "janz-ttl"
0022
0023 #define PORTA_DIRECTION 0x23
0024 #define PORTB_DIRECTION 0x2B
0025 #define PORTC_DIRECTION 0x06
0026 #define PORTA_IOCTL 0x24
0027 #define PORTB_IOCTL 0x2C
0028 #define PORTC_IOCTL 0x07
0029
0030 #define MASTER_INT_CTL 0x00
0031 #define MASTER_CONF_CTL 0x01
0032
0033 #define CONF_PAE BIT(2)
0034 #define CONF_PBE BIT(7)
0035 #define CONF_PCE BIT(4)
0036
0037 struct ttl_control_regs {
0038 __be16 portc;
0039 __be16 portb;
0040 __be16 porta;
0041 __be16 control;
0042 };
0043
0044 struct ttl_module {
0045 struct gpio_chip gpio;
0046
0047
0048 struct ttl_control_regs __iomem *regs;
0049
0050 u8 portc_shadow;
0051 u8 portb_shadow;
0052 u8 porta_shadow;
0053
0054 spinlock_t lock;
0055 };
0056
0057 static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
0058 {
0059 struct ttl_module *mod = dev_get_drvdata(gpio->parent);
0060 u8 *shadow;
0061 int ret;
0062
0063 if (offset < 8) {
0064 shadow = &mod->porta_shadow;
0065 } else if (offset < 16) {
0066 shadow = &mod->portb_shadow;
0067 offset -= 8;
0068 } else {
0069 shadow = &mod->portc_shadow;
0070 offset -= 16;
0071 }
0072
0073 spin_lock(&mod->lock);
0074 ret = *shadow & BIT(offset);
0075 spin_unlock(&mod->lock);
0076 return !!ret;
0077 }
0078
0079 static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
0080 {
0081 struct ttl_module *mod = dev_get_drvdata(gpio->parent);
0082 void __iomem *port;
0083 u8 *shadow;
0084
0085 if (offset < 8) {
0086 port = &mod->regs->porta;
0087 shadow = &mod->porta_shadow;
0088 } else if (offset < 16) {
0089 port = &mod->regs->portb;
0090 shadow = &mod->portb_shadow;
0091 offset -= 8;
0092 } else {
0093 port = &mod->regs->portc;
0094 shadow = &mod->portc_shadow;
0095 offset -= 16;
0096 }
0097
0098 spin_lock(&mod->lock);
0099 if (value)
0100 *shadow |= BIT(offset);
0101 else
0102 *shadow &= ~BIT(offset);
0103
0104 iowrite16be(*shadow, port);
0105 spin_unlock(&mod->lock);
0106 }
0107
0108 static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
0109 {
0110 iowrite16be(reg, &mod->regs->control);
0111 iowrite16be(val, &mod->regs->control);
0112 }
0113
0114 static void ttl_setup_device(struct ttl_module *mod)
0115 {
0116
0117 iowrite16be(0x0000, &mod->regs->control);
0118 iowrite16be(0x0001, &mod->regs->control);
0119 iowrite16be(0x0000, &mod->regs->control);
0120
0121
0122 ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
0123 ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
0124 ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
0125
0126
0127 ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
0128 ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
0129 ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
0130
0131
0132 iowrite16be(0x0000, &mod->regs->porta);
0133 iowrite16be(0x0000, &mod->regs->portb);
0134 iowrite16be(0x0000, &mod->regs->portc);
0135
0136
0137 ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
0138 }
0139
0140 static int ttl_probe(struct platform_device *pdev)
0141 {
0142 struct janz_platform_data *pdata;
0143 struct ttl_module *mod;
0144 struct gpio_chip *gpio;
0145 int ret;
0146
0147 pdata = dev_get_platdata(&pdev->dev);
0148 if (!pdata) {
0149 dev_err(&pdev->dev, "no platform data\n");
0150 return -ENXIO;
0151 }
0152
0153 mod = devm_kzalloc(&pdev->dev, sizeof(*mod), GFP_KERNEL);
0154 if (!mod)
0155 return -ENOMEM;
0156
0157 platform_set_drvdata(pdev, mod);
0158 spin_lock_init(&mod->lock);
0159
0160
0161 mod->regs = devm_platform_ioremap_resource(pdev, 0);
0162 if (IS_ERR(mod->regs))
0163 return PTR_ERR(mod->regs);
0164
0165 ttl_setup_device(mod);
0166
0167
0168 gpio = &mod->gpio;
0169 gpio->parent = &pdev->dev;
0170 gpio->label = pdev->name;
0171 gpio->get = ttl_get_value;
0172 gpio->set = ttl_set_value;
0173 gpio->owner = THIS_MODULE;
0174
0175
0176 gpio->base = -1;
0177 gpio->ngpio = 20;
0178
0179 ret = devm_gpiochip_add_data(&pdev->dev, gpio, NULL);
0180 if (ret) {
0181 dev_err(&pdev->dev, "unable to add GPIO chip\n");
0182 return ret;
0183 }
0184
0185 return 0;
0186 }
0187
0188 static struct platform_driver ttl_driver = {
0189 .driver = {
0190 .name = DRV_NAME,
0191 },
0192 .probe = ttl_probe,
0193 };
0194
0195 module_platform_driver(ttl_driver);
0196
0197 MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
0198 MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
0199 MODULE_LICENSE("GPL");
0200 MODULE_ALIAS("platform:janz-ttl");