aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c52
-rw-r--r--arch/arm/mach-omap1/include/mach/board-ams-delta.h7
2 files changed, 35 insertions, 24 deletions
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 4ff3551d93d3..fda402c837d9 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -321,20 +321,6 @@ struct modem_private_data {
321 321
322static struct modem_private_data modem_priv; 322static struct modem_private_data modem_priv;
323 323
324void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value)
325{
326 int bit = 0;
327 u16 bitpos = 1 << bit;
328
329 for (; bit < ngpio; bit++, bitpos = bitpos << 1) {
330 if (!(mask & bitpos))
331 continue;
332 else
333 gpio_set_value(base + bit, (value & bitpos) != 0);
334 }
335}
336EXPORT_SYMBOL(ams_delta_latch_write);
337
338static struct resource ams_delta_nand_resources[] = { 324static struct resource ams_delta_nand_resources[] = {
339 [0] = { 325 [0] = {
340 .start = OMAP1_MPUIO_BASE, 326 .start = OMAP1_MPUIO_BASE,
@@ -680,6 +666,40 @@ static void __init omap_gpio_deps_init(void)
680 modem_assign_irq(chip); 666 modem_assign_irq(chip);
681} 667}
682 668
669/*
670 * Initialize latch2 pins with values which are safe for dependent on-board
671 * devices or useful for their successull initialization even before GPIO
672 * driver takes control over the latch pins:
673 * - LATCH2_PIN_LCD_VBLEN = 0
674 * - LATCH2_PIN_LCD_NDISP = 0 Keep LCD device powered off before its
675 * driver takes control over it.
676 * - LATCH2_PIN_NAND_NCE = 0
677 * - LATCH2_PIN_NAND_NWP = 0 Keep NAND device down and write-
678 * protected before its driver takes
679 * control over it.
680 * - LATCH2_PIN_KEYBRD_PWR = 0 Keep keyboard powered off before serio
681 * driver takes control over it.
682 * - LATCH2_PIN_KEYBRD_DATAOUT = 0 Keep low to avoid corruption of first
683 * byte of data received from attached
684 * keyboard when serio device is probed;
685 * the pin is also hogged low by the latch2
686 * GPIO driver as soon as it is ready.
687 * - LATCH2_PIN_MODEM_NRESET = 1 Enable voice MODEM device, allowing for
688 * its successful probe even before a
689 * regulator it depends on, which in turn
690 * takes control over the pin, is set up.
691 * - LATCH2_PIN_MODEM_CODEC = 1 Attach voice MODEM CODEC data port
692 * to the MODEM so the CODEC is under
693 * control even if audio driver doesn't
694 * take it over.
695 */
696static void __init ams_delta_latch2_init(void)
697{
698 u16 latch2 = 1 << LATCH2_PIN_MODEM_NRESET | 1 << LATCH2_PIN_MODEM_CODEC;
699
700 __raw_writew(latch2, LATCH2_VIRT);
701}
702
683static void __init ams_delta_init(void) 703static void __init ams_delta_init(void)
684{ 704{
685 /* mux pins for uarts */ 705 /* mux pins for uarts */
@@ -701,6 +721,7 @@ static void __init ams_delta_init(void)
701 omap_cfg_reg(J18_1610_CAM_D7); 721 omap_cfg_reg(J18_1610_CAM_D7);
702 722
703 omap_gpio_deps_init(); 723 omap_gpio_deps_init();
724 ams_delta_latch2_init();
704 gpiod_add_hogs(ams_delta_gpio_hogs); 725 gpiod_add_hogs(ams_delta_gpio_hogs);
705 726
706 omap_serial_init(); 727 omap_serial_init();
@@ -888,9 +909,6 @@ static int __init ams_delta_modem_init(void)
888 /* Initialize the modem_nreset regulator consumer before use */ 909 /* Initialize the modem_nreset regulator consumer before use */
889 modem_priv.regulator = ERR_PTR(-ENODEV); 910 modem_priv.regulator = ERR_PTR(-ENODEV);
890 911
891 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
892 AMS_DELTA_LATCH2_MODEM_CODEC);
893
894 err = platform_device_register(&ams_delta_modem_device); 912 err = platform_device_register(&ams_delta_modem_device);
895 913
896 return err; 914 return err;
diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h b/arch/arm/mach-omap1/include/mach/board-ams-delta.h
index ad6f865d1f16..3b2d8019238a 100644
--- a/arch/arm/mach-omap1/include/mach/board-ams-delta.h
+++ b/arch/arm/mach-omap1/include/mach/board-ams-delta.h
@@ -59,13 +59,6 @@
59#define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN 59#define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN
60#define AMS_DELTA_LATCH2_NGPIO 16 60#define AMS_DELTA_LATCH2_NGPIO 16
61 61
62#ifndef __ASSEMBLY__
63void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value);
64#define ams_delta_latch2_write(mask, value) \
65 ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \
66 AMS_DELTA_LATCH2_NGPIO, (mask), (value))
67#endif
68
69#endif /* CONFIG_MACH_AMS_DELTA */ 62#endif /* CONFIG_MACH_AMS_DELTA */
70 63
71#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */ 64#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
lter_Interval 0x08 #define Change_Status 0x02 #define MasterInterruptStatus 0x04 #define Overflow 0x02 #define EdgeStatus 0x01 #define Master_Interrupt_Control 0x03 #define FallingEdgeIntEnable 0x10 #define RisingEdgeIntEnable 0x08 #define MasterInterruptEnable 0x04 #define OverflowIntEnable 0x02 #define EdgeIntEnable 0x01 static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it); static int ni_65xx_detach(struct comedi_device * dev); static struct comedi_driver driver_ni_65xx = { driver_name:"ni_65xx", module:THIS_MODULE, attach:ni_65xx_attach, detach:ni_65xx_detach, }; typedef struct { int dev_id; const char *name; unsigned num_dio_ports; unsigned num_di_ports; unsigned num_do_ports; unsigned invert_outputs:1; } ni_65xx_board; static const ni_65xx_board ni_65xx_boards[] = { { dev_id: 0x7085, name: "pci-6509", num_dio_ports:12, invert_outputs:0}, { dev_id: 0x1710, name: "pxi-6509", num_dio_ports:12, invert_outputs:0}, { dev_id: 0x7124, name: "pci-6510", num_di_ports:4}, { dev_id: 0x70c3, name: "pci-6511", num_di_ports:8}, { dev_id: 0x70d3, name: "pxi-6511", num_di_ports:8}, { dev_id: 0x70cc, name: "pci-6512", num_do_ports:8}, { dev_id: 0x70d2, name: "pxi-6512", num_do_ports:8}, { dev_id: 0x70c8, name: "pci-6513", num_do_ports:8, invert_outputs:1}, { dev_id: 0x70d1, name: "pxi-6513", num_do_ports:8, invert_outputs:1}, { dev_id: 0x7088, name: "pci-6514", num_di_ports:4, num_do_ports:4, invert_outputs:1}, { dev_id: 0x70CD, name: "pxi-6514", num_di_ports:4, num_do_ports:4, invert_outputs:1}, { dev_id: 0x7087, name: "pci-6515", num_di_ports:4, num_do_ports:4, invert_outputs:1}, { dev_id: 0x70c9, name: "pxi-6515", num_di_ports:4, num_do_ports:4, invert_outputs:1}, { dev_id: 0x7125, name: "pci-6516", num_do_ports:4, invert_outputs:1}, { dev_id: 0x7126, name: "pci-6517", num_do_ports:4, invert_outputs:1}, { dev_id: 0x7127, name: "pci-6518", num_di_ports:2, num_do_ports:2, invert_outputs:1}, { dev_id: 0x7128, name: "pci-6519", num_di_ports:2, num_do_ports:2, invert_outputs:1}, { dev_id: 0x71c5, name: "pci-6520", num_di_ports:1, num_do_ports:1, }, { dev_id: 0x718b, name: "pci-6521", num_di_ports:1, num_do_ports:1, }, { dev_id: 0x718c, name: "pxi-6521", num_di_ports:1, num_do_ports:1, }, { dev_id: 0x70a9, name: "pci-6528", num_di_ports:3, num_do_ports:3, }, { dev_id: 0x7086, name: "pxi-6528", num_di_ports:3, num_do_ports:3, }, }; #define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0])) static inline const ni_65xx_board *board(struct comedi_device * dev) { return dev->board_ptr; } static inline unsigned ni_65xx_port_by_channel(unsigned channel) { return channel / ni_65xx_channels_per_port; } static inline unsigned ni_65xx_total_num_ports(const ni_65xx_board * board) { return board->num_dio_ports + board->num_di_ports + board->num_do_ports; } static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = { {PCI_VENDOR_ID_NATINST, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7085, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7086, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7087, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7088, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70a9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x70d3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7126, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7127, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x7128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x718b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x718c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NATINST, 0x71c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0} }; MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table); typedef struct { struct mite_struct *mite; unsigned int filter_interval; unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS]; unsigned short output_bits[NI_65XX_MAX_NUM_PORTS]; unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS]; } ni_65xx_private; static inline ni_65xx_private *private(struct comedi_device * dev) { return dev->private; } typedef struct { unsigned base_port; } ni_65xx_subdevice_private; static inline ni_65xx_subdevice_private *sprivate(struct comedi_subdevice * subdev) { return subdev->private; } static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void) { ni_65xx_subdevice_private *subdev_private = kzalloc(sizeof(ni_65xx_subdevice_private), GFP_KERNEL); if (subdev_private == NULL) return NULL; return subdev_private; } static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot); static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { const unsigned chan = CR_CHAN(insn->chanspec); const unsigned port = sprivate(s)->base_port + ni_65xx_port_by_channel(chan); if (data[0] != INSN_CONFIG_FILTER) return -EINVAL; if (data[1]) { static const unsigned filter_resolution_ns = 200; static const unsigned max_filter_interval = 0xfffff; unsigned interval = (data[1] + (filter_resolution_ns / 2)) / filter_resolution_ns; if (interval > max_filter_interval) interval = max_filter_interval; data[1] = interval * filter_resolution_ns; if (interval != private(dev)->filter_interval) { writeb(interval, private(dev)->mite->daq_io_addr + Filter_Interval); private(dev)->filter_interval = interval; } private(dev)->filter_enable[port] |= 1 << (chan % ni_65xx_channels_per_port); } else { private(dev)->filter_enable[port] &= ~(1 << (chan % ni_65xx_channels_per_port)); } writeb(private(dev)->filter_enable[port], private(dev)->mite->daq_io_addr + Filter_Enable(port)); return 2; } static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { unsigned port; if (insn->n < 1) return -EINVAL; port = sprivate(s)->base_port + ni_65xx_port_by_channel(CR_CHAN(insn->chanspec)); switch (data[0]) { case INSN_CONFIG_FILTER: return ni_65xx_config_filter(dev, s, insn, data); break; case INSN_CONFIG_DIO_OUTPUT: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; private(dev)->dio_direction[port] = COMEDI_OUTPUT; writeb(0, private(dev)->mite->daq_io_addr + Port_Select(port)); return 1; break; case INSN_CONFIG_DIO_INPUT: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; private(dev)->dio_direction[port] = COMEDI_INPUT; writeb(1, private(dev)->mite->daq_io_addr + Port_Select(port)); return 1; break; case INSN_CONFIG_DIO_QUERY: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; data[1] = private(dev)->dio_direction[port]; return insn->n; break; default: break; } return -EINVAL; } static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { unsigned base_bitfield_channel; const unsigned max_ports_per_bitfield = 5; unsigned read_bits = 0; unsigned j; if (insn->n != 2) return -EINVAL; base_bitfield_channel = CR_CHAN(insn->chanspec); for (j = 0; j < max_ports_per_bitfield; ++j) { const unsigned port = sprivate(s)->base_port + ni_65xx_port_by_channel(base_bitfield_channel) + j; unsigned base_port_channel; unsigned port_mask, port_data, port_read_bits; int bitshift; if (port >= ni_65xx_total_num_ports(board(dev))) break; base_port_channel = port * ni_65xx_channels_per_port; port_mask = data[0]; port_data = data[1]; bitshift = base_port_channel - base_bitfield_channel; if (bitshift >= 32 || bitshift <= -32) break; if (bitshift > 0) { port_mask >>= bitshift; port_data >>= bitshift; } else { port_mask <<= -bitshift; port_data <<= -bitshift; } port_mask &= 0xff; port_data &= 0xff; if (port_mask) { unsigned bits; private(dev)->output_bits[port] &= ~port_mask; private(dev)->output_bits[port] |= port_data & port_mask; bits = private(dev)->output_bits[port]; if (board(dev)->invert_outputs) bits = ~bits; writeb(bits, private(dev)->mite->daq_io_addr + Port_Data(port)); // rt_printk("wrote 0x%x to port %i\n", bits, port); } port_read_bits = readb(private(dev)->mite->daq_io_addr + Port_Data(port)); // rt_printk("read 0x%x from port %i\n", port_read_bits, port); if (bitshift > 0) { port_read_bits <<= bitshift; } else { port_read_bits >>= -bitshift; } read_bits |= port_read_bits; } data[1] = read_bits; return insn->n; } static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices + 2; unsigned int status; status = readb(private(dev)->mite->daq_io_addr + Change_Status); if ((status & MasterInterruptStatus) == 0) return IRQ_NONE; if ((status & EdgeStatus) == 0) return IRQ_NONE; writeb(ClrEdge | ClrOverflow, private(dev)->mite->daq_io_addr + Clear_Register); comedi_buf_put(s->async, 0); s->async->events |= COMEDI_CB_EOS; comedi_event(dev, s); return IRQ_HANDLED; } static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd) { int err = 0; int tmp; /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_NOW; if (!cmd->start_src || tmp != cmd->start_src) err++; tmp = cmd->scan_begin_src; cmd->scan_begin_src &= TRIG_OTHER; if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++; tmp = cmd->convert_src; cmd->convert_src &= TRIG_FOLLOW; if (!cmd->convert_src || tmp != cmd->convert_src) err++; tmp = cmd->scan_end_src; cmd->scan_end_src &= TRIG_COUNT; if (!cmd->scan_end_src || tmp != cmd->scan_end_src) err++; tmp = cmd->stop_src; cmd->stop_src &= TRIG_COUNT; if (!cmd->stop_src || tmp != cmd->stop_src) err++; if (err) return 1; /* step 2: make sure trigger sources are unique and mutually compatible */ if (err) return 2; /* step 3: make sure arguments are trivially compatible */ if (cmd->start_arg != 0) { cmd->start_arg = 0; err++; } if (cmd->scan_begin_arg != 0) { cmd->scan_begin_arg = 0; err++; } if (cmd->convert_arg != 0) { cmd->convert_arg = 0; err++; } if (cmd->scan_end_arg != 1) { cmd->scan_end_arg = 1; err++; } if (cmd->stop_arg != 0) { cmd->stop_arg = 0; err++; } if (err) return 3; /* step 4: fix up any arguments */ if (err) return 4; return 0; } static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s) { //struct comedi_cmd *cmd = &s->async->cmd; writeb(ClrEdge | ClrOverflow, private(dev)->mite->daq_io_addr + Clear_Register); writeb(FallingEdgeIntEnable | RisingEdgeIntEnable | MasterInterruptEnable | EdgeIntEnable, private(dev)->mite->daq_io_addr + Master_Interrupt_Control); return 0; } static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s) { writeb(0x00, private(dev)->mite->daq_io_addr + Master_Interrupt_Control); return 0; } static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { if (insn->n < 1) return -EINVAL; data[1] = 0; return 2; } static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { if (insn->n < 1) return -EINVAL; if (data[0] != INSN_CONFIG_CHANGE_NOTIFY) return -EINVAL; writeb(data[1], private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0)); writeb(data[1] >> 8, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x10)); writeb(data[1] >> 16, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x20)); writeb(data[1] >> 24, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x30)); writeb(data[2], private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0)); writeb(data[2] >> 8, private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x10)); writeb(data[2] >> 16,