From 8d9903666100782c67ed05cfacc604838de422bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Jul 2012 10:28:33 -0700 Subject: [PATCH] --- yaml --- r: 318029 b: refs/heads/master c: 8405f041adfeabb137d81a624b70ff35a803c53c h: refs/heads/master i: 318027: 5b12d06dc7235cf20895d0666b15d6b069624efe v: v3 --- [refs] | 2 +- trunk/Documentation/ramoops.txt | 25 + trunk/drivers/staging/Kconfig | 2 + trunk/drivers/staging/Makefile | 1 + .../comedi/drivers/addi-data/addi_common.c | 23 - .../comedi/drivers/addi-data/addi_common.h | 1 - .../comedi/drivers/addi-data/hwdrv_apci16xx.h | 15 - .../comedi/drivers/addi-data/hwdrv_apci3xxx.h | 14 - trunk/drivers/staging/comedi/drivers/dt282x.c | 55 +- trunk/drivers/staging/comedi/drivers/rtd520.c | 565 ++++---- trunk/drivers/staging/et131x/et131x.c | 8 +- .../staging/ft1000/ft1000-usb/ft1000_usb.c | 6 +- .../staging/ft1000/ft1000-usb/ft1000_usb.h | 177 +-- trunk/drivers/staging/gdm72xx/gdm_qos.c | 5 +- trunk/drivers/staging/gdm72xx/gdm_sdio.c | 7 +- trunk/drivers/staging/gdm72xx/gdm_usb.c | 7 +- trunk/drivers/staging/gdm72xx/gdm_wimax.c | 8 +- trunk/drivers/staging/gdm72xx/usb_boot.c | 2 +- trunk/drivers/staging/ipack/devices/ipoctal.c | 18 +- trunk/drivers/staging/omap-thermal/Kconfig | 46 + trunk/drivers/staging/omap-thermal/Makefile | 5 + trunk/drivers/staging/omap-thermal/TODO | 28 + .../staging/omap-thermal/omap-bandgap.c | 1187 +++++++++++++++++ .../staging/omap-thermal/omap-bandgap.h | 441 ++++++ .../omap-thermal/omap-thermal-common.c | 364 +++++ .../staging/omap-thermal/omap-thermal.h | 108 ++ .../staging/omap-thermal/omap4-thermal.c | 259 ++++ .../staging/omap-thermal/omap5-thermal.c | 297 +++++ .../staging/omap-thermal/omap_bandgap.txt | 30 + trunk/drivers/staging/panel/panel.c | 60 +- trunk/drivers/staging/rts_pstor/rtsx.c | 4 +- trunk/drivers/staging/sm7xxfb/Kconfig | 2 +- trunk/drivers/staging/sm7xxfb/sm7xxfb.c | 374 +++--- .../staging/ste_rmi4/synaptics_i2c_rmi4.c | 8 +- trunk/drivers/staging/vt6656/wcmd.c | 85 +- trunk/drivers/staging/winbond/wbusb.c | 8 +- trunk/drivers/staging/wlags49_h2/dhf.c | 1 - trunk/drivers/staging/wlags49_h2/dhf.h | 1 - trunk/drivers/staging/wlags49_h2/hcf.h | 1 - trunk/drivers/staging/wlags49_h2/hcfcfg.h | 1 - trunk/drivers/staging/wlags49_h2/mdd.h | 1 - trunk/drivers/staging/wlags49_h2/mmd.c | 1 - trunk/drivers/staging/wlags49_h2/mmd.h | 1 - trunk/drivers/staging/wlan-ng/prism2sta.c | 8 +- trunk/fs/pstore/Kconfig | 12 + trunk/fs/pstore/Makefile | 1 + trunk/fs/pstore/ftrace.c | 35 + trunk/fs/pstore/inode.c | 111 +- trunk/fs/pstore/internal.h | 43 + trunk/fs/pstore/platform.c | 12 +- trunk/fs/pstore/ram.c | 76 +- trunk/fs/pstore/ram_core.c | 30 +- trunk/include/linux/pstore.h | 13 + trunk/include/linux/pstore_ram.h | 8 +- trunk/kernel/trace/trace.c | 7 +- trunk/kernel/trace/trace_functions.c | 36 +- 56 files changed, 3752 insertions(+), 894 deletions(-) create mode 100644 trunk/drivers/staging/omap-thermal/Kconfig create mode 100644 trunk/drivers/staging/omap-thermal/Makefile create mode 100644 trunk/drivers/staging/omap-thermal/TODO create mode 100644 trunk/drivers/staging/omap-thermal/omap-bandgap.c create mode 100644 trunk/drivers/staging/omap-thermal/omap-bandgap.h create mode 100644 trunk/drivers/staging/omap-thermal/omap-thermal-common.c create mode 100644 trunk/drivers/staging/omap-thermal/omap-thermal.h create mode 100644 trunk/drivers/staging/omap-thermal/omap4-thermal.c create mode 100644 trunk/drivers/staging/omap-thermal/omap5-thermal.c create mode 100644 trunk/drivers/staging/omap-thermal/omap_bandgap.txt create mode 100644 trunk/fs/pstore/ftrace.c diff --git a/[refs] b/[refs] index ab3cee64f960..5d82d34fe516 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dcbc3c414e62faa4e1a1e17421f89eceea6bee30 +refs/heads/master: 8405f041adfeabb137d81a624b70ff35a803c53c diff --git a/trunk/Documentation/ramoops.txt b/trunk/Documentation/ramoops.txt index 59a74a8ee2e5..197ad59ab9bf 100644 --- a/trunk/Documentation/ramoops.txt +++ b/trunk/Documentation/ramoops.txt @@ -94,3 +94,28 @@ timestamp and a new line. The dump then continues with the actual data. The dump data can be read from the pstore filesystem. The format for these files is "dmesg-ramoops-N", where N is the record number in memory. To delete a stored record from RAM, simply unlink the respective pstore file. + +5. Persistent function tracing + +Persistent function tracing might be useful for debugging software or hardware +related hangs. The functions call chain log is stored in a "ftrace-ramoops" +file. Here is an example of usage: + + # mount -t debugfs debugfs /sys/kernel/debug/ + # cd /sys/kernel/debug/tracing + # echo function > current_tracer + # echo 1 > options/func_pstore + # reboot -f + [...] + # mount -t pstore pstore /mnt/ + # tail /mnt/ftrace-ramoops + 0 ffffffff8101ea64 ffffffff8101bcda native_apic_mem_read <- disconnect_bsp_APIC+0x6a/0xc0 + 0 ffffffff8101ea44 ffffffff8101bcf6 native_apic_mem_write <- disconnect_bsp_APIC+0x86/0xc0 + 0 ffffffff81020084 ffffffff8101a4b5 hpet_disable <- native_machine_shutdown+0x75/0x90 + 0 ffffffff81005f94 ffffffff8101a4bb iommu_shutdown_noop <- native_machine_shutdown+0x7b/0x90 + 0 ffffffff8101a6a1 ffffffff8101a437 native_machine_emergency_restart <- native_machine_restart+0x37/0x40 + 0 ffffffff811f9876 ffffffff8101a73a acpi_reboot <- native_machine_emergency_restart+0xaa/0x1e0 + 0 ffffffff8101a514 ffffffff8101a772 mach_reboot_fixups <- native_machine_emergency_restart+0xe2/0x1e0 + 0 ffffffff811d9c54 ffffffff8101a7a0 __const_udelay <- native_machine_emergency_restart+0x110/0x1e0 + 0 ffffffff811d9c34 ffffffff811d9c80 __delay <- __const_udelay+0x30/0x40 + 0 ffffffff811d9d14 ffffffff811d9c3f delay_tsc <- __delay+0xf/0x20 diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index d3934d79524a..e3402d5644dd 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -134,4 +134,6 @@ source "drivers/staging/gdm72xx/Kconfig" source "drivers/staging/csr/Kconfig" +source "drivers/staging/omap-thermal/Kconfig" + endif # STAGING diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index 5b2219ac5207..3be59d02cae4 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_USB_G_CCG) += ccg/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ obj-$(CONFIG_CSR_WIFI) += csr/ +obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal/ diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c index a5aa673335ef..a3d4ed25fb0d 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -613,7 +613,6 @@ static const struct addi_board boardtypes[] = { .i_IorangeBase0 = 128, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .i_NbrTTLChannel = 48, - .pr_TTLRangelist = &range_apci16xx_ttl, .reset = i_APCI16XX_Reset, .ttl_config = i_APCI16XX_InsnConfigInitTTLIO, .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO, @@ -626,7 +625,6 @@ static const struct addi_board boardtypes[] = { .i_IorangeBase0 = 128, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .i_NbrTTLChannel = 96, - .pr_TTLRangelist = &range_apci16xx_ttl, .reset = i_APCI16XX_Reset, .ttl_config = i_APCI16XX_InsnConfigInitTTLIO, .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO, @@ -651,7 +649,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 4095, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -678,7 +675,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 4095, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -705,7 +701,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 4095, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -732,7 +727,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 65535, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -759,7 +753,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 65535, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -786,7 +779,6 @@ static const struct addi_board boardtypes[] = { .i_AiMaxdata = 65535, .pr_AiRangelist = &range_apci3XXX_ai, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -816,7 +808,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -851,7 +842,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -886,7 +876,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -921,7 +910,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -956,7 +944,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -991,7 +978,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -1026,7 +1012,6 @@ static const struct addi_board boardtypes[] = { .pr_AiRangelist = &range_apci3XXX_ai, .pr_AoRangelist = &range_apci3XXX_ao, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -1057,7 +1042,6 @@ static const struct addi_board boardtypes[] = { .pr_AiRangelist = &range_apci3XXX_ai, .pr_AoRangelist = &range_apci3XXX_ao, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -1088,7 +1072,6 @@ static const struct addi_board boardtypes[] = { .pr_AiRangelist = &range_apci3XXX_ai, .pr_AoRangelist = &range_apci3XXX_ao, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -1119,7 +1102,6 @@ static const struct addi_board boardtypes[] = { .pr_AiRangelist = &range_apci3XXX_ai, .pr_AoRangelist = &range_apci3XXX_ao, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 10000, .interrupt = v_APCI3XXX_Interrupt, @@ -1153,7 +1135,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -1192,7 +1173,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -1231,7 +1211,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -1270,7 +1249,6 @@ static const struct addi_board boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 1, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .b_AvailableConvertUnit = 6, .ui_MinAcquisitiontimeNs = 5000, .interrupt = v_APCI3XXX_Interrupt, @@ -1413,7 +1391,6 @@ static const struct addi_board boardtypes[] = { .i_AoMaxdata = 4095, .pr_AoRangelist = &range_apci3XXX_ao, .i_NbrTTLChannel = 24, - .pr_TTLRangelist = &range_apci3XXX_ttl, .interrupt = v_APCI3XXX_Interrupt, .reset = i_APCI3XXX_Reset, .ao_write = i_APCI3XXX_InsnWriteAnalogOutput, diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.h b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.h index 2c3f34703dd2..b7bbb7164f58 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -85,7 +85,6 @@ struct addi_board { int i_DoMaxdata; /* data to set all channels high */ int i_NbrTTLChannel; /* Number of TTL channels */ - const struct comedi_lrange *pr_TTLRangelist; /* rangelist for TTL */ int i_Dma; /* dma present or not */ int i_Timer; /* timer subdevice present or not */ diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h index 5bf91e13a035..a12df4bc88ac 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h @@ -41,21 +41,6 @@ #ifdef __KERNEL__ -static const struct comedi_lrange range_apci16xx_ttl = { 12, - {BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1)} -}; - /* +----------------------------------------------------------------------------+ | TTL INISIALISATION FUNCTION | diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h index cce9e12e820f..e10b7e510335 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h @@ -42,20 +42,6 @@ static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10), UNI_RANGE(1)} }; -static const struct comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1), - BIP_RANGE(1)} -}; - static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10), UNI_RANGE(10)} }; diff --git a/trunk/drivers/staging/comedi/drivers/dt282x.c b/trunk/drivers/staging/comedi/drivers/dt282x.c index 4af33431c380..1f0b40e4bddd 100644 --- a/trunk/drivers/staging/comedi/drivers/dt282x.c +++ b/trunk/drivers/staging/comedi/drivers/dt282x.c @@ -255,11 +255,8 @@ struct dt282x_private { * Some useless abstractions */ #define chan_to_DAC(a) ((a)&1) -#define update_dacsr(a) outw(devpriv->dacsr|(a), dev->iobase+DT2821_DACSR) -#define update_adcsr(a) outw(devpriv->adcsr|(a), dev->iobase+DT2821_ADCSR) #define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY) #define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE) -#define update_supcsr(a) outw(devpriv->supcsr|(a), dev->iobase+DT2821_SUPCSR) /* * danger! macro abuse... a is the expression to wait on, and b is @@ -317,7 +314,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev) int i; struct comedi_subdevice *s = dev->subdevices + 1; - update_supcsr(DT2821_CLRDMADNE); + outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); if (!s->async->prealloc_buf) { printk(KERN_ERR "async->data disappeared. dang!\n"); @@ -350,7 +347,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) int ret; struct comedi_subdevice *s = dev->subdevices; - update_supcsr(DT2821_CLRDMADNE); + outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); if (!s->async->prealloc_buf) { printk(KERN_ERR "async->data disappeared. dang!\n"); @@ -387,7 +384,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) /* XXX probably wrong */ if (!devpriv->ntrig) { devpriv->supcsr &= ~(DT2821_DDMA); - update_supcsr(0); + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); } #endif /* restart the channel */ @@ -513,7 +510,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) s->async->events |= COMEDI_CB_EOA; } else { if (supcsr & DT2821_SCDN) - update_supcsr(DT2821_STRIG); + outw(devpriv->supcsr | DT2821_STRIG, + dev->iobase + DT2821_SUPCSR); } handled = 1; } @@ -534,7 +532,8 @@ static void dt282x_load_changain(struct comedi_device *dev, int n, for (i = 0; i < n; i++) { chan = CR_CHAN(chanlist[i]); range = CR_RANGE(chanlist[i]); - update_adcsr((range << 4) | (chan)); + outw(devpriv->adcsr | (range << 4) | chan, + dev->iobase + DT2821_ADCSR); } outw(n - 1, dev->iobase + DT2821_CHANCSR); } @@ -553,15 +552,16 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, /* XXX should we really be enabling the ad clock here? */ devpriv->adcsr = DT2821_ADCLK; - update_adcsr(0); + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); dt282x_load_changain(dev, 1, &insn->chanspec); - update_supcsr(DT2821_PRLD); + outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); for (i = 0; i < insn->n; i++) { - update_supcsr(DT2821_STRIG); + outw(devpriv->supcsr | DT2821_STRIG, + dev->iobase + DT2821_SUPCSR); wait_for(ad_done(), comedi_error(dev, "timeout\n"); return -ETIME;); @@ -718,7 +718,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* external trigger */ devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1; } - update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT); + outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT, + dev->iobase + DT2821_SUPCSR); devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; devpriv->nread = devpriv->ntrig; @@ -729,7 +730,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (devpriv->ntrig) { prep_ai_dma(dev, 1, 0); devpriv->supcsr |= DT2821_DDMA; - update_supcsr(0); + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); } devpriv->adcsr = 0; @@ -737,16 +738,17 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist); devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE; - update_adcsr(0); + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); - update_supcsr(DT2821_PRLD); + outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); if (cmd->scan_begin_src == TRIG_FOLLOW) { - update_supcsr(DT2821_STRIG); + outw(devpriv->supcsr | DT2821_STRIG, + dev->iobase + DT2821_SUPCSR); } else { devpriv->supcsr |= DT2821_XTRIG; - update_supcsr(0); + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); } return 0; @@ -766,10 +768,10 @@ static int dt282x_ai_cancel(struct comedi_device *dev, dt282x_disable_dma(dev); devpriv->adcsr = 0; - update_adcsr(0); + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); devpriv->supcsr = 0; - update_supcsr(DT2821_ADCINIT); + outw(devpriv->supcsr | DT2821_ADCINIT, dev->iobase + DT2821_SUPCSR); return 0; } @@ -845,11 +847,11 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, d ^= (1 << (boardtype.dabits - 1)); } - update_dacsr(0); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); outw(d, dev->iobase + DT2821_DADAT); - update_supcsr(DT2821_DACON); + outw(devpriv->supcsr | DT2821_DACON, dev->iobase + DT2821_SUPCSR); return 1; } @@ -972,7 +974,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, } prep_ao_dma(dev, 1, size); - update_supcsr(DT2821_STRIG); + outw(devpriv->supcsr | DT2821_STRIG, dev->iobase + DT2821_SUPCSR); s->async->inttrig = NULL; return 1; @@ -993,7 +995,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dt282x_disable_dma(dev); devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA; - update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT); + outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT, + dev->iobase + DT2821_SUPCSR); devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; devpriv->nread = devpriv->ntrig; @@ -1005,7 +1008,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outw(timer, dev->iobase + DT2821_TMRCTR); devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY; - update_dacsr(0); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); s->async->inttrig = dt282x_ao_inttrig; @@ -1018,10 +1021,10 @@ static int dt282x_ao_cancel(struct comedi_device *dev, dt282x_disable_dma(dev); devpriv->dacsr = 0; - update_dacsr(0); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); devpriv->supcsr = 0; - update_supcsr(DT2821_DACINIT); + outw(devpriv->supcsr | DT2821_DACINIT, dev->iobase + DT2821_SUPCSR); return 0; } diff --git a/trunk/drivers/staging/comedi/drivers/rtd520.c b/trunk/drivers/staging/comedi/drivers/rtd520.c index e3a6aa26e858..9998d6b25d2e 100644 --- a/trunk/drivers/staging/comedi/drivers/rtd520.c +++ b/trunk/drivers/staging/comedi/drivers/rtd520.c @@ -194,110 +194,79 @@ Configuration options: ======================================================================*/ /* - The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128) -*/ -static const struct comedi_lrange rtd_ai_7520_range = { 18, { - /* +-5V input range gain steps */ - BIP_RANGE(5.0), - BIP_RANGE(5.0 / 2), - BIP_RANGE(5.0 / 4), - BIP_RANGE(5.0 / 8), - BIP_RANGE(5.0 / - 16), - BIP_RANGE(5.0 / - 32), - /* +-10V input range gain steps */ - BIP_RANGE(10.0), - BIP_RANGE(10.0 / - 2), - BIP_RANGE(10.0 / - 4), - BIP_RANGE(10.0 / - 8), - BIP_RANGE(10.0 / - 16), - BIP_RANGE(10.0 / - 32), - /* +10V input range gain steps */ - UNI_RANGE(10.0), - UNI_RANGE(10.0 / - 2), - UNI_RANGE(10.0 / - 4), - UNI_RANGE(10.0 / - 8), - UNI_RANGE(10.0 / - 16), - UNI_RANGE(10.0 / - 32), - - } + * The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128) + */ +static const struct comedi_lrange rtd_ai_7520_range = { + 18, { + /* +-5V input range gain steps */ + BIP_RANGE(5.0), + BIP_RANGE(5.0 / 2), + BIP_RANGE(5.0 / 4), + BIP_RANGE(5.0 / 8), + BIP_RANGE(5.0 / 16), + BIP_RANGE(5.0 / 32), + /* +-10V input range gain steps */ + BIP_RANGE(10.0), + BIP_RANGE(10.0 / 2), + BIP_RANGE(10.0 / 4), + BIP_RANGE(10.0 / 8), + BIP_RANGE(10.0 / 16), + BIP_RANGE(10.0 / 32), + /* +10V input range gain steps */ + UNI_RANGE(10.0), + UNI_RANGE(10.0 / 2), + UNI_RANGE(10.0 / 4), + UNI_RANGE(10.0 / 8), + UNI_RANGE(10.0 / 16), + UNI_RANGE(10.0 / 32), + } }; /* PCI4520 has two more gains (6 more entries) */ -static const struct comedi_lrange rtd_ai_4520_range = { 24, { - /* +-5V input range gain steps */ - BIP_RANGE(5.0), - BIP_RANGE(5.0 / 2), - BIP_RANGE(5.0 / 4), - BIP_RANGE(5.0 / 8), - BIP_RANGE(5.0 / - 16), - BIP_RANGE(5.0 / - 32), - BIP_RANGE(5.0 / - 64), - BIP_RANGE(5.0 / - 128), - /* +-10V input range gain steps */ - BIP_RANGE(10.0), - BIP_RANGE(10.0 / - 2), - BIP_RANGE(10.0 / - 4), - BIP_RANGE(10.0 / - 8), - BIP_RANGE(10.0 / - 16), - BIP_RANGE(10.0 / - 32), - BIP_RANGE(10.0 / - 64), - BIP_RANGE(10.0 / - 128), - /* +10V input range gain steps */ - UNI_RANGE(10.0), - UNI_RANGE(10.0 / - 2), - UNI_RANGE(10.0 / - 4), - UNI_RANGE(10.0 / - 8), - UNI_RANGE(10.0 / - 16), - UNI_RANGE(10.0 / - 32), - UNI_RANGE(10.0 / - 64), - UNI_RANGE(10.0 / - 128), - } +static const struct comedi_lrange rtd_ai_4520_range = { + 24, { + /* +-5V input range gain steps */ + BIP_RANGE(5.0), + BIP_RANGE(5.0 / 2), + BIP_RANGE(5.0 / 4), + BIP_RANGE(5.0 / 8), + BIP_RANGE(5.0 / 16), + BIP_RANGE(5.0 / 32), + BIP_RANGE(5.0 / 64), + BIP_RANGE(5.0 / 128), + /* +-10V input range gain steps */ + BIP_RANGE(10.0), + BIP_RANGE(10.0 / 2), + BIP_RANGE(10.0 / 4), + BIP_RANGE(10.0 / 8), + BIP_RANGE(10.0 / 16), + BIP_RANGE(10.0 / 32), + BIP_RANGE(10.0 / 64), + BIP_RANGE(10.0 / 128), + /* +10V input range gain steps */ + UNI_RANGE(10.0), + UNI_RANGE(10.0 / 2), + UNI_RANGE(10.0 / 4), + UNI_RANGE(10.0 / 8), + UNI_RANGE(10.0 / 16), + UNI_RANGE(10.0 / 32), + UNI_RANGE(10.0 / 64), + UNI_RANGE(10.0 / 128), + } }; /* Table order matches range values */ -static const struct comedi_lrange rtd_ao_range = { 4, { - RANGE(0, 5), - RANGE(0, 10), - RANGE(-5, 5), - RANGE(-10, 10), - } +static const struct comedi_lrange rtd_ao_range = { + 4, { + UNI_RANGE(5), + UNI_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(10), + } }; -/* - Board descriptions - */ struct rtdBoard { - const char *name; /* must be first */ + const char *name; int device_id; int aiChans; int aiBits; @@ -308,30 +277,24 @@ struct rtdBoard { static const struct rtdBoard rtd520Boards[] = { { - .name = "DM7520", - .device_id = 0x7520, - .aiChans = 16, - .aiBits = 12, - .aiMaxGain = 32, - .range10Start = 6, - .rangeUniStart = 12, - }, - { - .name = "PCI4520", - .device_id = 0x4520, - .aiChans = 16, - .aiBits = 12, - .aiMaxGain = 128, - .range10Start = 8, - .rangeUniStart = 16, - }, + .name = "DM7520", + .device_id = 0x7520, + .aiChans = 16, + .aiBits = 12, + .aiMaxGain = 32, + .range10Start = 6, + .rangeUniStart = 12, + }, { + .name = "PCI4520", + .device_id = 0x4520, + .aiChans = 16, + .aiBits = 12, + .aiMaxGain = 128, + .range10Start = 8, + .rangeUniStart = 16, + }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct rtdBoard *)dev->board_ptr) - /* This structure is for data unique to this hardware driver. This is also unique for each board in the system. @@ -398,136 +361,6 @@ struct rtdPrivate { #define CHAN_ARRAY_CLEAR(array, index) \ (((array)[(index)/8] &= ~(1 << ((index) & 0x7)))) -/* - * most drivers define the following macro to make it easy to - * access the private structure. - */ -#define devpriv ((struct rtdPrivate *)dev->private) - -/* Macros to access registers */ - -/* Digital IO */ -#define RtdDio0Write(dev, v) \ - writew((v) & 0xff, devpriv->las0+LAS0_DIO0) - -#define RtdDio1Read(dev) \ - (readw(devpriv->las0+LAS0_DIO1) & 0xff) -#define RtdDio1Write(dev, v) \ - writew((v) & 0xff, devpriv->las0+LAS0_DIO1) - -#define RtdDioStatusRead(dev) \ - (readw(devpriv->las0+LAS0_DIO_STATUS) & 0xff) -#define RtdDioStatusWrite(dev, v) \ - writew((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS) - -#define RtdDio0CtrlRead(dev) \ - (readw(devpriv->las0+LAS0_DIO0_CTRL) & 0xff) -#define RtdDio0CtrlWrite(dev, v) \ - writew((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL) - -/* Digital to Analog converter */ -/* Write one data value (sign + 12bit + marker bits) */ -/* Note: matches what DMA would put. Actual value << 3 */ -#define RtdDacFifoPut(dev, n, v) \ - writew((v), devpriv->las1 + (((n) == 0) ? LAS1_DAC1_FIFO : \ - LAS1_DAC2_FIFO)) - -/* Start single DAC conversion */ -#define RtdDacUpdate(dev, n) \ - writew(0, devpriv->las0 + (((n) == 0) ? LAS0_DAC1 : LAS0_DAC2)) - -/* Start single DAC conversion on both DACs */ -#define RtdDacBothUpdate(dev) \ - writew(0, devpriv->las0+LAS0_DAC) - -/* Set DAC output type and range */ -#define RtdDacRange(dev, n, v) \ - writew((v) & 7, devpriv->las0 \ - +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)) - -/* Reset DAC FIFO */ -#define RtdDacClearFifo(dev, n) \ - writel(0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : \ - LAS0_DAC2_RESET)) - -/* Set source for DMA 0 (write only, shadow?) */ -#define RtdDma0Source(dev, n) \ - writel((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC) - -/* Set source for DMA 1 (write only, shadow?) */ -#define RtdDma1Source(dev, n) \ - writel((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC) - -/* Reset board state for DMA 0 */ -#define RtdDma0Reset(dev) \ - writel(0, devpriv->las0+LAS0_DMA0_RESET) - -/* Reset board state for DMA 1 */ -#define RtdDma1Reset(dev) \ - writel(0, devpriv->las0+LAS0_DMA1_SRC) - -/* PLX9080 interrupt mask and status */ -#define RtdPlxInterruptRead(dev) \ - readl(devpriv->lcfg+LCFG_ITCSR) -#define RtdPlxInterruptWrite(dev, v) \ - writel(v, devpriv->lcfg+LCFG_ITCSR) - -/* Set mode for DMA 0 */ -#define RtdDma0Mode(dev, m) \ - writel((m), devpriv->lcfg+LCFG_DMAMODE0) - -/* Set PCI address for DMA 0 */ -#define RtdDma0PciAddr(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMAPADR0) - -/* Set local address for DMA 0 */ -#define RtdDma0LocalAddr(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMALADR0) - -/* Set byte count for DMA 0 */ -#define RtdDma0Count(dev, c) \ - writel((c), devpriv->lcfg+LCFG_DMASIZ0) - -/* Set next descriptor for DMA 0 */ -#define RtdDma0Next(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMADPR0) - -/* Set mode for DMA 1 */ -#define RtdDma1Mode(dev, m) \ - writel((m), devpriv->lcfg+LCFG_DMAMODE1) - -/* Set PCI address for DMA 1 */ -#define RtdDma1PciAddr(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMAADR1) - -/* Set local address for DMA 1 */ -#define RtdDma1LocalAddr(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMALADR1) - -/* Set byte count for DMA 1 */ -#define RtdDma1Count(dev, c) \ - writel((c), devpriv->lcfg+LCFG_DMASIZ1) - -/* Set next descriptor for DMA 1 */ -#define RtdDma1Next(dev, a) \ - writel((a), devpriv->lcfg+LCFG_DMADPR1) - -/* Set control for DMA 0 (write only, shadow?) */ -#define RtdDma0Control(dev, n) \ - writeb(devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0) - -/* Get status for DMA 0 */ -#define RtdDma0Status(dev) \ - readb(devpriv->lcfg+LCFG_DMACSR0) - -/* Set control for DMA 1 (write only, shadow?) */ -#define RtdDma1Control(dev, n) \ - writeb(devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1) - -/* Get status for DMA 1 */ -#define RtdDma1Status(dev) \ - readb(devpriv->lcfg+LCFG_DMACSR1) - /* Given a desired period and the clock period (both in ns), return the proper counter value (divider-1). @@ -577,6 +410,8 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode) static unsigned short rtdConvertChanGain(struct comedi_device *dev, unsigned int comediChan, int chanIndex) { /* index in channel list */ + const struct rtdBoard *thisboard = comedi_board(dev); + struct rtdPrivate *devpriv = dev->private; unsigned int chan, range, aref; unsigned short r = 0; @@ -629,6 +464,8 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev, static void rtd_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { + struct rtdPrivate *devpriv = dev->private; + if (n_chan > 1) { /* setup channel gain table */ int ii; @@ -649,6 +486,7 @@ static void rtd_load_channelgain_list(struct comedi_device *dev, empty status flag clears */ static int rtd520_probe_fifo_depth(struct comedi_device *dev) { + struct rtdPrivate *devpriv = dev->private; unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); unsigned i; static const unsigned limit = 0x2000; @@ -656,6 +494,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev) writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); rtd_load_channelgain_list(dev, 1, &chanspec); + /* ADC conversion trigger source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); /* convert samples */ for (i = 0; i < limit; ++i) { @@ -696,6 +535,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct rtdPrivate *devpriv = dev->private; int n, ii; int stat; @@ -705,7 +545,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, /* write channel to multiplexer and clear channel gain table */ rtd_load_channelgain_list(dev, 1, &insn->chanspec); - /* set conversion source */ + /* ADC conversion trigger source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); /* convert n samples */ @@ -751,6 +591,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int count) { + struct rtdPrivate *devpriv = dev->private; int ii; for (ii = 0; ii < count; ii++) { @@ -791,6 +632,8 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, */ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) { + struct rtdPrivate *devpriv = dev->private; + while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) { short sample; s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO); @@ -821,6 +664,7 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) */ void abort_dma(struct comedi_device *dev, unsigned int channel) { /* DMA channel 0, 1 */ + struct rtdPrivate *devpriv = dev->private; unsigned long dma_cs_addr; /* the control/status register */ uint8_t status; unsigned int ii; @@ -879,6 +723,7 @@ void abort_dma(struct comedi_device *dev, unsigned int channel) */ static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s) { + struct rtdPrivate *devpriv = dev->private; int ii, n; s16 *dp; @@ -941,8 +786,9 @@ static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s) static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ void *d) { /* our data *//* cpu context (ignored) */ - struct comedi_device *dev = d; /* must be called "dev" for devpriv */ + struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ + struct rtdPrivate *devpriv = dev->private; u32 overrun; u16 status; u16 fifoStatus; @@ -960,26 +806,26 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ } #ifdef USE_DMA if (devpriv->flags & DMA0_ACTIVE) { /* Check DMA */ - u32 istatus = RtdPlxInterruptRead(dev); + u32 istatus = readl(devpriv->lcfg + LCFG_ITCSR); if (istatus & ICS_DMA0_A) { if (ai_process_dma(dev, s) < 0) { DPRINTK ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n", devpriv->aiCount); - RtdDma0Control(dev, - (devpriv->dma0Control & - ~PLX_DMA_START_BIT) - | PLX_CLEAR_DMA_INTR_BIT); + devpriv->dma0Control &= ~PLX_DMA_START_BIT; + devpriv->dma0Control |= PLX_CLEAR_DMA_INTR_BIT; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); goto abortTransfer; } /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n", devpriv->aiCount, istatus); */ - RtdDma0Control(dev, - (devpriv-> - dma0Control & ~PLX_DMA_START_BIT) - | PLX_CLEAR_DMA_INTR_BIT); + devpriv->dma0Control &= ~PLX_DMA_START_BIT; + devpriv->dma0Control |= PLX_CLEAR_DMA_INTR_BIT; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); if (0 == devpriv->aiCount) { /* counted down */ DPRINTK("rtd520: Samples Done (DMA).\n"); goto transferDone; @@ -1063,15 +909,16 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ /* fall into transferDone */ transferDone: + /* pacer stop source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); + writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); devpriv->intMask = 0; writew(devpriv->intMask, devpriv->las0 + LAS0_IT); #ifdef USE_DMA if (devpriv->flags & DMA0_ACTIVE) { - RtdPlxInterruptWrite(dev, /* disable any more interrupts */ - RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); + writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E, + devpriv->lcfg + LCFG_ITCSR); abort_dma(dev, 0); devpriv->flags &= ~DMA0_ACTIVE; /* if Using DMA, then we should have read everything by now */ @@ -1330,26 +1177,30 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, */ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct rtdPrivate *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int timer; /* stop anything currently running */ + /* pacer stop source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); + writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); devpriv->intMask = 0; writew(devpriv->intMask, devpriv->las0 + LAS0_IT); #ifdef USE_DMA if (devpriv->flags & DMA0_ACTIVE) { /* cancel anything running */ - RtdPlxInterruptWrite(dev, /* disable any more interrupts */ - RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); + writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E, + devpriv->lcfg + LCFG_ITCSR); abort_dma(dev, 0); devpriv->flags &= ~DMA0_ACTIVE; - if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) { /*clear pending int */ - RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT); + if (readl(devpriv->lcfg + LCFG_ITCSR) & ICS_DMA0_A) { + devpriv->dma0Control = PLX_CLEAR_DMA_INTR_BIT; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); } } - RtdDma0Reset(dev); /* reset onboard state */ + writel(0, devpriv->las0 + LAS0_DMA0_RESET); #endif /* USE_DMA */ writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); writel(0, devpriv->las0 + LAS0_OVERRUN); @@ -1367,12 +1218,17 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* setup the common case and override if needed */ if (cmd->chanlist_len > 1) { /*DPRINTK ("rtd520: Multi channel setup\n"); */ + /* pacer start source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_PACER_START); + /* burst trigger source: PACER */ writel(1, devpriv->las0 + LAS0_BURST_START); + /* ADC conversion trigger source: BURST */ writel(2, devpriv->las0 + LAS0_ADC_CONVERSION); } else { /* single channel */ /*DPRINTK ("rtd520: single channel setup\n"); */ + /* pacer start source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_PACER_START); + /* ADC conversion trigger source: PACER */ writel(1, devpriv->las0 + LAS0_ADC_CONVERSION); } writel((devpriv->fifoLen / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT); @@ -1421,7 +1277,9 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->transCount = 0; devpriv->flags &= ~SEND_EOS; } + /* pacer clock source: INTERNAL 8MHz */ writel(1, devpriv->las0 + LAS0_PACER_SELECT); + /* just interrupt, don't stop */ writel(1, devpriv->las0 + LAS0_ACNT_STOP_ENABLE); /* BUG??? these look like enumerated values, but they are bit fields */ @@ -1457,6 +1315,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; case TRIG_EXT: + /* pacer start source: EXTERNAL */ writel(1, devpriv->las0 + LAS0_PACER_START); break; @@ -1479,6 +1338,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; case TRIG_EXT: /* external */ + /* burst trigger source: EXTERNAL */ writel(2, devpriv->las0 + LAS0_BURST_START); break; @@ -1505,18 +1365,22 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* point to first transfer in ring */ devpriv->dma0Offset = 0; - RtdDma0Mode(dev, DMA_MODE_BITS); - RtdDma0Next(dev, /* point to first block */ - devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next); - RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */ - - RtdPlxInterruptWrite(dev, /* enable interrupt */ - RtdPlxInterruptRead(dev) | ICS_DMA0_E); + writel(DMA_MODE_BITS, devpriv->lcfg + LCFG_DMAMODE0); + /* point to first block */ + writel(devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next, + devpriv->lcfg + LCFG_DMADPR0); + writel(DMAS_ADFIFO_HALF_FULL, devpriv->las0 + LAS0_DMA0_SRC); + writel(readl(devpriv->lcfg + LCFG_ITCSR) | ICS_DMA0_E, + devpriv->lcfg + LCFG_ITCSR); /* Must be 2 steps. See PLX app note about "Starting a DMA transfer" */ - RtdDma0Control(dev, PLX_DMA_EN_BIT); /* enable DMA (clear INTR?) */ - RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT); /*start DMA */ + devpriv->dma0Control = PLX_DMA_EN_BIT; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); + devpriv->dma0Control |= PLX_DMA_START_BIT; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n", - RtdPlxInterruptRead(dev), devpriv->intMask); + readl(devpriv->lcfg + LCFG_ITCSR), devpriv->intMask); #else /* USE_DMA */ devpriv->intMask = IRQM_ADC_ABOUT_CNT; writew(devpriv->intMask, devpriv->las0 + LAS0_IT); @@ -1526,7 +1390,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* BUG: start_src is ASSUMED to be TRIG_NOW */ /* BUG? it seems like things are running before the "start" */ - readl(devpriv->las0 + LAS0_PACER); + readl(devpriv->las0 + LAS0_PACER); /* start pacer */ return 0; } @@ -1535,19 +1399,21 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { + struct rtdPrivate *devpriv = dev->private; u32 overrun; u16 status; + /* pacer stop source: SOFTWARE */ writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); + writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); devpriv->intMask = 0; writew(devpriv->intMask, devpriv->las0 + LAS0_IT); devpriv->aiCount = 0; /* stop and don't transfer any more */ #ifdef USE_DMA if (devpriv->flags & DMA0_ACTIVE) { - RtdPlxInterruptWrite(dev, /* disable any more interrupts */ - RtdPlxInterruptRead(dev) & ~ICS_DMA0_E); + writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E, + devpriv->lcfg + LCFG_ITCSR); abort_dma(dev, 0); devpriv->flags &= ~DMA0_ACTIVE; } @@ -1567,12 +1433,14 @@ static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct rtdPrivate *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); /* Configure the output range (table index matches the range values) */ - RtdDacRange(dev, chan, range); + writew(range & 7, devpriv->las0 + + ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)); /* Writing a list of values to an AO channel is probably not * very useful, but that's how the interface is defined. */ @@ -1596,8 +1464,9 @@ static int rtd_ao_winsn(struct comedi_device *dev, chan, range, data[i], val); /* a typical programming sequence */ - RtdDacFifoPut(dev, chan, val); /* put the value in */ - RtdDacUpdate(dev, chan); /* trigger the conversion */ + writew(val, devpriv->las1 + + ((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO)); + writew(0, devpriv->las0 + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2)); devpriv->aoValue[chan] = data[i]; /* save for read back */ @@ -1627,6 +1496,7 @@ static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct rtdPrivate *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); @@ -1651,6 +1521,8 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct rtdPrivate *devpriv = dev->private; + /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ if (data[0]) { @@ -1658,7 +1530,7 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, s->state |= data[0] & data[1]; /* Write out the new digital output lines */ - RtdDio0Write(dev, s->state); + writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0); } /* on return, data[1] contains the value of the digital * input lines. */ @@ -1676,6 +1548,7 @@ static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct rtdPrivate *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); /* The input or output configuration of each digital line is @@ -1700,9 +1573,11 @@ static int rtd_dio_insn_config(struct comedi_device *dev, DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits); /* TODO support digital match interrupts and strobes */ - RtdDioStatusWrite(dev, 0x01); /* make Dio0Ctrl point to direction */ - RtdDio0CtrlWrite(dev, s->io_bits); /* set direction 1 means Out */ - RtdDioStatusWrite(dev, 0); /* make Dio0Ctrl clear interrupts */ + devpriv->dioStatus = 0x01; /* set direction */ + writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); + writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL); + devpriv->dioStatus = 0x00; /* clear interrupts */ + writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); /* port1 can only be all input or all output */ @@ -1711,10 +1586,42 @@ static int rtd_dio_insn_config(struct comedi_device *dev, return 1; } +static struct pci_dev *rtd_find_pci(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + const struct rtdBoard *thisboard; + struct pci_dev *pcidev = NULL; + int bus = it->options[0]; + int slot = it->options[1]; + int i; + + for_each_pci_dev(pcidev) { + if (pcidev->vendor != PCI_VENDOR_ID_RTD) + continue; + if (bus || slot) { + if (pcidev->bus->number != bus || + PCI_SLOT(pcidev->devfn) != slot) + continue; + } + for (i = 0; i < ARRAY_SIZE(rtd520Boards); i++) { + thisboard = &rtd520Boards[i]; + if (pcidev->device == thisboard->device_id) { + dev->board_ptr = thisboard; + return pcidev; + } + } + } + dev_warn(dev->class_dev, + "no supported board found! (req. bus/slot: %d/%d)\n", + bus, slot); + return NULL; +} + static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) { /* board name and options flags */ + const struct rtdBoard *thisboard; + struct rtdPrivate *devpriv; struct comedi_subdevice *s; - struct pci_dev *pcidev; int ret; resource_size_t physLas0; /* configuration */ resource_size_t physLas1; /* data area */ @@ -1737,43 +1644,16 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) */ if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0) return -ENOMEM; + devpriv = dev->private; - /* - * Probe the device to determine what device in the series it is. - */ - for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL); - pcidev != NULL; - pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) { - int i; - - if (it->options[0] || it->options[1]) { - if (pcidev->bus->number != it->options[0] - || PCI_SLOT(pcidev->devfn) != it->options[1]) { - continue; - } - } - for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i) { - if (pcidev->device == rtd520Boards[i].device_id) { - dev->board_ptr = &rtd520Boards[i]; - break; - } - } - if (dev->board_ptr) - break; /* found one */ - } - if (!pcidev) { - if (it->options[0] && it->options[1]) { - printk(KERN_INFO "No RTD card at bus=%d slot=%d.\n", - it->options[0], it->options[1]); - } else { - printk(KERN_INFO "No RTD card found.\n"); - } + devpriv->pci_dev = rtd_find_pci(dev, it); + if (!devpriv->pci_dev) return -EIO; - } - devpriv->pci_dev = pcidev; + thisboard = comedi_board(dev); + dev->board_name = thisboard->name; - ret = comedi_pci_enable(pcidev, DRV_NAME); + ret = comedi_pci_enable(devpriv->pci_dev, DRV_NAME); if (ret < 0) { printk(KERN_INFO "Failed to enable PCI device and request regions.\n"); return ret; @@ -1892,7 +1772,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* also, initialize shadow registers */ writel(0, devpriv->las0 + LAS0_BOARD_RESET); udelay(100); /* needed? */ - RtdPlxInterruptWrite(dev, 0); + writel(0, devpriv->lcfg + LCFG_ITCSR); devpriv->intMask = 0; writew(devpriv->intMask, devpriv->las0 + LAS0_IT); devpriv->intClearMask = ~0; @@ -1901,10 +1781,11 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) writel(0, devpriv->las0 + LAS0_OVERRUN); writel(0, devpriv->las0 + LAS0_CGT_CLEAR); writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); - RtdDacClearFifo(dev, 0); - RtdDacClearFifo(dev, 1); + writel(0, devpriv->las0 + LAS0_DAC1_RESET); + writel(0, devpriv->las0 + LAS0_DAC2_RESET); /* clear digital IO fifo */ - RtdDioStatusWrite(dev, 0); /* safe state, set shadow */ + devpriv->dioStatus = 0; + writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); devpriv->utcCtrl[0] = (0 << 6) | 0x30; devpriv->utcCtrl[1] = (1 << 6) | 0x30; devpriv->utcCtrl[2] = (2 << 6) | 0x30; @@ -1998,17 +1879,16 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) goto rtd_attach_die_error; } - RtdDma0Mode(dev, DMA_MODE_BITS); + writel(DMA_MODE_BITS, devpriv->lcfg + LCFG_DMAMODE0); /* set DMA trigger source */ - RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); + writel(DMAS_ADFIFO_HALF_FULL, devpriv->las0 + LAS0_DMA0_SRC); } else { printk(KERN_INFO "( no IRQ->no DMA )"); } #endif /* USE_DMA */ - if (dev->irq) { /* enable plx9080 interrupts */ - RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); - } + if (dev->irq) + writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR); printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor); @@ -2038,9 +1918,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif /* USE_DMA */ /* subdevices and priv are freed by the core */ if (dev->irq) { - /* disable interrupt controller */ - RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) - & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E)); + writel(readl(devpriv->lcfg + LCFG_ITCSR) & + ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E), + devpriv->lcfg + LCFG_ITCSR); free_irq(dev->irq, dev); } @@ -2063,6 +1943,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void rtd_detach(struct comedi_device *dev) { + struct rtdPrivate *devpriv = dev->private; #ifdef USE_DMA int index; #endif @@ -2071,9 +1952,13 @@ static void rtd_detach(struct comedi_device *dev) /* Shut down any board ops by resetting it */ #ifdef USE_DMA if (devpriv->lcfg) { - RtdDma0Control(dev, 0); /* disable DMA */ - RtdDma1Control(dev, 0); /* disable DMA */ - RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE); + devpriv->dma0Control = 0; + devpriv->dma1Control = 0; + writeb(devpriv->dma0Control, + devpriv->lcfg + LCFG_DMACSR0); + writeb(devpriv->dma1Control, + devpriv->lcfg + LCFG_DMACSR1); + writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR); } #endif /* USE_DMA */ if (devpriv->las0) { @@ -2107,9 +1992,9 @@ static void rtd_detach(struct comedi_device *dev) } #endif /* USE_DMA */ if (dev->irq) { - RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev) - & ~(ICS_PLIE | ICS_DMA0_E | - ICS_DMA1_E)); + writel(readl(devpriv->lcfg + LCFG_ITCSR) & + ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E), + devpriv->lcfg + LCFG_ITCSR); free_irq(dev->irq, dev); } if (devpriv->las0) diff --git a/trunk/drivers/staging/et131x/et131x.c b/trunk/drivers/staging/et131x/et131x.c index ac6897b593c9..4c78f12ddc34 100644 --- a/trunk/drivers/staging/et131x/et131x.c +++ b/trunk/drivers/staging/et131x/et131x.c @@ -3943,12 +3943,6 @@ static struct ethtool_ops et131x_ethtool_ops = { .get_regs = et131x_get_regs, .get_link = ethtool_op_get_link, }; - -static void et131x_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops); -} - /** * et131x_hwaddr_init - set up the MAC Address on the ET1310 * @adapter: pointer to our private adapter structure @@ -5301,7 +5295,7 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, netdev->netdev_ops = &et131x_netdev_ops; SET_NETDEV_DEV(netdev, &pdev->dev); - et131x_set_ethtool_ops(netdev); + SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops); adapter = et131x_adapter_init(netdev, pdev); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index e8c4a4e5ac6d..b2ecd0e6780e 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -70,7 +70,7 @@ static int ft1000_probe(struct usb_interface *interface, ft1000dev = kzalloc(sizeof(struct ft1000_device), GFP_KERNEL); if (!ft1000dev) { - printk(KERN_ERR "out of memory allocating device structure\n"); + pr_err("out of memory allocating device structure\n"); return -ENOMEM; } @@ -138,7 +138,7 @@ static int ft1000_probe(struct usb_interface *interface, ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev); if (ret < 0) { - printk(KERN_ERR "Error request_firmware().\n"); + pr_err("Error request_firmware().\n"); goto err_fw; } @@ -166,7 +166,7 @@ static int ft1000_probe(struct usb_interface *interface, DEBUG("In probe: pft1000info=%p\n", pft1000info); ret = dsp_reload(ft1000dev); if (ret) { - printk(KERN_ERR "Problem with DSP image loading\n"); + pr_err("Problem with DSP image loading\n"); goto err_load; } diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h index 51c084756b4a..642bb89942f5 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h @@ -1,7 +1,6 @@ #ifndef _FT1000_USB_H_ #define _FT1000_USB_H_ -/*Jim*/ #include "../ft1000.h" #include "ft1000_ioctl.h" #define FT1000_DRV_VER 0x01010403 @@ -15,19 +14,18 @@ #define SUCCESS 0x00 struct app_info_block { - u32 nTxMsg; // DPRAM msg sent to DSP with app_id - u32 nRxMsg; // DPRAM msg rcv from dsp with app_id - u32 nTxMsgReject; // DPRAM msg rejected due to DSP doorbell set - u32 nRxMsgMiss; // DPRAM msg dropped due to overflow - struct fown_struct *fileobject;// Application's file object - u16 app_id; // Application id + u32 nTxMsg; /* DPRAM msg sent to DSP with app_id */ + u32 nRxMsg; /* DPRAM msg rcv from dsp with app_id */ + u32 nTxMsgReject; /* DPRAM msg rejected due to DSP doorbell set */ + u32 nRxMsgMiss; /* DPRAM msg dropped due to overflow */ + struct fown_struct *fileobject;/* Application's file object */ + u16 app_id; /* Application id */ int DspBCMsgFlag; - int NumOfMsg; // number of messages queued up + int NumOfMsg; /* number of messages queued up */ wait_queue_head_t wait_dpram_msg; - struct list_head app_sqlist; // link list of msgs for applicaton on slow queue -} __attribute__((packed)); + struct list_head app_sqlist; /* link list of msgs for applicaton on slow queue */ +} __packed; -/*end of Jim*/ #define DEBUG(args...) printk(KERN_INFO args) #define FALSE 0 @@ -47,20 +45,19 @@ struct app_info_block { #undef FT1000_DPRAM_RX_BASE #define FT1000_DPRAM_RX_BASE 0x1800 /* RX AREA (SlowQ) */ -// MEMORY MAP FOR MAGNEMITE +/* MEMORY MAP FOR MAGNEMITE */ /* the indexes are swapped comparing to PCMCIA - is it OK or a bug? */ #undef FT1000_MAG_DSP_LED_INDX #define FT1000_MAG_DSP_LED_INDX 0x1 /* dsp led status for PAD device */ #undef FT1000_MAG_DSP_CON_STATE_INDX #define FT1000_MAG_DSP_CON_STATE_INDX 0x0 /* DSP Connection Status Info */ -// Maximum times trying to get ASIC out of reset +/* Maximum times trying to get ASIC out of reset */ #define MAX_ASIC_RESET_CNT 20 #define MAX_BUF_SIZE 4096 -struct ft1000_device -{ +struct ft1000_device { struct usb_device *dev; struct net_device *net; @@ -74,11 +71,7 @@ struct ft1000_device u8 bulk_in_endpointAddr; u8 bulk_out_endpointAddr; - - //struct ft1000_ethernet_configuration configuration; - -// struct net_device_stats stats; //mbelian -} __attribute__ ((packed)); +} __packed; struct ft1000_debug_dirs { struct list_head list; @@ -88,90 +81,101 @@ struct ft1000_debug_dirs { }; struct ft1000_info { - struct ft1000_device *pFt1000Dev; - struct net_device_stats stats; + struct ft1000_device *pFt1000Dev; + struct net_device_stats stats; - struct task_struct *pPollThread; + struct task_struct *pPollThread; - unsigned char fcodeldr; - unsigned char bootmode; + unsigned char fcodeldr; + unsigned char bootmode; unsigned char usbboot; - unsigned short dspalive; - u16 ASIC_ID; - bool fProvComplete; - bool fCondResetPend; - bool fAppMsgPend; - u16 DrvErrNum; - u16 AsicID; - int DspAsicReset; - int DeviceCreated; - int CardReady; - int NetDevRegDone; - u8 CardNumber; - u8 DeviceName[15]; - struct ft1000_debug_dirs nodes; - int registered; - int mediastate; - u8 squeseqnum; // sequence number on slow queue - spinlock_t dpram_lock; - spinlock_t fifo_lock; - u16 fifo_cnt; - u8 DspVer[DSPVERSZ]; // DSP version number - u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number - u8 Sku[SKUSZ]; // SKU - u8 eui64[EUISZ]; // EUI64 - time_t ConTm; // Connection Time - u8 ProductMode[MODESZ]; - u8 RfCalVer[CALVERSZ]; - u8 RfCalDate[CALDATESZ]; - u16 DSP_TIME[4]; - u16 LedStat; //mbelian - u16 ConStat; //mbelian - u16 ProgConStat; - struct list_head prov_list; - int appcnt; + unsigned short dspalive; + u16 ASIC_ID; + bool fProvComplete; + bool fCondResetPend; + bool fAppMsgPend; + u16 DrvErrNum; + u16 AsicID; + int DspAsicReset; + int DeviceCreated; + int CardReady; + int NetDevRegDone; + u8 CardNumber; + u8 DeviceName[15]; + struct ft1000_debug_dirs nodes; + int registered; + int mediastate; + u8 squeseqnum; /* sequence number on slow queue */ + spinlock_t dpram_lock; + spinlock_t fifo_lock; + u16 fifo_cnt; + u8 DspVer[DSPVERSZ]; /* DSP version number */ + u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */ + u8 Sku[SKUSZ]; /* SKU */ + u8 eui64[EUISZ]; /* EUI64 */ + time_t ConTm; /* Connection Time */ + u8 ProductMode[MODESZ]; + u8 RfCalVer[CALVERSZ]; + u8 RfCalDate[CALDATESZ]; + u16 DSP_TIME[4]; + u16 LedStat; + u16 ConStat; + u16 ProgConStat; + struct list_head prov_list; + int appcnt; struct app_info_block app_info[MAX_NUM_APP]; - u16 DSPInfoBlklen; - u16 DrvMsgPend; - int (*ft1000_reset)(struct net_device *dev); - u16 DSPInfoBlk[MAX_DSP_SESS_REC]; - union { - u16 Rec[MAX_DSP_SESS_REC]; - u32 MagRec[MAX_DSP_SESS_REC/2]; - } DSPSess; + u16 DSPInfoBlklen; + u16 DrvMsgPend; + int (*ft1000_reset)(struct net_device *dev); + u16 DSPInfoBlk[MAX_DSP_SESS_REC]; + union { + u16 Rec[MAX_DSP_SESS_REC]; + u32 MagRec[MAX_DSP_SESS_REC/2]; + } DSPSess; unsigned short tempbuf[32]; char netdevname[IFNAMSIZ]; - struct proc_dir_entry *ft1000_proc_dir; //mbelian + struct proc_dir_entry *ft1000_proc_dir; }; struct dpram_blk { - struct list_head list; - u16 *pbuffer; -} __attribute__ ((packed)); - -int ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegIndx); -int ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx); -int ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt); -int ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt); -int ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow); -int ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow); -int fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer); -int fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer); + struct list_head list; + u16 *pbuffer; +} __packed; + +int ft1000_read_register(struct ft1000_device *ft1000dev, + u16 *Data, u16 nRegIndx); +int ft1000_write_register(struct ft1000_device *ft1000dev, + u16 value, u16 nRegIndx); +int ft1000_read_dpram32(struct ft1000_device *ft1000dev, + u16 indx, u8 *buffer, u16 cnt); +int ft1000_write_dpram32(struct ft1000_device *ft1000dev, + u16 indx, u8 *buffer, u16 cnt); +int ft1000_read_dpram16(struct ft1000_device *ft1000dev, + u16 indx, u8 *buffer, u8 highlow); +int ft1000_write_dpram16(struct ft1000_device *ft1000dev, + u16 indx, u16 value, u8 highlow); +int fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, + u16 indx, u8 *buffer); +int fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, + u16 indx, u8 *buffer); extern void *pFileStart; extern size_t FileLength; extern int numofmsgbuf; -int ft1000_close (struct net_device *dev); -u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32 FileLength); +int ft1000_close(struct net_device *dev); +u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, + u32 FileLength); extern struct list_head freercvpool; -extern spinlock_t free_buff_lock; // lock to arbitrate free buffer list for receive command data + +extern spinlock_t free_buff_lock; /* lock to arbitrate free buffer list for receive command data */ int ft1000_create_dev(struct ft1000_device *dev); void ft1000_destroy_dev(struct net_device *dev); -extern void card_send_command(struct ft1000_device *ft1000dev, void *ptempbuffer, int size); +extern void card_send_command(struct ft1000_device *ft1000dev, + void *ptempbuffer, int size); struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist); void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist); @@ -179,8 +183,9 @@ void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist); int dsp_reload(struct ft1000_device *ft1000dev); int init_ft1000_netdev(struct ft1000_device *ft1000dev); struct usb_interface; -int reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf); -int ft1000_poll(void* dev_id); +int reg_ft1000_netdev(struct ft1000_device *ft1000dev, + struct usb_interface *intf); +int ft1000_poll(void *dev_id); int ft1000_init_proc(struct net_device *dev); void ft1000_cleanup_proc(struct ft1000_info *info); diff --git a/trunk/drivers/staging/gdm72xx/gdm_qos.c b/trunk/drivers/staging/gdm72xx/gdm_qos.c index e7134e28a06d..80bde053fbc2 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_qos.c +++ b/trunk/drivers/staging/gdm72xx/gdm_qos.c @@ -195,7 +195,7 @@ static u32 chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *Stream, u8 *port) return 0; } -static u32 get_qos_index(struct nic *nic, u8* iph, u8* tcpudph) +static u32 get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph) { u32 IP_Ver, Header_Len, i; struct qos_cb_s *qcb = &nic->qos; @@ -240,8 +240,7 @@ static u32 extract_qos_list(struct nic *nic, struct list_head *head) qcb->csr[i].QoSBufCount++; if (!list_empty(&qcb->qos_list[i])) - wprintk("QoS Index(%d) " - "is piled!!\n", i); + wprintk("QoS Index(%d) is piled!!\n", i); } } } diff --git a/trunk/drivers/staging/gdm72xx/gdm_sdio.c b/trunk/drivers/staging/gdm72xx/gdm_sdio.c index 5e19b09e3bff..3e43c012ef27 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_sdio.c +++ b/trunk/drivers/staging/gdm72xx/gdm_sdio.c @@ -664,20 +664,17 @@ static int sdio_wimax_probe(struct sdio_func *func, if (ret) return ret; - phy_dev = kmalloc(sizeof(*phy_dev), GFP_KERNEL); + phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL); if (phy_dev == NULL) { ret = -ENOMEM; goto out; } - sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); + sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); if (sdev == NULL) { ret = -ENOMEM; goto out; } - memset(phy_dev, 0, sizeof(*phy_dev)); - memset(sdev, 0, sizeof(*sdev)); - phy_dev->priv_dev = (void *)sdev; phy_dev->send_func = gdm_sdio_send; phy_dev->rcv_func = gdm_sdio_receive; diff --git a/trunk/drivers/staging/gdm72xx/gdm_usb.c b/trunk/drivers/staging/gdm72xx/gdm_usb.c index 89268c785b25..d48d49c145ee 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_usb.c +++ b/trunk/drivers/staging/gdm72xx/gdm_usb.c @@ -590,20 +590,17 @@ static int gdm_usb_probe(struct usb_interface *intf, goto out; } - phy_dev = kmalloc(sizeof(*phy_dev), GFP_KERNEL); + phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL); if (phy_dev == NULL) { ret = -ENOMEM; goto out; } - udev = kmalloc(sizeof(*udev), GFP_KERNEL); + udev = kzalloc(sizeof(*udev), GFP_KERNEL); if (udev == NULL) { ret = -ENOMEM; goto out; } - memset(phy_dev, 0, sizeof(*phy_dev)); - memset(udev, 0, sizeof(*udev)); - if (idProduct == 0x7205 || idProduct == 0x7206) udev->padding = GDM7205_PADDING; else diff --git a/trunk/drivers/staging/gdm72xx/gdm_wimax.c b/trunk/drivers/staging/gdm72xx/gdm_wimax.c index e616de13b623..0716efc1817d 100644 --- a/trunk/drivers/staging/gdm72xx/gdm_wimax.c +++ b/trunk/drivers/staging/gdm72xx/gdm_wimax.c @@ -255,17 +255,15 @@ static void gdm_wimax_event_rcv(struct net_device *dev, u16 type, void *msg, static int gdm_wimax_event_init(void) { - if (wm_event.ref_cnt == 0) { + if (!wm_event.ref_cnt) { wm_event.sock = netlink_init(NETLINK_WIMAX, gdm_wimax_event_rcv); + if (wm_event.sock) + wm_event.ref_cnt++; INIT_LIST_HEAD(&wm_event.evtq); INIT_LIST_HEAD(&wm_event.freeq); INIT_WORK(&wm_event.ws, __gdm_wimax_event_send); spin_lock_init(&wm_event.evt_lock); - } - - if (wm_event.sock) { - wm_event.ref_cnt++; return 0; } diff --git a/trunk/drivers/staging/gdm72xx/usb_boot.c b/trunk/drivers/staging/gdm72xx/usb_boot.c index c163bcc437ed..fef290c38db6 100644 --- a/trunk/drivers/staging/gdm72xx/usb_boot.c +++ b/trunk/drivers/staging/gdm72xx/usb_boot.c @@ -174,7 +174,7 @@ int usb_boot(struct usb_device *usbdev, u16 pid) if (IS_ERR(filp)) { printk(KERN_ERR "Can't find %s.\n", img_name); set_fs(fs); - ret = -ENOENT; + ret = PTR_ERR(filp); goto restore_fs; } diff --git a/trunk/drivers/staging/ipack/devices/ipoctal.c b/trunk/drivers/staging/ipack/devices/ipoctal.c index a5af423a4e7c..fd0e30132ca2 100644 --- a/trunk/drivers/staging/ipack/devices/ipoctal.c +++ b/trunk/drivers/staging/ipack/devices/ipoctal.c @@ -114,8 +114,6 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, CR_ENABLE_RX); - tty->driver_data = ipoctal; - return 0; } @@ -136,6 +134,8 @@ static int ipoctal_open(struct tty_struct *tty, struct file *file) if (atomic_read(&ipoctal->open[channel])) return -EBUSY; + tty->driver_data = ipoctal; + res = tty_port_open(&ipoctal->tty_port[channel], tty, file); if (res) return res; @@ -411,6 +411,20 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, for (i = 0; i < NR_CHANNELS ; i++) { ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr, CR_DISABLE_RX | CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_RX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_TX); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + MR1_CHRL_8_BITS | MR1_ERROR_CHAR | + MR1_RxINT_RxRDY); /* mr1 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + 0); /* mr2 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.csr, + TX_CLK_9600 | RX_CLK_9600); } for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { diff --git a/trunk/drivers/staging/omap-thermal/Kconfig b/trunk/drivers/staging/omap-thermal/Kconfig new file mode 100644 index 000000000000..30cbc3bc8dfa --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/Kconfig @@ -0,0 +1,46 @@ +config OMAP_BANDGAP + tristate "Texas Instruments OMAP4+ temperature sensor driver" + depends on THERMAL + depends on ARCH_OMAP4 || SOC_OMAP5 + help + If you say yes here you get support for the Texas Instruments + OMAP4460+ on die bandgap temperature sensor support. The register + set is part of system control module. + + This includes alert interrupts generation and also the TSHUT + support. + +config OMAP_THERMAL + bool "Texas Instruments OMAP4+ thermal framework support" + depends on OMAP_BANDGAP + depends on CPU_THERMAL + help + If you say yes here you want to get support for generic thermal + framework for the Texas Instruments OMAP4460+ on die bandgap + temperature sensor. + +config OMAP4_THERMAL + bool "Texas Instruments OMAP4 thermal support" + depends on OMAP_BANDGAP + depends on ARCH_OMAP4 + help + If you say yes here you get thermal support for the Texas Instruments + OMAP4 SoC family. The current chip supported are: + - OMAP4430 + - OMAP4460 + - OMAP4470 + + This includes alert interrupts generation and also the TSHUT + support. + +config OMAP5_THERMAL + bool "Texas Instruments OMAP5 thermal support" + depends on OMAP_BANDGAP + depends on SOC_OMAP5 + help + If you say yes here you get thermal support for the Texas Instruments + OMAP5 SoC family. The current chip supported are: + - OMAP5430 + + This includes alert interrupts generation and also the TSHUT + support. diff --git a/trunk/drivers/staging/omap-thermal/Makefile b/trunk/drivers/staging/omap-thermal/Makefile new file mode 100644 index 000000000000..091c4d20b14d --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal.o +omap-thermal-y := omap-bandgap.o +omap-thermal-$(CONFIG_OMAP_THERMAL) += omap-thermal-common.o +omap-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal.o +omap-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal.o diff --git a/trunk/drivers/staging/omap-thermal/TODO b/trunk/drivers/staging/omap-thermal/TODO new file mode 100644 index 000000000000..9e23cc4d551b --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/TODO @@ -0,0 +1,28 @@ +List of TODOs (by Eduardo Valentin) + +on omap-bandgap.c: +- Rework locking +- Improve driver code by adding usage of regmap-mmio +- Test every exposed API to userland +- Add support to hwmon +- Review and revisit all API exposed +- Revisit PM support +- Revisit data structures and simplify them +- Once SCM-core api settles, update this driver accordingly + +on omap-thermal-common.c/omap-thermal.h: +- Revisit extrapolation constants for O4/O5 +- Revisit need for locking +- Revisit trips and its definitions +- Revisit trending + +on omap5-thermal.c +- Add support for GPU cooling + +generally: +- write Kconfig dependencies so that omap variants are covered +- make checkpatch.pl and sparse happy +- make sure this code works on OMAP4430, OMAP4460 and OMAP5430 +- update documentation + +Copy patches to Eduardo Valentin diff --git a/trunk/drivers/staging/omap-thermal/omap-bandgap.c b/trunk/drivers/staging/omap-thermal/omap-bandgap.c new file mode 100644 index 000000000000..c556abb63a17 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap-bandgap.c @@ -0,0 +1,1187 @@ +/* + * OMAP4 Bandgap temperature sensor driver + * + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ + * Author: J Keerthy + * Author: Moiz Sonasath + * Couple of fixes, DT and MFD adaptation: + * Eduardo Valentin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "omap-bandgap.h" + +static u32 omap_bandgap_readl(struct omap_bandgap *bg_ptr, u32 reg) +{ + return readl(bg_ptr->base + reg); +} + +static void omap_bandgap_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg) +{ + writel(val, bg_ptr->base + reg); +} + +static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on) +{ + struct temp_sensor_registers *tsr; + int i; + u32 ctrl; + + if (!OMAP_BANDGAP_HAS(bg_ptr, POWER_SWITCH)) + return 0; + + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + tsr = bg_ptr->conf->sensors[i].registers; + ctrl = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + ctrl &= ~tsr->bgap_tempsoff_mask; + /* active on 0 */ + ctrl |= !on << __ffs(tsr->bgap_tempsoff_mask); + + /* write BGAP_TEMPSOFF should be reset to 0 */ + omap_bandgap_writel(bg_ptr, ctrl, tsr->temp_sensor_ctrl); + } + + return 0; +} + +/* This is the Talert handler. Call it only if HAS(TALERT) is set */ +static irqreturn_t talert_irq_handler(int irq, void *data) +{ + struct omap_bandgap *bg_ptr = data; + struct temp_sensor_registers *tsr; + u32 t_hot = 0, t_cold = 0, temp, ctrl; + int i; + + bg_ptr = data; + /* Read the status of t_hot */ + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + tsr = bg_ptr->conf->sensors[i].registers; + t_hot = omap_bandgap_readl(bg_ptr, tsr->bgap_status); + t_hot &= tsr->status_hot_mask; + + /* Read the status of t_cold */ + t_cold = omap_bandgap_readl(bg_ptr, tsr->bgap_status); + t_cold &= tsr->status_cold_mask; + + if (!t_cold && !t_hot) + continue; + + ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl); + /* + * One TALERT interrupt: Two sources + * If the interrupt is due to t_hot then mask t_hot and + * and unmask t_cold else mask t_cold and unmask t_hot + */ + if (t_hot) { + ctrl &= ~tsr->mask_hot_mask; + ctrl |= tsr->mask_cold_mask; + } else if (t_cold) { + ctrl &= ~tsr->mask_cold_mask; + ctrl |= tsr->mask_hot_mask; + } + + omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl); + + /* read temperature */ + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= tsr->bgap_dtemp_mask; + + /* report temperature to whom may concern */ + if (bg_ptr->conf->report_temperature) + bg_ptr->conf->report_temperature(bg_ptr, i); + } + + return IRQ_HANDLED; +} + +/* This is the Tshut handler. Call it only if HAS(TSHUT) is set */ +static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data) +{ + orderly_poweroff(true); + + return IRQ_HANDLED; +} + +static +int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val, + int *t) +{ + struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data; + + /* look up for temperature in the table and return the temperature */ + if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val) + return -ERANGE; + + *t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val]; + + return 0; +} + +static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i, + int *adc) +{ + struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[i].ts_data; + int high, low, mid; + + low = 0; + high = ts_data->adc_end_val - ts_data->adc_start_val; + mid = (high + low) / 2; + + if (temp < bg_ptr->conv_table[high] || temp > bg_ptr->conv_table[high]) + return -EINVAL; + + while (low < high) { + if (temp < bg_ptr->conv_table[mid]) + high = mid - 1; + else + low = mid + 1; + mid = (low + high) / 2; + } + + *adc = ts_data->adc_start_val + low; + + return 0; +} + +/* Talert masks. Call it only if HAS(TALERT) is set */ +static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id, + u32 t_hot, u32 t_cold) +{ + struct temp_sensor_registers *tsr; + u32 temp, reg_val; + + /* Read the current on die temperature */ + tsr = bg_ptr->conf->sensors[id].registers; + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= tsr->bgap_dtemp_mask; + + reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl); + if (temp < t_hot) + reg_val |= tsr->mask_hot_mask; + else + reg_val &= ~tsr->mask_hot_mask; + + if (t_cold < temp) + reg_val |= tsr->mask_cold_mask; + else + reg_val &= ~tsr->mask_cold_mask; + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl); + + return 0; +} + +static +int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i, + u32 *sum) +{ + int temp, ret; + + ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp); + if (ret < 0) + return ret; + + temp += hyst_val; + + return temp_to_adc_conversion(temp, bg_ptr, i, sum); +} + +/* Talert Thot threshold. Call it only if HAS(TALERT) is set */ +static +int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot) +{ + struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data; + struct temp_sensor_registers *tsr; + u32 thresh_val, reg_val; + int cold, err = 0; + + tsr = bg_ptr->conf->sensors[id].registers; + + /* obtain the T cold value */ + thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + cold = (thresh_val & tsr->threshold_tcold_mask) >> + __ffs(tsr->threshold_tcold_mask); + if (t_hot <= cold) { + /* change the t_cold to t_hot - 5000 millidegrees */ + err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold); + /* write the new t_cold value */ + reg_val = thresh_val & (~tsr->threshold_tcold_mask); + reg_val |= cold << __ffs(tsr->threshold_tcold_mask); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + thresh_val = reg_val; + } + + /* write the new t_hot value */ + reg_val = thresh_val & ~tsr->threshold_thot_mask; + reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + if (err) { + dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n"); + return -EIO; + } + + return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold); +} + +/* Talert Thot and Tcold thresholds. Call it only if HAS(TALERT) is set */ +static +int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id, + int t_hot, int t_cold) +{ + struct temp_sensor_registers *tsr; + u32 reg_val, thresh_val; + + tsr = bg_ptr->conf->sensors[id].registers; + thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + + /* write the new t_cold value */ + reg_val = thresh_val & ~tsr->threshold_tcold_mask; + reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask)); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + + thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + + /* write the new t_hot value */ + reg_val = thresh_val & ~tsr->threshold_thot_mask; + reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + + reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl); + reg_val |= tsr->mask_hot_mask; + reg_val |= tsr->mask_cold_mask; + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl); + + return 0; +} + +/* Talert Tcold threshold. Call it only if HAS(TALERT) is set */ +static +int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id, + int t_cold) +{ + struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data; + struct temp_sensor_registers *tsr; + u32 thresh_val, reg_val; + int hot, err = 0; + + tsr = bg_ptr->conf->sensors[id].registers; + /* obtain the T cold value */ + thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + hot = (thresh_val & tsr->threshold_thot_mask) >> + __ffs(tsr->threshold_thot_mask); + + if (t_cold >= hot) { + /* change the t_hot to t_cold + 5000 millidegrees */ + err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot); + /* write the new t_hot value */ + reg_val = thresh_val & (~tsr->threshold_thot_mask); + reg_val |= hot << __ffs(tsr->threshold_thot_mask); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + thresh_val = reg_val; + } + + /* write the new t_cold value */ + reg_val = thresh_val & ~tsr->threshold_tcold_mask; + reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask)); + omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold); + if (err) { + dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n"); + return -EIO; + } + + return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold); +} + +/* This is Tshut Thot config. Call it only if HAS(TSHUT_CONFIG) is set */ +static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr, + int id, int tshut_hot) +{ + struct temp_sensor_registers *tsr; + u32 reg_val; + + tsr = bg_ptr->conf->sensors[id].registers; + reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold); + reg_val &= ~tsr->tshut_hot_mask; + reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask); + omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold); + + return 0; +} + +/* This is Tshut Tcold config. Call it only if HAS(TSHUT_CONFIG) is set */ +static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr, + int id, int tshut_cold) +{ + struct temp_sensor_registers *tsr; + u32 reg_val; + + tsr = bg_ptr->conf->sensors[id].registers; + reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold); + reg_val &= ~tsr->tshut_cold_mask; + reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask); + omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold); + + return 0; +} + +/* This is counter config. Call it only if HAS(COUNTER) is set */ +static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id, + u32 counter) +{ + struct temp_sensor_registers *tsr; + u32 val; + + tsr = bg_ptr->conf->sensors[id].registers; + val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter); + val &= ~tsr->counter_mask; + val |= counter << __ffs(tsr->counter_mask); + omap_bandgap_writel(bg_ptr, val, tsr->bgap_counter); + + return 0; +} + +#define bandgap_is_valid(b) \ + (!IS_ERR_OR_NULL(b)) +#define bandgap_is_valid_sensor_id(b, i) \ + ((i) >= 0 && (i) < (b)->conf->sensor_count) +static inline int omap_bandgap_validate(struct omap_bandgap *bg_ptr, int id) +{ + if (!bandgap_is_valid(bg_ptr)) { + pr_err("%s: invalid bandgap pointer\n", __func__); + return -EINVAL; + } + + if (!bandgap_is_valid_sensor_id(bg_ptr, id)) { + dev_err(bg_ptr->dev, "%s: sensor id out of range (%d)\n", + __func__, id); + return -ERANGE; + } + + return 0; +} + +/* Exposed APIs */ +/** + * omap_bandgap_read_thot() - reads sensor current thot + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @thot - resulting current thot value + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, + int *thot) +{ + struct temp_sensor_registers *tsr; + u32 temp; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + return -ENOTSUPP; + + tsr = bg_ptr->conf->sensors[id].registers; + temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + temp = (temp & tsr->threshold_thot_mask) >> + __ffs(tsr->threshold_thot_mask); + ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp); + if (ret) { + dev_err(bg_ptr->dev, "failed to read thot\n"); + return -EIO; + } + + *thot = temp; + + return 0; +} + +/** + * omap_bandgap_write_thot() - sets sensor current thot + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @val - desired thot value + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val) +{ + struct temp_sensor_data *ts_data; + struct temp_sensor_registers *tsr; + u32 t_hot; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + return -ENOTSUPP; + + ts_data = bg_ptr->conf->sensors[id].ts_data; + tsr = bg_ptr->conf->sensors[id].registers; + + if (val < ts_data->min_temp + ts_data->hyst_val) + return -EINVAL; + ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot); + if (ret < 0) + return ret; + + mutex_lock(&bg_ptr->bg_mutex); + temp_sensor_configure_thot(bg_ptr, id, t_hot); + mutex_unlock(&bg_ptr->bg_mutex); + + return 0; +} + +/** + * omap_bandgap_read_tcold() - reads sensor current tcold + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @tcold - resulting current tcold value + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, + int *tcold) +{ + struct temp_sensor_registers *tsr; + u32 temp; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + return -ENOTSUPP; + + tsr = bg_ptr->conf->sensors[id].registers; + temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold); + temp = (temp & tsr->threshold_tcold_mask) + >> __ffs(tsr->threshold_tcold_mask); + ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp); + if (ret) + return -EIO; + + *tcold = temp; + + return 0; +} + +/** + * omap_bandgap_write_tcold() - sets the sensor tcold + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @val - desired tcold value + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val) +{ + struct temp_sensor_data *ts_data; + struct temp_sensor_registers *tsr; + u32 t_cold; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + return -ENOTSUPP; + + ts_data = bg_ptr->conf->sensors[id].ts_data; + tsr = bg_ptr->conf->sensors[id].registers; + if (val > ts_data->max_temp + ts_data->hyst_val) + return -EINVAL; + + ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold); + if (ret < 0) + return ret; + + mutex_lock(&bg_ptr->bg_mutex); + temp_sensor_configure_tcold(bg_ptr, id, t_cold); + mutex_unlock(&bg_ptr->bg_mutex); + + return 0; +} + +/** + * omap_bandgap_read_update_interval() - read the sensor update interval + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @interval - resulting update interval in miliseconds + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id, + int *interval) +{ + struct temp_sensor_registers *tsr; + u32 time; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + return -ENOTSUPP; + + tsr = bg_ptr->conf->sensors[id].registers; + time = omap_bandgap_readl(bg_ptr, tsr->bgap_counter); + if (ret) + return ret; + time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask); + time = time * 1000 / bg_ptr->clk_rate; + + *interval = time; + + return 0; +} + +/** + * omap_bandgap_write_update_interval() - set the update interval + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @interval - desired update interval in miliseconds + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, + int id, u32 interval) +{ + int ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + return -ENOTSUPP; + + interval = interval * bg_ptr->clk_rate / 1000; + mutex_lock(&bg_ptr->bg_mutex); + configure_temp_sensor_counter(bg_ptr, id, interval); + mutex_unlock(&bg_ptr->bg_mutex); + + return 0; +} + +/** + * omap_bandgap_read_temperature() - report current temperature + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @temperature - resulting temperature + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id, + int *temperature) +{ + struct temp_sensor_registers *tsr; + u32 temp; + int ret; + + ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + tsr = bg_ptr->conf->sensors[id].registers; + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= tsr->bgap_dtemp_mask; + + ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp); + if (ret) + return -EIO; + + *temperature = temp; + + return 0; +} + +/** + * omap_bandgap_set_sensor_data() - helper function to store thermal + * framework related data. + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * @data - thermal framework related data to be stored + * + * returns 0 on success or the proper error code + */ +int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id, + void *data) +{ + int ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ret; + + bg_ptr->conf->sensors[id].data = data; + + return 0; +} + +/** + * omap_bandgap_get_sensor_data() - helper function to get thermal + * framework related data. + * @bg_ptr - pointer to bandgap instance + * @id - sensor id + * + * returns data stored by set function with sensor id on success or NULL + */ +void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id) +{ + int ret = omap_bandgap_validate(bg_ptr, id); + if (ret) + return ERR_PTR(ret); + + return bg_ptr->conf->sensors[id].data; +} + +static int +omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id) +{ + struct temp_sensor_registers *tsr; + u32 temp = 0, counter = 1000; + + tsr = bg_ptr->conf->sensors[id].registers; + /* Select single conversion mode */ + if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) { + temp = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl); + temp &= ~(1 << __ffs(tsr->mode_ctrl_mask)); + omap_bandgap_writel(bg_ptr, temp, tsr->bgap_mode_ctrl); + } + + /* Start of Conversion = 1 */ + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp |= 1 << __ffs(tsr->bgap_soc_mask); + omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl); + /* Wait until DTEMP is updated */ + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= (tsr->bgap_dtemp_mask); + while ((temp == 0) && --counter) { + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= (tsr->bgap_dtemp_mask); + } + /* Start of Conversion = 0 */ + temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl); + temp &= ~(1 << __ffs(tsr->bgap_soc_mask)); + omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl); + + return 0; +} + +/** + * enable_continuous_mode() - One time enabling of continuous conversion mode + * @bg_ptr - pointer to scm instance + * + * Call this function only if HAS(MODE_CONFIG) is set + */ +static int enable_continuous_mode(struct omap_bandgap *bg_ptr) +{ + struct temp_sensor_registers *tsr; + int i; + u32 val; + + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + /* Perform a single read just before enabling continuous */ + omap_bandgap_force_single_read(bg_ptr, i); + tsr = bg_ptr->conf->sensors[i].registers; + val = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl); + val |= 1 << __ffs(tsr->mode_ctrl_mask); + omap_bandgap_writel(bg_ptr, val, tsr->bgap_mode_ctrl); + } + + return 0; +} + +static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr, + struct platform_device *pdev) +{ + int gpio_nr = bg_ptr->tshut_gpio; + int status; + + /* Request for gpio_86 line */ + status = gpio_request(gpio_nr, "tshut"); + if (status < 0) { + dev_err(bg_ptr->dev, + "Could not request for TSHUT GPIO:%i\n", 86); + return status; + } + status = gpio_direction_input(gpio_nr); + if (status) { + dev_err(bg_ptr->dev, + "Cannot set input TSHUT GPIO %d\n", gpio_nr); + return status; + } + + status = request_irq(gpio_to_irq(gpio_nr), + omap_bandgap_tshut_irq_handler, + IRQF_TRIGGER_RISING, "tshut", + NULL); + if (status) { + gpio_free(gpio_nr); + dev_err(bg_ptr->dev, "request irq failed for TSHUT"); + } + + return 0; +} + +/* Initialization of Talert. Call it only if HAS(TALERT) is set */ +static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr, + struct platform_device *pdev) +{ + int ret; + + bg_ptr->irq = platform_get_irq(pdev, 0); + if (bg_ptr->irq < 0) { + dev_err(&pdev->dev, "get_irq failed\n"); + return bg_ptr->irq; + } + ret = request_threaded_irq(bg_ptr->irq, NULL, + talert_irq_handler, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "talert", bg_ptr); + if (ret) { + dev_err(&pdev->dev, "Request threaded irq failed.\n"); + return ret; + } + + return 0; +} + +static const struct of_device_id of_omap_bandgap_match[]; +static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + const struct of_device_id *of_id; + struct omap_bandgap *bg_ptr; + struct resource *res; + u32 prop; + int i; + + /* just for the sake */ + if (!node) { + dev_err(&pdev->dev, "no platform information available\n"); + return ERR_PTR(-EINVAL); + } + + bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap), + GFP_KERNEL); + if (!bg_ptr) { + dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); + return ERR_PTR(-ENOMEM); + } + + of_id = of_match_device(of_omap_bandgap_match, &pdev->dev); + if (of_id) + bg_ptr->conf = of_id->data; + + i = 0; + do { + void __iomem *chunk; + + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + break; + chunk = devm_request_and_ioremap(&pdev->dev, res); + if (i == 0) + bg_ptr->base = chunk; + if (!chunk) { + dev_err(&pdev->dev, + "failed to request the IO (%d:%pR).\n", + i, res); + return ERR_PTR(-EADDRNOTAVAIL); + } + i++; + } while (res); + + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) { + if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) { + dev_err(&pdev->dev, "missing tshut gpio in device tree\n"); + return ERR_PTR(-EINVAL); + } + bg_ptr->tshut_gpio = prop; + if (!gpio_is_valid(bg_ptr->tshut_gpio)) { + dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", + bg_ptr->tshut_gpio); + return ERR_PTR(-EINVAL); + } + } + + return bg_ptr; +} + +static +int __devinit omap_bandgap_probe(struct platform_device *pdev) +{ + struct omap_bandgap *bg_ptr; + int clk_rate, ret = 0, i; + + bg_ptr = omap_bandgap_build(pdev); + if (IS_ERR_OR_NULL(bg_ptr)) { + dev_err(&pdev->dev, "failed to fetch platform data\n"); + return PTR_ERR(bg_ptr); + } + bg_ptr->dev = &pdev->dev; + + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) { + ret = omap_bandgap_tshut_init(bg_ptr, pdev); + if (ret) { + dev_err(&pdev->dev, + "failed to initialize system tshut IRQ\n"); + return ret; + } + } + + bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name); + ret = IS_ERR_OR_NULL(bg_ptr->fclock); + if (ret) { + dev_err(&pdev->dev, "failed to request fclock reference\n"); + goto free_irqs; + } + + bg_ptr->div_clk = clk_get(NULL, bg_ptr->conf->div_ck_name); + ret = IS_ERR_OR_NULL(bg_ptr->div_clk); + if (ret) { + dev_err(&pdev->dev, + "failed to request div_ts_ck clock ref\n"); + goto free_irqs; + } + + bg_ptr->conv_table = bg_ptr->conf->conv_table; + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + struct temp_sensor_registers *tsr; + u32 val; + + tsr = bg_ptr->conf->sensors[i].registers; + /* + * check if the efuse has a non-zero value if not + * it is an untrimmed sample and the temperatures + * may not be accurate + */ + val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse); + if (ret || !val) + dev_info(&pdev->dev, + "Non-trimmed BGAP, Temp not accurate\n"); + } + + clk_rate = clk_round_rate(bg_ptr->div_clk, + bg_ptr->conf->sensors[0].ts_data->max_freq); + if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq || + clk_rate == 0xffffffff) { + ret = -ENODEV; + dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate); + goto put_clks; + } + + ret = clk_set_rate(bg_ptr->div_clk, clk_rate); + if (ret) + dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n"); + + bg_ptr->clk_rate = clk_rate; + clk_enable(bg_ptr->fclock); + + mutex_init(&bg_ptr->bg_mutex); + bg_ptr->dev = &pdev->dev; + platform_set_drvdata(pdev, bg_ptr); + + omap_bandgap_power(bg_ptr, true); + + /* Set default counter to 1 for now */ + if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + for (i = 0; i < bg_ptr->conf->sensor_count; i++) + configure_temp_sensor_counter(bg_ptr, i, 1); + + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + struct temp_sensor_data *ts_data; + + ts_data = bg_ptr->conf->sensors[i].ts_data; + + if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + temp_sensor_init_talert_thresholds(bg_ptr, i, + ts_data->t_hot, + ts_data->t_cold); + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) { + temp_sensor_configure_tshut_hot(bg_ptr, i, + ts_data->tshut_hot); + temp_sensor_configure_tshut_cold(bg_ptr, i, + ts_data->tshut_cold); + } + } + + if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) + enable_continuous_mode(bg_ptr); + + /* Set .250 seconds time as default counter */ + if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + for (i = 0; i < bg_ptr->conf->sensor_count; i++) + configure_temp_sensor_counter(bg_ptr, i, + bg_ptr->clk_rate / 4); + + /* Every thing is good? Then expose the sensors */ + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + char *domain; + + domain = bg_ptr->conf->sensors[i].domain; + if (bg_ptr->conf->expose_sensor) + bg_ptr->conf->expose_sensor(bg_ptr, i, domain); + + if (bg_ptr->conf->sensors[i].register_cooling) + bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i); + } + + /* + * Enable the Interrupts once everything is set. Otherwise irq handler + * might be called as soon as it is enabled where as rest of framework + * is still getting initialised. + */ + if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) { + ret = omap_bandgap_talert_init(bg_ptr, pdev); + if (ret) { + dev_err(&pdev->dev, "failed to initialize Talert IRQ\n"); + i = bg_ptr->conf->sensor_count; + goto disable_clk; + } + } + + return 0; + +disable_clk: + clk_disable(bg_ptr->fclock); +put_clks: + clk_put(bg_ptr->fclock); + clk_put(bg_ptr->div_clk); +free_irqs: + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) { + free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL); + gpio_free(bg_ptr->tshut_gpio); + } + + return ret; +} + +static +int __devexit omap_bandgap_remove(struct platform_device *pdev) +{ + struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev); + int i; + + /* First thing is to remove sensor interfaces */ + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + if (bg_ptr->conf->sensors[i].register_cooling) + bg_ptr->conf->sensors[i].unregister_cooling(bg_ptr, i); + + if (bg_ptr->conf->remove_sensor) + bg_ptr->conf->remove_sensor(bg_ptr, i); + } + + omap_bandgap_power(bg_ptr, false); + + clk_disable(bg_ptr->fclock); + clk_put(bg_ptr->fclock); + clk_put(bg_ptr->div_clk); + + if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) + free_irq(bg_ptr->irq, bg_ptr); + + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) { + free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL); + gpio_free(bg_ptr->tshut_gpio); + } + + return 0; +} + +#ifdef CONFIG_PM +static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr) +{ + int i; + + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + struct temp_sensor_registers *tsr; + struct temp_sensor_regval *rval; + + rval = &bg_ptr->conf->sensors[i].regval; + tsr = bg_ptr->conf->sensors[i].registers; + + if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) + rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr, + tsr->bgap_mode_ctrl); + if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + rval->bg_counter = omap_bandgap_readl(bg_ptr, + tsr->bgap_counter); + if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) { + rval->bg_threshold = omap_bandgap_readl(bg_ptr, + tsr->bgap_threshold); + rval->bg_ctrl = omap_bandgap_readl(bg_ptr, + tsr->bgap_mask_ctrl); + } + + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) + rval->tshut_threshold = omap_bandgap_readl(bg_ptr, + tsr->tshut_threshold); + } + + return 0; +} + +static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr) +{ + int i; + u32 temp = 0; + + for (i = 0; i < bg_ptr->conf->sensor_count; i++) { + struct temp_sensor_registers *tsr; + struct temp_sensor_regval *rval; + u32 val = 0; + + rval = &bg_ptr->conf->sensors[i].regval; + tsr = bg_ptr->conf->sensors[i].registers; + + if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter); + + if (val == 0) { + if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) + omap_bandgap_writel(bg_ptr, rval->tshut_threshold, + tsr->tshut_threshold); + /* Force immediate temperature measurement and update + * of the DTEMP field + */ + omap_bandgap_force_single_read(bg_ptr, i); + + if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) + omap_bandgap_writel(bg_ptr, rval->bg_counter, + tsr->bgap_counter); + if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) + omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl, + tsr->bgap_mode_ctrl); + if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) { + omap_bandgap_writel(bg_ptr, + rval->bg_threshold, + tsr->bgap_threshold); + omap_bandgap_writel(bg_ptr, rval->bg_ctrl, + tsr->bgap_mask_ctrl); + } + } else { + temp = omap_bandgap_readl(bg_ptr, + tsr->temp_sensor_ctrl); + temp &= (tsr->bgap_dtemp_mask); + omap_bandgap_force_single_read(bg_ptr, i); + if (temp == 0 && OMAP_BANDGAP_HAS(bg_ptr, TALERT)) { + temp = omap_bandgap_readl(bg_ptr, + tsr->bgap_mask_ctrl); + temp |= 1 << __ffs(tsr->mode_ctrl_mask); + omap_bandgap_writel(bg_ptr, temp, + tsr->bgap_mask_ctrl); + } + } + } + + return 0; +} + +static int omap_bandgap_suspend(struct device *dev) +{ + struct omap_bandgap *bg_ptr = dev_get_drvdata(dev); + int err; + + err = omap_bandgap_save_ctxt(bg_ptr); + omap_bandgap_power(bg_ptr, false); + clk_disable(bg_ptr->fclock); + + return err; +} + +static int omap_bandgap_resume(struct device *dev) +{ + struct omap_bandgap *bg_ptr = dev_get_drvdata(dev); + + clk_enable(bg_ptr->fclock); + omap_bandgap_power(bg_ptr, true); + + return omap_bandgap_restore_ctxt(bg_ptr); +} +static const struct dev_pm_ops omap_bandgap_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend, + omap_bandgap_resume) +}; + +#define DEV_PM_OPS (&omap_bandgap_dev_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +static const struct of_device_id of_omap_bandgap_match[] = { +#ifdef CONFIG_OMAP4_THERMAL + { + .compatible = "ti,omap4430-bandgap", + .data = (void *)&omap4430_data, + }, + { + .compatible = "ti,omap4460-bandgap", + .data = (void *)&omap4460_data, + }, + { + .compatible = "ti,omap4470-bandgap", + .data = (void *)&omap4470_data, + }, +#endif +#ifdef CONFIG_OMAP5_THERMAL + { + .compatible = "ti,omap5430-bandgap", + .data = (void *)&omap5430_data, + }, +#endif + /* Sentinel */ + { }, +}; +MODULE_DEVICE_TABLE(of, of_omap_bandgap_match); + +static struct platform_driver omap_bandgap_sensor_driver = { + .probe = omap_bandgap_probe, + .remove = omap_bandgap_remove, + .driver = { + .name = "omap-bandgap", + .pm = DEV_PM_OPS, + .of_match_table = of_omap_bandgap_match, + }, +}; + +module_platform_driver(omap_bandgap_sensor_driver); + +MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:omap-bandgap"); +MODULE_AUTHOR("Texas Instrument Inc."); diff --git a/trunk/drivers/staging/omap-thermal/omap-bandgap.h b/trunk/drivers/staging/omap-thermal/omap-bandgap.h new file mode 100644 index 000000000000..78aed7535f47 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap-bandgap.h @@ -0,0 +1,441 @@ +/* + * OMAP4 Bandgap temperature sensor driver + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Contact: + * Eduardo Valentin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __OMAP_BANDGAP_H +#define __OMAP_BANDGAP_H + +#include +#include +#include + +/* TEMP_SENSOR OMAP4430 */ +#define OMAP4430_BGAP_TSHUT_SHIFT 11 +#define OMAP4430_BGAP_TSHUT_MASK (1 << 11) + +/* TEMP_SENSOR OMAP4430 */ +#define OMAP4430_BGAP_TEMPSOFF_SHIFT 12 +#define OMAP4430_BGAP_TEMPSOFF_MASK (1 << 12) +#define OMAP4430_SINGLE_MODE_SHIFT 10 +#define OMAP4430_SINGLE_MODE_MASK (1 << 10) +#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT 9 +#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK (1 << 9) +#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT 8 +#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 8) +#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0 +#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0) + +#define OMAP4430_ADC_START_VALUE 0 +#define OMAP4430_ADC_END_VALUE 127 +#define OMAP4430_MAX_FREQ 32768 +#define OMAP4430_MIN_FREQ 32768 +#define OMAP4430_MIN_TEMP -40000 +#define OMAP4430_MAX_TEMP 125000 +#define OMAP4430_HYST_VAL 5000 + +/* TEMP_SENSOR OMAP4460 */ +#define OMAP4460_BGAP_TEMPSOFF_SHIFT 13 +#define OMAP4460_BGAP_TEMPSOFF_MASK (1 << 13) +#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT 11 +#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK (1 << 11) +#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10 +#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10) +#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0 +#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) + +/* BANDGAP_CTRL */ +#define OMAP4460_SINGLE_MODE_SHIFT 31 +#define OMAP4460_SINGLE_MODE_MASK (1 << 31) +#define OMAP4460_MASK_HOT_SHIFT 1 +#define OMAP4460_MASK_HOT_MASK (1 << 1) +#define OMAP4460_MASK_COLD_SHIFT 0 +#define OMAP4460_MASK_COLD_MASK (1 << 0) + +/* BANDGAP_COUNTER */ +#define OMAP4460_COUNTER_SHIFT 0 +#define OMAP4460_COUNTER_MASK (0xffffff << 0) + +/* BANDGAP_THRESHOLD */ +#define OMAP4460_T_HOT_SHIFT 16 +#define OMAP4460_T_HOT_MASK (0x3ff << 16) +#define OMAP4460_T_COLD_SHIFT 0 +#define OMAP4460_T_COLD_MASK (0x3ff << 0) + +/* TSHUT_THRESHOLD */ +#define OMAP4460_TSHUT_HOT_SHIFT 16 +#define OMAP4460_TSHUT_HOT_MASK (0x3ff << 16) +#define OMAP4460_TSHUT_COLD_SHIFT 0 +#define OMAP4460_TSHUT_COLD_MASK (0x3ff << 0) + +/* BANDGAP_STATUS */ +#define OMAP4460_CLEAN_STOP_SHIFT 3 +#define OMAP4460_CLEAN_STOP_MASK (1 << 3) +#define OMAP4460_BGAP_ALERT_SHIFT 2 +#define OMAP4460_BGAP_ALERT_MASK (1 << 2) +#define OMAP4460_HOT_FLAG_SHIFT 1 +#define OMAP4460_HOT_FLAG_MASK (1 << 1) +#define OMAP4460_COLD_FLAG_SHIFT 0 +#define OMAP4460_COLD_FLAG_MASK (1 << 0) + +/* TEMP_SENSOR OMAP5430 */ +#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT 12 +#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK (1 << 12) +#define OMAP5430_BGAP_TEMPSOFF_SHIFT 11 +#define OMAP5430_BGAP_TEMPSOFF_MASK (1 << 11) +#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10 +#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10) +#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0 +#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) + +/* BANDGAP_CTRL */ +#define OMAP5430_MASK_HOT_CORE_SHIFT 5 +#define OMAP5430_MASK_HOT_CORE_MASK (1 << 5) +#define OMAP5430_MASK_COLD_CORE_SHIFT 4 +#define OMAP5430_MASK_COLD_CORE_MASK (1 << 4) +#define OMAP5430_MASK_HOT_MM_SHIFT 3 +#define OMAP5430_MASK_HOT_MM_MASK (1 << 3) +#define OMAP5430_MASK_COLD_MM_SHIFT 2 +#define OMAP5430_MASK_COLD_MM_MASK (1 << 2) +#define OMAP5430_MASK_HOT_MPU_SHIFT 1 +#define OMAP5430_MASK_HOT_MPU_MASK (1 << 1) +#define OMAP5430_MASK_COLD_MPU_SHIFT 0 +#define OMAP5430_MASK_COLD_MPU_MASK (1 << 0) + +/* BANDGAP_COUNTER */ +#define OMAP5430_REPEAT_MODE_SHIFT 31 +#define OMAP5430_REPEAT_MODE_MASK (1 << 31) +#define OMAP5430_COUNTER_SHIFT 0 +#define OMAP5430_COUNTER_MASK (0xffffff << 0) + +/* BANDGAP_THRESHOLD */ +#define OMAP5430_T_HOT_SHIFT 16 +#define OMAP5430_T_HOT_MASK (0x3ff << 16) +#define OMAP5430_T_COLD_SHIFT 0 +#define OMAP5430_T_COLD_MASK (0x3ff << 0) + +/* TSHUT_THRESHOLD */ +#define OMAP5430_TSHUT_HOT_SHIFT 16 +#define OMAP5430_TSHUT_HOT_MASK (0x3ff << 16) +#define OMAP5430_TSHUT_COLD_SHIFT 0 +#define OMAP5430_TSHUT_COLD_MASK (0x3ff << 0) + +/* BANDGAP_STATUS */ +#define OMAP5430_BGAP_ALERT_SHIFT 31 +#define OMAP5430_BGAP_ALERT_MASK (1 << 31) +#define OMAP5430_HOT_CORE_FLAG_SHIFT 5 +#define OMAP5430_HOT_CORE_FLAG_MASK (1 << 5) +#define OMAP5430_COLD_CORE_FLAG_SHIFT 4 +#define OMAP5430_COLD_CORE_FLAG_MASK (1 << 4) +#define OMAP5430_HOT_MM_FLAG_SHIFT 3 +#define OMAP5430_HOT_MM_FLAG_MASK (1 << 3) +#define OMAP5430_COLD_MM_FLAG_SHIFT 2 +#define OMAP5430_COLD_MM_FLAG_MASK (1 << 2) +#define OMAP5430_HOT_MPU_FLAG_SHIFT 1 +#define OMAP5430_HOT_MPU_FLAG_MASK (1 << 1) +#define OMAP5430_COLD_MPU_FLAG_SHIFT 0 +#define OMAP5430_COLD_MPU_FLAG_MASK (1 << 0) + +/* Offsets from the base of temperature sensor registers */ + +/* 4430 - All goes relative to OPP_BGAP */ +#define OMAP4430_FUSE_OPP_BGAP 0x0 +#define OMAP4430_TEMP_SENSOR_CTRL_OFFSET 0xCC + +/* 4460 - All goes relative to OPP_BGAP */ +#define OMAP4460_FUSE_OPP_BGAP 0x0 +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET 0xCC +#define OMAP4460_BGAP_CTRL_OFFSET 0x118 +#define OMAP4460_BGAP_COUNTER_OFFSET 0x11C +#define OMAP4460_BGAP_THRESHOLD_OFFSET 0x120 +#define OMAP4460_BGAP_TSHUT_OFFSET 0x124 +#define OMAP4460_BGAP_STATUS_OFFSET 0x128 + +/* 5430 - All goes relative to OPP_BGAP_GPU */ +#define OMAP5430_FUSE_OPP_BGAP_GPU 0x0 +#define OMAP5430_TEMP_SENSOR_GPU_OFFSET 0x150 +#define OMAP5430_BGAP_COUNTER_GPU_OFFSET 0x1C0 +#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET 0x1A8 +#define OMAP5430_BGAP_TSHUT_GPU_OFFSET 0x1B4 + +#define OMAP5430_FUSE_OPP_BGAP_MPU 0x4 +#define OMAP5430_TEMP_SENSOR_MPU_OFFSET 0x14C +#define OMAP5430_BGAP_CTRL_OFFSET 0x1A0 +#define OMAP5430_BGAP_COUNTER_MPU_OFFSET 0x1BC +#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET 0x1A4 +#define OMAP5430_BGAP_TSHUT_MPU_OFFSET 0x1B0 +#define OMAP5430_BGAP_STATUS_OFFSET 0x1C8 + +#define OMAP5430_FUSE_OPP_BGAP_CORE 0x8 +#define OMAP5430_TEMP_SENSOR_CORE_OFFSET 0x154 +#define OMAP5430_BGAP_COUNTER_CORE_OFFSET 0x1C4 +#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET 0x1AC +#define OMAP5430_BGAP_TSHUT_CORE_OFFSET 0x1B8 + +#define OMAP4460_TSHUT_HOT 900 /* 122 deg C */ +#define OMAP4460_TSHUT_COLD 895 /* 100 deg C */ +#define OMAP4460_T_HOT 800 /* 73 deg C */ +#define OMAP4460_T_COLD 795 /* 71 deg C */ +#define OMAP4460_MAX_FREQ 1500000 +#define OMAP4460_MIN_FREQ 1000000 +#define OMAP4460_MIN_TEMP -40000 +#define OMAP4460_MAX_TEMP 123000 +#define OMAP4460_HYST_VAL 5000 +#define OMAP4460_ADC_START_VALUE 530 +#define OMAP4460_ADC_END_VALUE 932 + +#define OMAP5430_MPU_TSHUT_HOT 915 +#define OMAP5430_MPU_TSHUT_COLD 900 +#define OMAP5430_MPU_T_HOT 800 +#define OMAP5430_MPU_T_COLD 795 +#define OMAP5430_MPU_MAX_FREQ 1500000 +#define OMAP5430_MPU_MIN_FREQ 1000000 +#define OMAP5430_MPU_MIN_TEMP -40000 +#define OMAP5430_MPU_MAX_TEMP 125000 +#define OMAP5430_MPU_HYST_VAL 5000 +#define OMAP5430_ADC_START_VALUE 532 +#define OMAP5430_ADC_END_VALUE 934 + + +#define OMAP5430_GPU_TSHUT_HOT 915 +#define OMAP5430_GPU_TSHUT_COLD 900 +#define OMAP5430_GPU_T_HOT 800 +#define OMAP5430_GPU_T_COLD 795 +#define OMAP5430_GPU_MAX_FREQ 1500000 +#define OMAP5430_GPU_MIN_FREQ 1000000 +#define OMAP5430_GPU_MIN_TEMP -40000 +#define OMAP5430_GPU_MAX_TEMP 125000 +#define OMAP5430_GPU_HYST_VAL 5000 + +#define OMAP5430_CORE_TSHUT_HOT 915 +#define OMAP5430_CORE_TSHUT_COLD 900 +#define OMAP5430_CORE_T_HOT 800 +#define OMAP5430_CORE_T_COLD 795 +#define OMAP5430_CORE_MAX_FREQ 1500000 +#define OMAP5430_CORE_MIN_FREQ 1000000 +#define OMAP5430_CORE_MIN_TEMP -40000 +#define OMAP5430_CORE_MAX_TEMP 125000 +#define OMAP5430_CORE_HYST_VAL 5000 + +/** + * The register offsets and bit fields might change across + * OMAP versions hence populating them in this structure. + */ + +struct temp_sensor_registers { + u32 temp_sensor_ctrl; + u32 bgap_tempsoff_mask; + u32 bgap_soc_mask; + u32 bgap_eocz_mask; + u32 bgap_dtemp_mask; + + u32 bgap_mask_ctrl; + u32 mask_hot_mask; + u32 mask_cold_mask; + + u32 bgap_mode_ctrl; + u32 mode_ctrl_mask; + + u32 bgap_counter; + u32 counter_mask; + + u32 bgap_threshold; + u32 threshold_thot_mask; + u32 threshold_tcold_mask; + + u32 tshut_threshold; + u32 tshut_hot_mask; + u32 tshut_cold_mask; + + u32 bgap_status; + u32 status_clean_stop_mask; + u32 status_bgap_alert_mask; + u32 status_hot_mask; + u32 status_cold_mask; + + u32 bgap_efuse; +}; + +/** + * The thresholds and limits for temperature sensors. + */ +struct temp_sensor_data { + u32 tshut_hot; + u32 tshut_cold; + u32 t_hot; + u32 t_cold; + u32 min_freq; + u32 max_freq; + int max_temp; + int min_temp; + int hyst_val; + u32 adc_start_val; + u32 adc_end_val; + u32 update_int1; + u32 update_int2; +}; + +struct omap_bandgap_data; + +/** + * struct omap_bandgap - bandgap device structure + * @dev: device pointer + * @conf: platform data with sensor data + * @fclock: pointer to functional clock of temperature sensor + * @div_clk: pointer to parent clock of temperature sensor fclk + * @conv_table: Pointer to adc to temperature conversion table + * @bg_mutex: Mutex for sysfs, irq and PM + * @irq: MPU Irq number for thermal alert + * @tshut_gpio: GPIO where Tshut signal is routed + * @clk_rate: Holds current clock rate + */ +struct omap_bandgap { + struct device *dev; + void __iomem *base; + struct omap_bandgap_data *conf; + struct clk *fclock; + struct clk *div_clk; + const int *conv_table; + struct mutex bg_mutex; /* Mutex for irq and PM */ + int irq; + int tshut_gpio; + u32 clk_rate; +}; + +/** + * struct temp_sensor_regval - temperature sensor register values + * @bg_mode_ctrl: temp sensor control register value + * @bg_ctrl: bandgap ctrl register value + * @bg_counter: bandgap counter value + * @bg_threshold: bandgap threshold register value + * @tshut_threshold: bandgap tshut register value + */ +struct temp_sensor_regval { + u32 bg_mode_ctrl; + u32 bg_ctrl; + u32 bg_counter; + u32 bg_threshold; + u32 tshut_threshold; +}; + +/** + * struct thermal_cooling_conf - description on how to cool a thermal zone + * @freq_clip_count: size of freq_data + */ +struct thermal_cooling_conf { + int freq_clip_count; +}; + +/** + * struct omap_temp_sensor - bandgap temperature sensor platform data + * @ts_data: pointer to struct with thresholds, limits of temperature sensor + * @registers: pointer to the list of register offsets and bitfields + * @regval: temperature sensor register values + * @domain: the name of the domain where the sensor is located + * @cooling_data: description on how the zone should be cooled off. + * @slope: sensor gradient slope info for hotspot extrapolation + * @const: sensor gradient const info for hotspot extrapolation + * @slope_pcb: sensor gradient slope info for hotspot extrapolation + * with no external influence + * @const_pcb: sensor gradient const info for hotspot extrapolation + * with no external influence + * @data: private data + * @register_cooling: function to describe how this sensor is going to be cooled + * @unregister_cooling: function to release cooling data + */ +struct omap_temp_sensor { + struct temp_sensor_data *ts_data; + struct temp_sensor_registers *registers; + struct temp_sensor_regval regval; + char *domain; + struct thermal_cooling_conf cooling_data; + /* for hotspot extrapolation */ + const int slope; + const int constant; + const int slope_pcb; + const int constant_pcb; + void *data; + int (*register_cooling)(struct omap_bandgap *bg_ptr, int id); + int (*unregister_cooling)(struct omap_bandgap *bg_ptr, int id); +}; + +/** + * struct omap_bandgap_data - bandgap platform data structure + * @features: a bitwise flag set to describe the device features + * @conv_table: Pointer to adc to temperature conversion table + * @fclock_name: clock name of the functional clock + * @div_ck_nme: clock name of the clock divisor + * @sensor_count: count of temperature sensor device in scm + * @sensors: array of sensors present in this bandgap instance + * @expose_sensor: callback to export sensor to thermal API + */ +struct omap_bandgap_data { +#define OMAP_BANDGAP_FEATURE_TSHUT (1 << 0) +#define OMAP_BANDGAP_FEATURE_TSHUT_CONFIG (1 << 1) +#define OMAP_BANDGAP_FEATURE_TALERT (1 << 2) +#define OMAP_BANDGAP_FEATURE_MODE_CONFIG (1 << 3) +#define OMAP_BANDGAP_FEATURE_COUNTER (1 << 4) +#define OMAP_BANDGAP_FEATURE_POWER_SWITCH (1 << 5) +#define OMAP_BANDGAP_HAS(b, f) \ + ((b)->conf->features & OMAP_BANDGAP_FEATURE_ ## f) + unsigned int features; + const int *conv_table; + char *fclock_name; + char *div_ck_name; + int sensor_count; + int (*report_temperature)(struct omap_bandgap *bg_ptr, int id); + int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain); + int (*remove_sensor)(struct omap_bandgap *bg_ptr, int id); + + /* this needs to be at the end */ + struct omap_temp_sensor sensors[]; +}; + +int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot); +int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val); +int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold); +int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val); +int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id, + int *interval); +int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id, + u32 interval); +int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id, + int *temperature); +int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id, + void *data); +void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id); + +#ifdef CONFIG_OMAP4_THERMAL +extern const struct omap_bandgap_data omap4430_data; +extern const struct omap_bandgap_data omap4460_data; +extern const struct omap_bandgap_data omap4470_data; +#else +#define omap4430_data NULL +#define omap4460_data NULL +#define omap4470_data NULL +#endif + +#ifdef CONFIG_OMAP5_THERMAL +extern const struct omap_bandgap_data omap5430_data; +#else +#define omap5430_data NULL +#endif + +#endif diff --git a/trunk/drivers/staging/omap-thermal/omap-thermal-common.c b/trunk/drivers/staging/omap-thermal/omap-thermal-common.c new file mode 100644 index 000000000000..0675a5e2f7c8 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap-thermal-common.c @@ -0,0 +1,364 @@ +/* + * OMAP thermal driver interface + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Contact: + * Eduardo Valentin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "omap-thermal.h" +#include "omap-bandgap.h" + +/* common data structures */ +struct omap_thermal_data { + struct thermal_zone_device *omap_thermal; + struct thermal_cooling_device *cool_dev; + struct omap_bandgap *bg_ptr; + enum thermal_device_mode mode; + struct work_struct thermal_wq; + int sensor_id; +}; + +static void omap_thermal_work(struct work_struct *work) +{ + struct omap_thermal_data *data = container_of(work, + struct omap_thermal_data, thermal_wq); + + thermal_zone_device_update(data->omap_thermal); + + dev_dbg(&data->omap_thermal->device, "updated thermal zone %s\n", + data->omap_thermal->type); +} + +/** + * omap_thermal_hotspot_temperature - returns sensor extrapolated temperature + * @t: omap sensor temperature + * @s: omap sensor slope value + * @c: omap sensor const value + */ +static inline int omap_thermal_hotspot_temperature(int t, int s, int c) +{ + int delta = t * s / 1000 + c; + + if (delta < 0) + delta = 0; + + return t + delta; +} + +/* thermal zone ops */ +/* Get temperature callback function for thermal zone*/ +static inline int omap_thermal_get_temp(struct thermal_zone_device *thermal, + unsigned long *temp) +{ + struct omap_thermal_data *data = thermal->devdata; + struct omap_bandgap *bg_ptr = data->bg_ptr; + struct omap_temp_sensor *s = &bg_ptr->conf->sensors[data->sensor_id]; + int ret, tmp, pcb_temp, slope, constant; + + ret = omap_bandgap_read_temperature(bg_ptr, data->sensor_id, &tmp); + if (ret) + return ret; + + pcb_temp = 0; + /* TODO: Introduce pcb temperature lookup */ + /* In case pcb zone is available, use the extrapolation rule with it */ + if (pcb_temp) { + tmp -= pcb_temp; + slope = s->slope_pcb; + constant = s->constant_pcb; + } else { + slope = s->slope; + constant = s->constant; + } + *temp = omap_thermal_hotspot_temperature(tmp, slope, constant); + + return ret; +} + +/* Bind callback functions for thermal zone */ +static int omap_thermal_bind(struct thermal_zone_device *thermal, + struct thermal_cooling_device *cdev) +{ + struct omap_thermal_data *data = thermal->devdata; + int max, id; + + if (IS_ERR_OR_NULL(data)) + return -ENODEV; + + /* check if this is the cooling device we registered */ + if (data->cool_dev != cdev) + return 0; + + id = data->sensor_id; + max = data->bg_ptr->conf->sensors[id].cooling_data.freq_clip_count; + + /* TODO: bind with min and max states */ + /* Simple thing, two trips, one passive another critical */ + return thermal_zone_bind_cooling_device(thermal, 0, cdev); +} + +/* Unbind callback functions for thermal zone */ +static int omap_thermal_unbind(struct thermal_zone_device *thermal, + struct thermal_cooling_device *cdev) +{ + struct omap_thermal_data *data = thermal->devdata; + + if (IS_ERR_OR_NULL(data)) + return -ENODEV; + + /* check if this is the cooling device we registered */ + if (data->cool_dev != cdev) + return 0; + + /* Simple thing, two trips, one passive another critical */ + return thermal_zone_unbind_cooling_device(thermal, 0, cdev); +} + +/* Get mode callback functions for thermal zone */ +static int omap_thermal_get_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode *mode) +{ + struct omap_thermal_data *data = thermal->devdata; + + if (data) + *mode = data->mode; + + return 0; +} + +/* Set mode callback functions for thermal zone */ +static int omap_thermal_set_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode mode) +{ + struct omap_thermal_data *data = thermal->devdata; + + if (!data->omap_thermal) { + dev_notice(&thermal->device, "thermal zone not registered\n"); + return 0; + } + + mutex_lock(&data->omap_thermal->lock); + + if (mode == THERMAL_DEVICE_ENABLED) + data->omap_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; + else + data->omap_thermal->polling_delay = 0; + + mutex_unlock(&data->omap_thermal->lock); + + data->mode = mode; + thermal_zone_device_update(data->omap_thermal); + dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n", + data->omap_thermal->polling_delay); + + return 0; +} + +/* Get trip type callback functions for thermal zone */ +static int omap_thermal_get_trip_type(struct thermal_zone_device *thermal, + int trip, enum thermal_trip_type *type) +{ + if (!omap_thermal_is_valid_trip(trip)) + return -EINVAL; + + if (trip + 1 == OMAP_TRIP_NUMBER) + *type = THERMAL_TRIP_CRITICAL; + else + *type = THERMAL_TRIP_PASSIVE; + + return 0; +} + +/* Get trip temperature callback functions for thermal zone */ +static int omap_thermal_get_trip_temp(struct thermal_zone_device *thermal, + int trip, unsigned long *temp) +{ + if (!omap_thermal_is_valid_trip(trip)) + return -EINVAL; + + *temp = omap_thermal_get_trip_value(trip); + + return 0; +} + +/* Get critical temperature callback functions for thermal zone */ +static int omap_thermal_get_crit_temp(struct thermal_zone_device *thermal, + unsigned long *temp) +{ + /* shutdown zone */ + return omap_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp); +} + +static struct thermal_zone_device_ops omap_thermal_ops = { + .get_temp = omap_thermal_get_temp, + /* TODO: add .get_trend */ + .bind = omap_thermal_bind, + .unbind = omap_thermal_unbind, + .get_mode = omap_thermal_get_mode, + .set_mode = omap_thermal_set_mode, + .get_trip_type = omap_thermal_get_trip_type, + .get_trip_temp = omap_thermal_get_trip_temp, + .get_crit_temp = omap_thermal_get_crit_temp, +}; + +int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id, + char *domain) +{ + struct omap_thermal_data *data; + + data = devm_kzalloc(bg_ptr->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(bg_ptr->dev, "kzalloc fail\n"); + return -ENOMEM; + } + data->sensor_id = id; + data->bg_ptr = bg_ptr; + data->mode = THERMAL_DEVICE_ENABLED; + INIT_WORK(&data->thermal_wq, omap_thermal_work); + + /* TODO: remove TC1 TC2 */ + /* Create thermal zone */ + data->omap_thermal = thermal_zone_device_register(domain, + OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops, + 0, FAST_TEMP_MONITORING_RATE, 0, 0); + if (IS_ERR_OR_NULL(data->omap_thermal)) { + dev_err(bg_ptr->dev, "thermal zone device is NULL\n"); + return PTR_ERR(data->omap_thermal); + } + data->omap_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; + omap_bandgap_set_sensor_data(bg_ptr, id, data); + + return 0; +} + +int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id) +{ + struct omap_thermal_data *data; + + data = omap_bandgap_get_sensor_data(bg_ptr, id); + + thermal_zone_device_unregister(data->omap_thermal); + + return 0; +} + +int omap_thermal_report_sensor_temperature(struct omap_bandgap *bg_ptr, int id) +{ + struct omap_thermal_data *data; + + data = omap_bandgap_get_sensor_data(bg_ptr, id); + + schedule_work(&data->thermal_wq); + + return 0; +} + +static int omap_thermal_build_cpufreq_clip(struct omap_bandgap *bg_ptr, + struct freq_clip_table **tab_ptr, + int *tab_size) +{ + struct cpufreq_frequency_table *freq_table; + struct freq_clip_table *tab; + int i, count = 0; + + freq_table = cpufreq_frequency_get_table(0); + if (IS_ERR_OR_NULL(freq_table)) { + dev_err(bg_ptr->dev, + "%s: failed to get cpufreq table (%p)\n", + __func__, freq_table); + return -EINVAL; + } + + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned int freq = freq_table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + count++; + } + + tab = devm_kzalloc(bg_ptr->dev, sizeof(*tab) * count, GFP_KERNEL); + if (!tab) { + dev_err(bg_ptr->dev, + "%s: no memory available\n", __func__); + return -ENOMEM; + } + + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned int freq = freq_table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + + tab[count - i - 1].freq_clip_max = freq; + tab[count - i - 1].temp_level = OMAP_TRIP_HOT; + tab[count - i - 1].mask_val = cpumask_of(0); + } + + *tab_ptr = tab; + *tab_size = count; + + return 0; +} + +int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id) +{ + struct omap_thermal_data *data; + struct freq_clip_table *tab_ptr; + int tab_size, ret; + + data = omap_bandgap_get_sensor_data(bg_ptr, id); + + ret = omap_thermal_build_cpufreq_clip(bg_ptr, &tab_ptr, &tab_size); + if (ret < 0) { + dev_err(bg_ptr->dev, + "%s: failed to build cpufreq clip table\n", __func__); + return ret; + } + + /* Register cooling device */ + data->cool_dev = cpufreq_cooling_register(tab_ptr, tab_size); + if (IS_ERR_OR_NULL(data->cool_dev)) { + dev_err(bg_ptr->dev, + "Failed to register cpufreq cooling device\n"); + return PTR_ERR(data->cool_dev); + } + bg_ptr->conf->sensors[id].cooling_data.freq_clip_count = tab_size; + + return 0; +} + +int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id) +{ + struct omap_thermal_data *data; + + data = omap_bandgap_get_sensor_data(bg_ptr, id); + cpufreq_cooling_unregister(data->cool_dev); + + return 0; +} diff --git a/trunk/drivers/staging/omap-thermal/omap-thermal.h b/trunk/drivers/staging/omap-thermal/omap-thermal.h new file mode 100644 index 000000000000..0dd2184b9663 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap-thermal.h @@ -0,0 +1,108 @@ +/* + * OMAP thermal definitions + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Contact: + * Eduardo Valentin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __OMAP_THERMAL_H +#define __OMAP_THERMAL_H + +#include "omap-bandgap.h" + +/* sensors gradient and offsets */ +#define OMAP_GRADIENT_SLOPE_4460 348 +#define OMAP_GRADIENT_CONST_4460 -9301 +#define OMAP_GRADIENT_SLOPE_4470 308 +#define OMAP_GRADIENT_CONST_4470 -7896 + +#define OMAP_GRADIENT_SLOPE_5430_CPU 196 +#define OMAP_GRADIENT_CONST_5430_CPU -6822 +#define OMAP_GRADIENT_SLOPE_5430_GPU 64 +#define OMAP_GRADIENT_CONST_5430_GPU 978 + +/* PCB sensor calculation constants */ +#define OMAP_GRADIENT_SLOPE_W_PCB_4460 1142 +#define OMAP_GRADIENT_CONST_W_PCB_4460 -393 +#define OMAP_GRADIENT_SLOPE_W_PCB_4470 1063 +#define OMAP_GRADIENT_CONST_W_PCB_4470 -477 + +#define OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU 469 +#define OMAP_GRADIENT_CONST_W_PCB_5430_CPU -1272 +#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 378 +#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU 154 + +/* trip points of interest in milicelsius (at hotspot level) */ +#define OMAP_TRIP_COLD 100000 +#define OMAP_TRIP_HOT 110000 +#define OMAP_TRIP_SHUTDOWN 125000 +#define OMAP_TRIP_NUMBER 2 +#define OMAP_TRIP_STEP \ + ((OMAP_TRIP_SHUTDOWN - OMAP_TRIP_HOT) / (OMAP_TRIP_NUMBER - 1)) + +/* Update rates */ +#define FAST_TEMP_MONITORING_RATE 250 + +/* helper macros */ +/** + * omap_thermal_get_trip_value - returns trip temperature based on index + * @i: trip index + */ +#define omap_thermal_get_trip_value(i) \ + (OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP)) + +/** + * omap_thermal_is_valid_trip - check for trip index + * @i: trip index + */ +#define omap_thermal_is_valid_trip(trip) \ + ((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER) + +#ifdef CONFIG_OMAP_THERMAL +int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id, + char *domain); +int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id); +int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id); +int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id); +#else +static inline +int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id, + char *domain) +{ + return 0; +} + +static inline +int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id) +{ + return 0; +} + +static inline +int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id) +{ + return 0; +} + +static inline +int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id) +{ + return 0; +} +#endif +#endif diff --git a/trunk/drivers/staging/omap-thermal/omap4-thermal.c b/trunk/drivers/staging/omap-thermal/omap4-thermal.c new file mode 100644 index 000000000000..fa9dbcd71830 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap4-thermal.c @@ -0,0 +1,259 @@ +/* + * OMAP4 thermal driver. + * + * Copyright (C) 2011-2012 Texas Instruments Inc. + * Contact: + * Eduardo Valentin + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "omap-thermal.h" +#include "omap-bandgap.h" + +/* + * OMAP4430 has one instance of thermal sensor for MPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap4430_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET, + .bgap_tempsoff_mask = OMAP4430_BGAP_TEMPSOFF_MASK, + .bgap_soc_mask = OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK, + .bgap_eocz_mask = OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK, + + .bgap_mode_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET, + .mode_ctrl_mask = OMAP4430_SINGLE_MODE_MASK, + + .bgap_efuse = OMAP4430_FUSE_OPP_BGAP, +}; + +/* Thresholds and limits for OMAP4430 MPU temperature sensor */ +static struct temp_sensor_data omap4430_mpu_temp_sensor_data = { + .min_freq = OMAP4430_MIN_FREQ, + .max_freq = OMAP4430_MAX_FREQ, + .max_temp = OMAP4430_MAX_TEMP, + .min_temp = OMAP4430_MIN_TEMP, + .hyst_val = OMAP4430_HYST_VAL, + .adc_start_val = OMAP4430_ADC_START_VALUE, + .adc_end_val = OMAP4430_ADC_END_VALUE, +}; + +/* + * Temperature values in milli degree celsius + * ADC code values from 530 to 923 + */ +static const int +omap4430_adc_to_temp[OMAP4430_ADC_END_VALUE - OMAP4430_ADC_START_VALUE + 1] = { + -38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000, -22000, + -20000, -18000, -17000, -15000, -13000, -12000, -10000, -8000, -6000, + -5000, -3000, -1000, 0, 2000, 3000, 5000, 6000, 8000, 10000, 12000, + 13000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28000, 30000, + 32000, 33000, 35000, 37000, 38000, 40000, 42000, 43000, 45000, 47000, + 48000, 50000, 52000, 53000, 55000, 57000, 58000, 60000, 62000, 64000, + 66000, 68000, 70000, 71000, 73000, 75000, 77000, 78000, 80000, 82000, + 83000, 85000, 87000, 88000, 90000, 92000, 93000, 95000, 97000, 98000, + 100000, 102000, 103000, 105000, 107000, 109000, 111000, 113000, 115000, + 117000, 118000, 120000, 122000, 123000, +}; + +/* OMAP4430 data */ +const struct omap_bandgap_data omap4430_data = { + .features = OMAP_BANDGAP_FEATURE_MODE_CONFIG | + OMAP_BANDGAP_FEATURE_POWER_SWITCH, + .fclock_name = "bandgap_fclk", + .div_ck_name = "bandgap_fclk", + .conv_table = omap4430_adc_to_temp, + .expose_sensor = omap_thermal_expose_sensor, + .remove_sensor = omap_thermal_remove_sensor, + .sensors = { + { + .registers = &omap4430_mpu_temp_sensor_registers, + .ts_data = &omap4430_mpu_temp_sensor_data, + .domain = "cpu", + .slope = 0, + .constant = 20000, + .slope_pcb = 0, + .constant_pcb = 20000, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, + }, + }, + .sensor_count = 1, +}; +/* + * OMAP4460 has one instance of thermal sensor for MPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap4460_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET, + .bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK, + .bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK, + .bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK, + + .bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET, + .mask_hot_mask = OMAP4460_MASK_HOT_MASK, + .mask_cold_mask = OMAP4460_MASK_COLD_MASK, + + .bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET, + .mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK, + + .bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET, + .counter_mask = OMAP4460_COUNTER_MASK, + + .bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET, + .threshold_thot_mask = OMAP4460_T_HOT_MASK, + .threshold_tcold_mask = OMAP4460_T_COLD_MASK, + + .tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET, + .tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK, + .tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK, + + .bgap_status = OMAP4460_BGAP_STATUS_OFFSET, + .status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK, + .status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK, + .status_hot_mask = OMAP4460_HOT_FLAG_MASK, + .status_cold_mask = OMAP4460_COLD_FLAG_MASK, + + .bgap_efuse = OMAP4460_FUSE_OPP_BGAP, +}; + +/* Thresholds and limits for OMAP4460 MPU temperature sensor */ +static struct temp_sensor_data omap4460_mpu_temp_sensor_data = { + .tshut_hot = OMAP4460_TSHUT_HOT, + .tshut_cold = OMAP4460_TSHUT_COLD, + .t_hot = OMAP4460_T_HOT, + .t_cold = OMAP4460_T_COLD, + .min_freq = OMAP4460_MIN_FREQ, + .max_freq = OMAP4460_MAX_FREQ, + .max_temp = OMAP4460_MAX_TEMP, + .min_temp = OMAP4460_MIN_TEMP, + .hyst_val = OMAP4460_HYST_VAL, + .adc_start_val = OMAP4460_ADC_START_VALUE, + .adc_end_val = OMAP4460_ADC_END_VALUE, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* + * Temperature values in milli degree celsius + * ADC code values from 530 to 923 + */ +static const int +omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = { + -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200, + -37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800, + -34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300, + -30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800, + -27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400, + -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000, + -20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600, + -17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200, + -13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700, + -10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800, + -6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000, + -2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600, + 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400, + 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000, + 11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, + 15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700, + 19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600, + 23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400, + 26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200, + 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000, + 34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, + 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600, + 42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300, + 45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000, + 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800, + 53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, + 57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400, + 60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200, + 64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800, + 68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600, + 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400, + 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, + 79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800, + 83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400, + 86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200, + 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800, + 94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, + 98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200, + 101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400, + 104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800, + 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000, + 111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200, + 114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400, + 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600, + 121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200, + 124600, 124900, 125000, 125000, 125000, 125000 +}; + +/* OMAP4460 data */ +const struct omap_bandgap_data omap4460_data = { + .features = OMAP_BANDGAP_FEATURE_TSHUT | + OMAP_BANDGAP_FEATURE_TSHUT_CONFIG | + OMAP_BANDGAP_FEATURE_TALERT | + OMAP_BANDGAP_FEATURE_MODE_CONFIG | + OMAP_BANDGAP_FEATURE_POWER_SWITCH | + OMAP_BANDGAP_FEATURE_COUNTER, + .fclock_name = "bandgap_ts_fclk", + .div_ck_name = "div_ts_ck", + .conv_table = omap4460_adc_to_temp, + .expose_sensor = omap_thermal_expose_sensor, + .remove_sensor = omap_thermal_remove_sensor, + .sensors = { + { + .registers = &omap4460_mpu_temp_sensor_registers, + .ts_data = &omap4460_mpu_temp_sensor_data, + .domain = "cpu", + .slope = OMAP_GRADIENT_SLOPE_4460, + .constant = OMAP_GRADIENT_CONST_4460, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, + }, + }, + .sensor_count = 1, +}; + +/* OMAP4470 data */ +const struct omap_bandgap_data omap4470_data = { + .features = OMAP_BANDGAP_FEATURE_TSHUT | + OMAP_BANDGAP_FEATURE_TSHUT_CONFIG | + OMAP_BANDGAP_FEATURE_TALERT | + OMAP_BANDGAP_FEATURE_MODE_CONFIG | + OMAP_BANDGAP_FEATURE_POWER_SWITCH | + OMAP_BANDGAP_FEATURE_COUNTER, + .fclock_name = "bandgap_ts_fclk", + .div_ck_name = "div_ts_ck", + .conv_table = omap4460_adc_to_temp, + .expose_sensor = omap_thermal_expose_sensor, + .remove_sensor = omap_thermal_remove_sensor, + .sensors = { + { + .registers = &omap4460_mpu_temp_sensor_registers, + .ts_data = &omap4460_mpu_temp_sensor_data, + .domain = "cpu", + .slope = OMAP_GRADIENT_SLOPE_4470, + .constant = OMAP_GRADIENT_CONST_4470, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470, + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, + }, + }, + .sensor_count = 1, +}; diff --git a/trunk/drivers/staging/omap-thermal/omap5-thermal.c b/trunk/drivers/staging/omap-thermal/omap5-thermal.c new file mode 100644 index 000000000000..0658af24a5c7 --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap5-thermal.c @@ -0,0 +1,297 @@ +/* + * OMAP5 thermal driver. + * + * Copyright (C) 2011-2012 Texas Instruments Inc. + * Contact: + * Eduardo Valentin + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "omap-bandgap.h" +#include "omap-thermal.h" + +/* + * omap5430 has one instance of thermal sensor for MPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap5430_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET, + .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK, + .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK, + .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK, + + .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, + .mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK, + .mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK, + + .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET, + .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK, + + .bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET, + .counter_mask = OMAP5430_COUNTER_MASK, + + .bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET, + .threshold_thot_mask = OMAP5430_T_HOT_MASK, + .threshold_tcold_mask = OMAP5430_T_COLD_MASK, + + .tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET, + .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK, + .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, + + .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, + .status_clean_stop_mask = 0x0, + .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, + .status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK, + .status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK, + + .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU, +}; + +/* + * omap5430 has one instance of thermal sensor for GPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap5430_gpu_temp_sensor_registers = { + .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET, + .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK, + .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK, + .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK, + + .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, + .mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK, + .mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK, + + .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET, + .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK, + + .bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET, + .counter_mask = OMAP5430_COUNTER_MASK, + + .bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET, + .threshold_thot_mask = OMAP5430_T_HOT_MASK, + .threshold_tcold_mask = OMAP5430_T_COLD_MASK, + + .tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET, + .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK, + .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, + + .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, + .status_clean_stop_mask = 0x0, + .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, + .status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK, + .status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK, + + .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU, +}; + +/* + * omap5430 has one instance of thermal sensor for CORE + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap5430_core_temp_sensor_registers = { + .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET, + .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK, + .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK, + .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK, + + .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, + .mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK, + .mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK, + + .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET, + .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK, + + .bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET, + .counter_mask = OMAP5430_COUNTER_MASK, + + .bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET, + .threshold_thot_mask = OMAP5430_T_HOT_MASK, + .threshold_tcold_mask = OMAP5430_T_COLD_MASK, + + .tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET, + .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK, + .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, + + .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, + .status_clean_stop_mask = 0x0, + .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, + .status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK, + .status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK, + + .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE, +}; + +/* Thresholds and limits for OMAP5430 MPU temperature sensor */ +static struct temp_sensor_data omap5430_mpu_temp_sensor_data = { + .tshut_hot = OMAP5430_MPU_TSHUT_HOT, + .tshut_cold = OMAP5430_MPU_TSHUT_COLD, + .t_hot = OMAP5430_MPU_T_HOT, + .t_cold = OMAP5430_MPU_T_COLD, + .min_freq = OMAP5430_MPU_MIN_FREQ, + .max_freq = OMAP5430_MPU_MAX_FREQ, + .max_temp = OMAP5430_MPU_MAX_TEMP, + .min_temp = OMAP5430_MPU_MIN_TEMP, + .hyst_val = OMAP5430_MPU_HYST_VAL, + .adc_start_val = OMAP5430_ADC_START_VALUE, + .adc_end_val = OMAP5430_ADC_END_VALUE, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for OMAP5430 GPU temperature sensor */ +static struct temp_sensor_data omap5430_gpu_temp_sensor_data = { + .tshut_hot = OMAP5430_GPU_TSHUT_HOT, + .tshut_cold = OMAP5430_GPU_TSHUT_COLD, + .t_hot = OMAP5430_GPU_T_HOT, + .t_cold = OMAP5430_GPU_T_COLD, + .min_freq = OMAP5430_GPU_MIN_FREQ, + .max_freq = OMAP5430_GPU_MAX_FREQ, + .max_temp = OMAP5430_GPU_MAX_TEMP, + .min_temp = OMAP5430_GPU_MIN_TEMP, + .hyst_val = OMAP5430_GPU_HYST_VAL, + .adc_start_val = OMAP5430_ADC_START_VALUE, + .adc_end_val = OMAP5430_ADC_END_VALUE, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for OMAP5430 CORE temperature sensor */ +static struct temp_sensor_data omap5430_core_temp_sensor_data = { + .tshut_hot = OMAP5430_CORE_TSHUT_HOT, + .tshut_cold = OMAP5430_CORE_TSHUT_COLD, + .t_hot = OMAP5430_CORE_T_HOT, + .t_cold = OMAP5430_CORE_T_COLD, + .min_freq = OMAP5430_CORE_MIN_FREQ, + .max_freq = OMAP5430_CORE_MAX_FREQ, + .max_temp = OMAP5430_CORE_MAX_TEMP, + .min_temp = OMAP5430_CORE_MIN_TEMP, + .hyst_val = OMAP5430_CORE_HYST_VAL, + .adc_start_val = OMAP5430_ADC_START_VALUE, + .adc_end_val = OMAP5430_ADC_END_VALUE, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +static const int +omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = { + -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, + -38200, -37800, -37300, -36800, + -36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000, + -32600, + -32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700, + -28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800, + -24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000, + -20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200, + -16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200, + -12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400, + -9000, + -8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800, + -4300, + -3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400, + 800, + 1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, + 6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800, + 11100, + 11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300, + 15800, + 16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000, + 20400, + 20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600, + 25000, + 25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300, + 29800, + 30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000, + 34400, + 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600, + 39000, + 39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200, + 43600, + 44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800, + 48200, + 48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, + 52800, + 53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000, + 57400, + 57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600, + 62000, + 62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200, + 66600, + 67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800, + 71200, + 71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400, + 75800, + 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800, + 80300, + 80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400, + 84800, + 85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000, + 89400, + 89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, + 93800, + 94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000, + 98400, + 98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000, + 102400, + 102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100, + 106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800, + 110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400, + 113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000, + 117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600, + 121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200, + 124600, 124900, 125000, 125000, 125000, 125000, +}; + +const struct omap_bandgap_data omap5430_data = { + .features = OMAP_BANDGAP_FEATURE_TSHUT_CONFIG | + OMAP_BANDGAP_FEATURE_TALERT | + OMAP_BANDGAP_FEATURE_MODE_CONFIG | + OMAP_BANDGAP_FEATURE_COUNTER, + .fclock_name = "ts_clk_div_ck", + .div_ck_name = "ts_clk_div_ck", + .conv_table = omap5430_adc_to_temp, + .expose_sensor = omap_thermal_expose_sensor, + .remove_sensor = omap_thermal_remove_sensor, + .sensors = { + { + .registers = &omap5430_mpu_temp_sensor_registers, + .ts_data = &omap5430_mpu_temp_sensor_data, + .domain = "cpu", + .register_cooling = omap_thermal_register_cpu_cooling, + .unregister_cooling = omap_thermal_unregister_cpu_cooling, + .slope = OMAP_GRADIENT_SLOPE_5430_CPU, + .constant = OMAP_GRADIENT_CONST_5430_CPU, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU, + }, + { + .registers = &omap5430_gpu_temp_sensor_registers, + .ts_data = &omap5430_gpu_temp_sensor_data, + .domain = "gpu", + .slope = OMAP_GRADIENT_SLOPE_5430_GPU, + .constant = OMAP_GRADIENT_CONST_5430_GPU, + .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU, + .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU, + }, + { + .registers = &omap5430_core_temp_sensor_registers, + .ts_data = &omap5430_core_temp_sensor_data, + .domain = "core", + }, + }, + .sensor_count = 3, +}; diff --git a/trunk/drivers/staging/omap-thermal/omap_bandgap.txt b/trunk/drivers/staging/omap-thermal/omap_bandgap.txt new file mode 100644 index 000000000000..6008a1452fde --- /dev/null +++ b/trunk/drivers/staging/omap-thermal/omap_bandgap.txt @@ -0,0 +1,30 @@ +* Texas Instrument OMAP SCM bandgap bindings + +In the System Control Module, OMAP supplies a voltage reference +and a temperature sensor feature that are gathered in the band +gap voltage and temperature sensor (VBGAPTS) module. The band +gap provides current and voltage reference for its internal +circuits and other analog IP blocks. The analog-to-digital +converter (ADC) produces an output value that is proportional +to the silicon temperature. + +Required properties: +- compatible : Should be: + - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap + - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap +- interrupts : this entry should indicate which interrupt line +the talert signal is routed to; +Specific: +- ti,tshut-gpio : this entry should be used to inform which GPIO +line the tshut signal is routed to; + +Example: + +bandgap { + reg = <0x4a002260 0x4 + 0x4a00232C 0x4 + 0x4a002378 0x18>; + compatible = "ti,omap4460-control-bandgap"; + interrupts = <0 126 4>; /* talert */ + ti,tshut-gpio = <86>; +}; diff --git a/trunk/drivers/staging/panel/panel.c b/trunk/drivers/staging/panel/panel.c index 7365089a33e8..39f9982c2708 100644 --- a/trunk/drivers/staging/panel/panel.c +++ b/trunk/drivers/staging/panel/panel.c @@ -34,6 +34,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include @@ -1837,12 +1839,6 @@ static void panel_process_inputs(void) struct list_head *item; struct logical_input *input; -#if 0 - printk(KERN_DEBUG - "entering panel_process_inputs with pp=%016Lx & pc=%016Lx\n", - phys_prev, phys_curr); -#endif - keypressed = 0; inputs_stable = 1; list_for_each(item, &logical_inputs) { @@ -1987,10 +1983,9 @@ static struct logical_input *panel_bind_key(char *name, char *press, struct logical_input *key; key = kzalloc(sizeof(struct logical_input), GFP_KERNEL); - if (!key) { - printk(KERN_ERR "panel: not enough memory\n"); + if (!key) return NULL; - } + if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i, &scan_mask_o)) { kfree(key); @@ -2002,10 +1997,6 @@ static struct logical_input *panel_bind_key(char *name, char *press, key->rise_time = 1; key->fall_time = 1; -#if 0 - printk(KERN_DEBUG "bind: <%s> : m=%016Lx v=%016Lx\n", name, key->mask, - key->value); -#endif strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); strncpy(key->u.kbd.release_str, release, @@ -2030,10 +2021,9 @@ static struct logical_input *panel_bind_callback(char *name, struct logical_input *callback; callback = kmalloc(sizeof(struct logical_input), GFP_KERNEL); - if (!callback) { - printk(KERN_ERR "panel: not enough memory\n"); + if (!callback) return NULL; - } + memset(callback, 0, sizeof(struct logical_input)); if (!input_name2mask(name, &callback->mask, &callback->value, &scan_mask_i, &scan_mask_o)) @@ -2110,10 +2100,8 @@ static void panel_attach(struct parport *port) return; if (pprt) { - printk(KERN_ERR - "panel_attach(): port->number=%d parport=%d, " - "already registered !\n", - port->number, parport); + pr_err("%s: port->number=%d parport=%d, already registered!\n", + __func__, port->number, parport); return; } @@ -2122,16 +2110,14 @@ static void panel_attach(struct parport *port) /*PARPORT_DEV_EXCL */ 0, (void *)&pprt); if (pprt == NULL) { - pr_err("panel_attach(): port->number=%d parport=%d, " - "parport_register_device() failed\n", - port->number, parport); + pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n", + __func__, port->number, parport); return; } if (parport_claim(pprt)) { - printk(KERN_ERR - "Panel: could not claim access to parport%d. " - "Aborting.\n", parport); + pr_err("could not claim access to parport%d. Aborting.\n", + parport); goto err_unreg_device; } @@ -2165,10 +2151,8 @@ static void panel_detach(struct parport *port) return; if (!pprt) { - printk(KERN_ERR - "panel_detach(): port->number=%d parport=%d, " - "nothing to unregister.\n", - port->number, parport); + pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n", + __func__, port->number, parport); return; } @@ -2278,8 +2262,7 @@ int panel_init(void) init_in_progress = 1; if (parport_register_driver(&panel_driver)) { - printk(KERN_ERR - "Panel: could not register with parport. Aborting.\n"); + pr_err("could not register with parport. Aborting.\n"); return -EIO; } @@ -2291,20 +2274,19 @@ int panel_init(void) pprt = NULL; } parport_unregister_driver(&panel_driver); - printk(KERN_ERR "Panel driver version " PANEL_VERSION - " disabled.\n"); + pr_err("driver version " PANEL_VERSION " disabled.\n"); return -ENODEV; } register_reboot_notifier(&panel_notifier); if (pprt) - printk(KERN_INFO "Panel driver version " PANEL_VERSION - " registered on parport%d (io=0x%lx).\n", parport, - pprt->port->base); + pr_info("driver version " PANEL_VERSION + " registered on parport%d (io=0x%lx).\n", parport, + pprt->port->base); else - printk(KERN_INFO "Panel driver version " PANEL_VERSION - " not yet registered\n"); + pr_info("driver version " PANEL_VERSION + " not yet registered\n"); /* tells various subsystems about the fact that initialization is finished */ init_in_progress = 0; diff --git a/trunk/drivers/staging/rts_pstor/rtsx.c b/trunk/drivers/staging/rts_pstor/rtsx.c index 1dccd933a7e4..5fb05a2edebb 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx.c +++ b/trunk/drivers/staging/rts_pstor/rtsx.c @@ -1021,7 +1021,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, } /* Start up the thread for delayed SCSI-device scanning */ - th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan"); + th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { printk(KERN_ERR "Unable to start the device-scanning thread\n"); complete(&dev->scanning_done); @@ -1030,8 +1030,6 @@ static int __devinit rtsx_probe(struct pci_dev *pci, goto errout; } - wake_up_process(th); - /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { diff --git a/trunk/drivers/staging/sm7xxfb/Kconfig b/trunk/drivers/staging/sm7xxfb/Kconfig index d5013f8a865b..e2922ae3a3ee 100644 --- a/trunk/drivers/staging/sm7xxfb/Kconfig +++ b/trunk/drivers/staging/sm7xxfb/Kconfig @@ -1,6 +1,6 @@ config FB_SM7XX tristate "Silicon Motion SM7XX framebuffer support" - depends on FB + depends on FB && PCI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/trunk/drivers/staging/sm7xxfb/sm7xxfb.c b/trunk/drivers/staging/sm7xxfb/sm7xxfb.c index 73951963c018..90c90db8978e 100644 --- a/trunk/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/trunk/drivers/staging/sm7xxfb/sm7xxfb.c @@ -34,8 +34,6 @@ #include "sm7xx.h" -struct screen_info smtc_screen_info; - /* * Private structure */ @@ -54,37 +52,13 @@ struct smtcfb_info { u_int width; u_int height; u_int hz; -}; - -struct vesa_mode_table { - char mode_index[6]; - u16 lfb_width; - u16 lfb_height; - u16 lfb_depth; -}; - -static struct vesa_mode_table vesa_mode[] = { - {"0x301", 640, 480, 8}, - {"0x303", 800, 600, 8}, - {"0x305", 1024, 768, 8}, - {"0x307", 1280, 1024, 8}, - {"0x311", 640, 480, 16}, - {"0x314", 800, 600, 16}, - {"0x317", 1024, 768, 16}, - {"0x31A", 1280, 1024, 16}, - - {"0x312", 640, 480, 24}, - {"0x315", 800, 600, 24}, - {"0x318", 1024, 768, 24}, - {"0x31B", 1280, 1024, 24}, + u32 colreg[17]; }; char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */ -static u32 colreg[17]; - static struct fb_var_screeninfo smtcfb_var = { .xres = 1024, .yres = 600, @@ -108,113 +82,58 @@ static struct fb_fix_screeninfo smtcfb_fix = { .accel = FB_ACCEL_SMI_LYNX, }; -static void sm712_set_timing(struct smtcfb_info *sfb) -{ - int i = 0, j = 0; - u32 m_nScreenStride; - - dev_dbg(&sfb->pdev->dev, - "sfb->width=%d sfb->height=%d " - "sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", - sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); - - for (j = 0; j < numVGAModes; j++) { - if (VGAMode[j].mmSizeX == sfb->width && - VGAMode[j].mmSizeY == sfb->height && - VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && - VGAMode[j].hz == sfb->hz) { - - dev_dbg(&sfb->pdev->dev, - "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d " - "VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", - VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, - VGAMode[j].bpp, VGAMode[j].hz); - - dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j); - - smtc_mmiowb(0x0, 0x3c6); - - smtc_seqw(0, 0x1); - - smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); - - /* init SEQ register SR00 - SR04 */ - for (i = 0; i < SIZE_SR00_SR04; i++) - smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); +struct vesa_mode { + char index[6]; + u16 lfb_width; + u16 lfb_height; + u16 lfb_depth; +}; - /* init SEQ register SR10 - SR24 */ - for (i = 0; i < SIZE_SR10_SR24; i++) - smtc_seqw(i + 0x10, - VGAMode[j].Init_SR10_SR24[i]); +static struct vesa_mode vesa_mode_table[] = { + {"0x301", 640, 480, 8}, + {"0x303", 800, 600, 8}, + {"0x305", 1024, 768, 8}, + {"0x307", 1280, 1024, 8}, - /* init SEQ register SR30 - SR75 */ - for (i = 0; i < SIZE_SR30_SR75; i++) - if (((i + 0x30) != 0x62) \ - && ((i + 0x30) != 0x6a) \ - && ((i + 0x30) != 0x6b)) - smtc_seqw(i + 0x30, - VGAMode[j].Init_SR30_SR75[i]); + {"0x311", 640, 480, 16}, + {"0x314", 800, 600, 16}, + {"0x317", 1024, 768, 16}, + {"0x31A", 1280, 1024, 16}, - /* init SEQ register SR80 - SR93 */ - for (i = 0; i < SIZE_SR80_SR93; i++) - smtc_seqw(i + 0x80, - VGAMode[j].Init_SR80_SR93[i]); + {"0x312", 640, 480, 24}, + {"0x315", 800, 600, 24}, + {"0x318", 1024, 768, 24}, + {"0x31B", 1280, 1024, 24}, +}; - /* init SEQ register SRA0 - SRAF */ - for (i = 0; i < SIZE_SRA0_SRAF; i++) - smtc_seqw(i + 0xa0, - VGAMode[j].Init_SRA0_SRAF[i]); +struct screen_info smtc_scr_info; - /* init Graphic register GR00 - GR08 */ - for (i = 0; i < SIZE_GR00_GR08; i++) - smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); +/* process command line options, get vga parameter */ +static int __init sm7xx_vga_setup(char *options) +{ + int i; - /* init Attribute register AR00 - AR14 */ - for (i = 0; i < SIZE_AR00_AR14; i++) - smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + if (!options || !*options) + return -EINVAL; - /* init CRTC register CR00 - CR18 */ - for (i = 0; i < SIZE_CR00_CR18; i++) - smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + smtc_scr_info.lfb_width = 0; + smtc_scr_info.lfb_height = 0; + smtc_scr_info.lfb_depth = 0; - /* init CRTC register CR30 - CR4D */ - for (i = 0; i < SIZE_CR30_CR4D; i++) - smtc_crtcw(i + 0x30, - VGAMode[j].Init_CR30_CR4D[i]); + pr_debug("sm7xx_vga_setup = %s\n", options); - /* init CRTC register CR90 - CRA7 */ - for (i = 0; i < SIZE_CR90_CRA7; i++) - smtc_crtcw(i + 0x90, - VGAMode[j].Init_CR90_CRA7[i]); + for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) { + if (strstr(options, vesa_mode_table[i].index)) { + smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width; + smtc_scr_info.lfb_height = vesa_mode_table[i].lfb_height; + smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth; + return 0; } } - smtc_mmiowb(0x67, 0x3c2); - - /* set VPR registers */ - writel(0x0, sfb->m_pVPR + 0x0C); - writel(0x0, sfb->m_pVPR + 0x40); - - /* set data width */ - m_nScreenStride = - (sfb->width * sfb->fb.var.bits_per_pixel) / 64; - switch (sfb->fb.var.bits_per_pixel) { - case 8: - writel(0x0, sfb->m_pVPR + 0x0); - break; - case 16: - writel(0x00020000, sfb->m_pVPR + 0x0); - break; - case 24: - writel(0x00040000, sfb->m_pVPR + 0x0); - break; - case 32: - writel(0x00030000, sfb->m_pVPR + 0x0); - break; - } - writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), - sfb->m_pVPR + 0x10); + return -1; } +__setup("vga=", sm7xx_vga_setup); static void sm712_setpalette(int regno, unsigned red, unsigned green, unsigned blue, struct fb_info *info) @@ -228,17 +147,6 @@ static void sm712_setpalette(int regno, unsigned red, unsigned green, smtc_mmiowb(blue >> 10, dac_val); } -static void smtc_set_timing(struct smtcfb_info *sfb) -{ - switch (sfb->chip_id) { - case 0x710: - case 0x712: - case 0x720: - sm712_set_timing(sfb); - break; - } -} - /* chan_to_field * * convert a colour value into a field position @@ -554,6 +462,125 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, } #endif /* ! __BIG_ENDIAN */ +static void sm7xx_set_timing(struct smtcfb_info *sfb) +{ + int i = 0, j = 0; + u32 m_nScreenStride; + + dev_dbg(&sfb->pdev->dev, + "sfb->width=%d sfb->height=%d " + "sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", + sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); + + for (j = 0; j < numVGAModes; j++) { + if (VGAMode[j].mmSizeX == sfb->width && + VGAMode[j].mmSizeY == sfb->height && + VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && + VGAMode[j].hz == sfb->hz) { + + dev_dbg(&sfb->pdev->dev, + "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d " + "VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", + VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, + VGAMode[j].bpp, VGAMode[j].hz); + + dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j); + + smtc_mmiowb(0x0, 0x3c6); + + smtc_seqw(0, 0x1); + + smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); + + /* init SEQ register SR00 - SR04 */ + for (i = 0; i < SIZE_SR00_SR04; i++) + smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); + + /* init SEQ register SR10 - SR24 */ + for (i = 0; i < SIZE_SR10_SR24; i++) + smtc_seqw(i + 0x10, + VGAMode[j].Init_SR10_SR24[i]); + + /* init SEQ register SR30 - SR75 */ + for (i = 0; i < SIZE_SR30_SR75; i++) + if (((i + 0x30) != 0x62) \ + && ((i + 0x30) != 0x6a) \ + && ((i + 0x30) != 0x6b)) + smtc_seqw(i + 0x30, + VGAMode[j].Init_SR30_SR75[i]); + + /* init SEQ register SR80 - SR93 */ + for (i = 0; i < SIZE_SR80_SR93; i++) + smtc_seqw(i + 0x80, + VGAMode[j].Init_SR80_SR93[i]); + + /* init SEQ register SRA0 - SRAF */ + for (i = 0; i < SIZE_SRA0_SRAF; i++) + smtc_seqw(i + 0xa0, + VGAMode[j].Init_SRA0_SRAF[i]); + + /* init Graphic register GR00 - GR08 */ + for (i = 0; i < SIZE_GR00_GR08; i++) + smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); + + /* init Attribute register AR00 - AR14 */ + for (i = 0; i < SIZE_AR00_AR14; i++) + smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + + /* init CRTC register CR00 - CR18 */ + for (i = 0; i < SIZE_CR00_CR18; i++) + smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + + /* init CRTC register CR30 - CR4D */ + for (i = 0; i < SIZE_CR30_CR4D; i++) + smtc_crtcw(i + 0x30, + VGAMode[j].Init_CR30_CR4D[i]); + + /* init CRTC register CR90 - CRA7 */ + for (i = 0; i < SIZE_CR90_CRA7; i++) + smtc_crtcw(i + 0x90, + VGAMode[j].Init_CR90_CRA7[i]); + } + } + smtc_mmiowb(0x67, 0x3c2); + + /* set VPR registers */ + writel(0x0, sfb->m_pVPR + 0x0C); + writel(0x0, sfb->m_pVPR + 0x40); + + /* set data width */ + m_nScreenStride = + (sfb->width * sfb->fb.var.bits_per_pixel) / 64; + switch (sfb->fb.var.bits_per_pixel) { + case 8: + writel(0x0, sfb->m_pVPR + 0x0); + break; + case 16: + writel(0x00020000, sfb->m_pVPR + 0x0); + break; + case 24: + writel(0x00040000, sfb->m_pVPR + 0x0); + break; + case 32: + writel(0x00030000, sfb->m_pVPR + 0x0); + break; + } + writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), + sfb->m_pVPR + 0x10); + +} + +static void smtc_set_timing(struct smtcfb_info *sfb) +{ + switch (sfb->chip_id) { + case 0x710: + case 0x712: + case 0x720: + sm7xx_set_timing(sfb); + break; + } +} + void smtcfb_setmode(struct smtcfb_info *sfb) { switch (sfb->fb.var.bits_per_pixel) { @@ -646,7 +673,7 @@ static struct fb_ops smtcfb_ops = { }; /* - * Alloc struct smtcfb_info and assign the default value + * alloc struct smtcfb_info and assign the default value */ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev, char *name) { @@ -659,32 +686,32 @@ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev, char *name) sfb->pdev = pdev; - /*** Init sfb->fb with default value ***/ + /* init sfb->fb with default value */ + sfb->fb.flags = FBINFO_FLAG_DEFAULT; sfb->fb.fbops = &smtcfb_ops; - sfb->fb.var = smtcfb_var; - sfb->fb.fix = smtcfb_fix; + sfb->fb.fix = smtcfb_fix; strcpy(sfb->fb.fix.id, name); - sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; - sfb->fb.fix.type_aux = 0; - sfb->fb.fix.xpanstep = 0; - sfb->fb.fix.ypanstep = 0; - sfb->fb.fix.ywrapstep = 0; - sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX; - - sfb->fb.var.nonstd = 0; - sfb->fb.var.activate = FB_ACTIVATE_NOW; - sfb->fb.var.height = -1; - sfb->fb.var.width = -1; - /* text mode acceleration */ + sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + sfb->fb.fix.type_aux = 0; + sfb->fb.fix.xpanstep = 0; + sfb->fb.fix.ypanstep = 0; + sfb->fb.fix.ywrapstep = 0; + sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX; + + sfb->fb.var = smtcfb_var; + sfb->fb.var.nonstd = 0; + sfb->fb.var.activate = FB_ACTIVATE_NOW; + sfb->fb.var.height = -1; + sfb->fb.var.width = -1; sfb->fb.var.accel_flags = FB_ACCELF_TEXT; - sfb->fb.var.vmode = FB_VMODE_NONINTERLACED; + sfb->fb.var.vmode = FB_VMODE_NONINTERLACED; - sfb->fb.par = sfb; + sfb->fb.pseudo_palette = sfb->colreg; - sfb->fb.pseudo_palette = colreg; + sfb->fb.par = sfb; return sfb; } @@ -756,41 +783,6 @@ static inline void sm7xx_init_hw(void) outb_p(0x11, 0x3c5); } -/* - * sm712vga_setup - process command line options, get vga parameter - * @options: string of options - * Returns zero. - * - */ -static int __init sm712vga_setup(char *options) -{ - int index; - - if (!options || !*options) - return -EINVAL; - - smtc_screen_info.lfb_width = 0; - smtc_screen_info.lfb_height = 0; - smtc_screen_info.lfb_depth = 0; - - pr_debug("sm712vga_setup = %s\n", options); - - for (index = 0; - index < ARRAY_SIZE(vesa_mode); - index++) { - if (strstr(options, vesa_mode[index].mode_index)) { - smtc_screen_info.lfb_width = vesa_mode[index].lfb_width; - smtc_screen_info.lfb_height = - vesa_mode[index].lfb_height; - smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth; - return 0; - } - } - - return -1; -} -__setup("vga=", sm712vga_setup); - static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -820,11 +812,11 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, sm7xx_init_hw(); - /*get mode parameter from smtc_screen_info */ - if (smtc_screen_info.lfb_width != 0) { - sfb->fb.var.xres = smtc_screen_info.lfb_width; - sfb->fb.var.yres = smtc_screen_info.lfb_height; - sfb->fb.var.bits_per_pixel = smtc_screen_info.lfb_depth; + /* get mode parameter from smtc_scr_info */ + if (smtc_scr_info.lfb_width != 0) { + sfb->fb.var.xres = smtc_scr_info.lfb_width; + sfb->fb.var.yres = smtc_scr_info.lfb_height; + sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth; } else { /* default resolution 1024x600 16bit mode */ sfb->fb.var.xres = SCREEN_X_RES; diff --git a/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c index 11728a03f8a0..277491a877ea 100644 --- a/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c +++ b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c @@ -655,13 +655,13 @@ static int synpatics_rmi4_touchpad_detect(struct synaptics_rmi4_data *pdata, } /** - * synpatics_rmi4_touchpad_config() - confiures the rmi4 touchpad device + * synaptics_rmi4_touchpad_config() - configures the rmi4 touchpad device * @pdata: pointer to synaptics_rmi4_data structure * @rfi: pointer to synaptics_rmi4_fn structure * - * This function calls to confiures the rmi4 touchpad device + * This function calls to configures the rmi4 touchpad device */ -int synpatics_rmi4_touchpad_config(struct synaptics_rmi4_data *pdata, +int synaptics_rmi4_touchpad_config(struct synaptics_rmi4_data *pdata, struct synaptics_rmi4_fn *rfi) { /* @@ -855,7 +855,7 @@ static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata) if (rfi->num_of_data_sources) { if (rfi->fn_number == SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM) { - retval = synpatics_rmi4_touchpad_config + retval = synaptics_rmi4_touchpad_config (pdata, rfi); if (retval < 0) return retval; diff --git a/trunk/drivers/staging/vt6656/wcmd.c b/trunk/drivers/staging/vt6656/wcmd.c index 78ea121b7e2e..9d2caa819f47 100644 --- a/trunk/drivers/staging/vt6656/wcmd.c +++ b/trunk/drivers/staging/vt6656/wcmd.c @@ -1254,51 +1254,50 @@ static BOOL s_bClearBSSID_SCAN(void *hDeviceContext) //mike add:reset command timer void vResetCommandTimer(void *hDeviceContext) { - PSDevice pDevice = (PSDevice)hDeviceContext; - - //delete timer - del_timer(&pDevice->sTimerCommand); - //init timer - init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (unsigned long)pDevice; - pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; - pDevice->sTimerCommand.expires = RUN_AT(HZ); - pDevice->cbFreeCmdQueue = CMD_Q_SIZE; - pDevice->uCmdDequeueIdx = 0; - pDevice->uCmdEnqueueIdx = 0; - pDevice->eCommandState = WLAN_CMD_IDLE; - pDevice->bCmdRunning = FALSE; - pDevice->bCmdClear = FALSE; + PSDevice pDevice = (PSDevice)hDeviceContext; + + //delete timer + del_timer(&pDevice->sTimerCommand); + //init timer + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT(HZ); + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->eCommandState = WLAN_CMD_IDLE; + pDevice->bCmdRunning = FALSE; + pDevice->bCmdClear = FALSE; } void BSSvSecondTxData(void *hDeviceContext) { - PSDevice pDevice = (PSDevice)hDeviceContext; - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - - pDevice->nTxDataTimeCout++; - - if(pDevice->nTxDataTimeCout<4) //don't tx data if timer less than 40s - { - // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__, - // (int)pDevice->nTxDataTimeCout); - pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback - add_timer(&pDevice->sTimerTxData); - return; - } - - spin_lock_irq(&pDevice->lock); - //is wap_supplicant running successful OR only open && sharekey mode! - if(((pDevice->bLinkPass ==TRUE)&&(pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking - (pDevice->fWPA_Authened == TRUE)) { //wpa linking - // printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__); - pDevice->fTxDataInSleep = TRUE; - PSbSendNullPacket(pDevice); //send null packet - pDevice->fTxDataInSleep = FALSE; - } - spin_unlock_irq(&pDevice->lock); - - pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback - add_timer(&pDevice->sTimerTxData); - return; + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + pDevice->nTxDataTimeCout++; + + if (pDevice->nTxDataTimeCout < 4) { //don't tx data if timer less than 40s + // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__, + // (int)pDevice->nTxDataTimeCout); + pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback + add_timer(&pDevice->sTimerTxData); + return; + } + + spin_lock_irq(&pDevice->lock); + //is wap_supplicant running successful OR only open && sharekey mode! + if (((pDevice->bLinkPass == TRUE) && + (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking + (pDevice->fWPA_Authened == TRUE)) { //wpa linking + // printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__); + pDevice->fTxDataInSleep = TRUE; + PSbSendNullPacket(pDevice); //send null packet + pDevice->fTxDataInSleep = FALSE; + } + spin_unlock_irq(&pDevice->lock); + + pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback + add_timer(&pDevice->sTimerTxData); } diff --git a/trunk/drivers/staging/winbond/wbusb.c b/trunk/drivers/staging/winbond/wbusb.c index c3751a718384..ef360547ecec 100644 --- a/trunk/drivers/staging/winbond/wbusb.c +++ b/trunk/drivers/staging/winbond/wbusb.c @@ -747,20 +747,18 @@ static int wb35_probe(struct usb_interface *intf, struct usb_host_interface *interface; struct ieee80211_hw *dev; struct wbsoft_priv *priv; - int nr, err; + int err; u32 ltmp; usb_get_dev(udev); /* Check the device if it already be opened */ - nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x0, 0x400, <mp, 4, HZ * 100); - if (nr < 0) { - err = nr; + if (err < 0) goto error; - } /* Is already initialized? */ ltmp = cpu_to_le32(ltmp); diff --git a/trunk/drivers/staging/wlags49_h2/dhf.c b/trunk/drivers/staging/wlags49_h2/dhf.c index bb80b547cc19..13d360fa58ec 100644 --- a/trunk/drivers/staging/wlags49_h2/dhf.c +++ b/trunk/drivers/staging/wlags49_h2/dhf.c @@ -1,5 +1,4 @@ -/* vim:tw=110:ts=4: */ /************************************************************************************************************** * * FILE : DHF.C diff --git a/trunk/drivers/staging/wlags49_h2/dhf.h b/trunk/drivers/staging/wlags49_h2/dhf.h index dbe0611fd032..1299b8256468 100644 --- a/trunk/drivers/staging/wlags49_h2/dhf.h +++ b/trunk/drivers/staging/wlags49_h2/dhf.h @@ -1,5 +1,4 @@ -/* vim:tw=110:ts=4: */ #ifndef DHF_H #define DHF_H diff --git a/trunk/drivers/staging/wlags49_h2/hcf.h b/trunk/drivers/staging/wlags49_h2/hcf.h index 68e23303b5e8..2abeaa11d8ca 100644 --- a/trunk/drivers/staging/wlags49_h2/hcf.h +++ b/trunk/drivers/staging/wlags49_h2/hcf.h @@ -1,5 +1,4 @@ -// vim:tw=110:ts=4: #ifndef HCF_H #define HCF_H 1 diff --git a/trunk/drivers/staging/wlags49_h2/hcfcfg.h b/trunk/drivers/staging/wlags49_h2/hcfcfg.h index ef60da8c3ebc..39fb4d326f65 100644 --- a/trunk/drivers/staging/wlags49_h2/hcfcfg.h +++ b/trunk/drivers/staging/wlags49_h2/hcfcfg.h @@ -1,5 +1,4 @@ -// vim:tw=110:ts=4: #ifndef HCFCFG_H #define HCFCFG_H 1 diff --git a/trunk/drivers/staging/wlags49_h2/mdd.h b/trunk/drivers/staging/wlags49_h2/mdd.h index 5f951efb9c07..5c3515f31a16 100644 --- a/trunk/drivers/staging/wlags49_h2/mdd.h +++ b/trunk/drivers/staging/wlags49_h2/mdd.h @@ -1,5 +1,4 @@ -// vim:tw=110:ts=4: #ifndef MDD_H #define MDD_H 1 diff --git a/trunk/drivers/staging/wlags49_h2/mmd.c b/trunk/drivers/staging/wlags49_h2/mmd.c index 7204a373bc51..3312348c3477 100644 --- a/trunk/drivers/staging/wlags49_h2/mmd.c +++ b/trunk/drivers/staging/wlags49_h2/mmd.c @@ -1,5 +1,4 @@ -// vim:tw=110:ts=4: /************************************************************************************************************ * * FILE : mmd.c diff --git a/trunk/drivers/staging/wlags49_h2/mmd.h b/trunk/drivers/staging/wlags49_h2/mmd.h index 914952513005..14458035d9e9 100644 --- a/trunk/drivers/staging/wlags49_h2/mmd.h +++ b/trunk/drivers/staging/wlags49_h2/mmd.h @@ -1,5 +1,4 @@ -// vim:tw=110:ts=4: #ifndef MMD_H #define MMD_H 1 diff --git a/trunk/drivers/staging/wlan-ng/prism2sta.c b/trunk/drivers/staging/wlan-ng/prism2sta.c index 417aea5e01cd..1dfd9aa5e9fe 100644 --- a/trunk/drivers/staging/wlan-ng/prism2sta.c +++ b/trunk/drivers/staging/wlan-ng/prism2sta.c @@ -1947,8 +1947,8 @@ static wlandevice_t *create_wlan(void) hfa384x_t *hw = NULL; /* Alloc our structures */ - wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL); - hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL); + wlandev = kzalloc(sizeof(wlandevice_t), GFP_KERNEL); + hw = kzalloc(sizeof(hfa384x_t), GFP_KERNEL); if (!wlandev || !hw) { printk(KERN_ERR "%s: Memory allocation failure.\n", dev_info); @@ -1957,10 +1957,6 @@ static wlandevice_t *create_wlan(void) return NULL; } - /* Clear all the structs */ - memset(wlandev, 0, sizeof(wlandevice_t)); - memset(hw, 0, sizeof(hfa384x_t)); - /* Initialize the network device object. */ wlandev->nsdname = dev_info; wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; diff --git a/trunk/fs/pstore/Kconfig b/trunk/fs/pstore/Kconfig index d044de6ee308..d39bb5cce883 100644 --- a/trunk/fs/pstore/Kconfig +++ b/trunk/fs/pstore/Kconfig @@ -19,6 +19,18 @@ config PSTORE_CONSOLE When the option is enabled, pstore will log all kernel messages, even if no oops or panic happened. +config PSTORE_FTRACE + bool "Persistent function tracer" + depends on PSTORE + depends on FUNCTION_TRACER + help + With this option kernel traces function calls into a persistent + ram buffer that can be decoded and dumped after reboot through + pstore filesystem. It can be used to determine what function + was last called before a reset or panic. + + If unsure, say N. + config PSTORE_RAM tristate "Log panic/oops to a RAM buffer" depends on PSTORE diff --git a/trunk/fs/pstore/Makefile b/trunk/fs/pstore/Makefile index 278a44e0d4e1..4c9095c2781e 100644 --- a/trunk/fs/pstore/Makefile +++ b/trunk/fs/pstore/Makefile @@ -5,6 +5,7 @@ obj-y += pstore.o pstore-objs += inode.o platform.o +obj-$(CONFIG_PSTORE_FTRACE) += ftrace.o ramoops-objs += ram.o ram_core.o obj-$(CONFIG_PSTORE_RAM) += ramoops.o diff --git a/trunk/fs/pstore/ftrace.c b/trunk/fs/pstore/ftrace.c new file mode 100644 index 000000000000..a130d484b7d3 --- /dev/null +++ b/trunk/fs/pstore/ftrace.c @@ -0,0 +1,35 @@ +/* + * Copyright 2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +void notrace pstore_ftrace_call(unsigned long ip, unsigned long parent_ip) +{ + struct pstore_ftrace_record rec = {}; + + if (unlikely(oops_in_progress)) + return; + + rec.ip = ip; + rec.parent_ip = parent_ip; + pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); + psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, + sizeof(rec), psinfo); +} diff --git a/trunk/fs/pstore/inode.c b/trunk/fs/pstore/inode.c index 45bff5441b04..4ab572e6d277 100644 --- a/trunk/fs/pstore/inode.c +++ b/trunk/fs/pstore/inode.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -52,18 +53,117 @@ struct pstore_private { char data[]; }; +struct pstore_ftrace_seq_data { + const void *ptr; + size_t off; + size_t size; +}; + +#define REC_SIZE sizeof(struct pstore_ftrace_record) + +static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos) +{ + struct pstore_private *ps = s->private; + struct pstore_ftrace_seq_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + data->off = ps->size % REC_SIZE; + data->off += *pos * REC_SIZE; + if (data->off + REC_SIZE > ps->size) { + kfree(data); + return NULL; + } + + return data; + +} + +static void pstore_ftrace_seq_stop(struct seq_file *s, void *v) +{ + kfree(v); +} + +static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct pstore_private *ps = s->private; + struct pstore_ftrace_seq_data *data = v; + + data->off += REC_SIZE; + if (data->off + REC_SIZE > ps->size) + return NULL; + + (*pos)++; + return data; +} + +static int pstore_ftrace_seq_show(struct seq_file *s, void *v) +{ + struct pstore_private *ps = s->private; + struct pstore_ftrace_seq_data *data = v; + struct pstore_ftrace_record *rec = (void *)(ps->data + data->off); + + seq_printf(s, "%d %08lx %08lx %pf <- %pF\n", + pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip, + (void *)rec->ip, (void *)rec->parent_ip); + + return 0; +} + +static const struct seq_operations pstore_ftrace_seq_ops = { + .start = pstore_ftrace_seq_start, + .next = pstore_ftrace_seq_next, + .stop = pstore_ftrace_seq_stop, + .show = pstore_ftrace_seq_show, +}; + static ssize_t pstore_file_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - struct pstore_private *ps = file->private_data; + struct seq_file *sf = file->private_data; + struct pstore_private *ps = sf->private; + if (ps->type == PSTORE_TYPE_FTRACE) + return seq_read(file, userbuf, count, ppos); return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size); } +static int pstore_file_open(struct inode *inode, struct file *file) +{ + struct pstore_private *ps = inode->i_private; + struct seq_file *sf; + int err; + const struct seq_operations *sops = NULL; + + if (ps->type == PSTORE_TYPE_FTRACE) + sops = &pstore_ftrace_seq_ops; + + err = seq_open(file, sops); + if (err < 0) + return err; + + sf = file->private_data; + sf->private = ps; + + return 0; +} + +static loff_t pstore_file_llseek(struct file *file, loff_t off, int origin) +{ + struct seq_file *sf = file->private_data; + + if (sf->op) + return seq_lseek(file, off, origin); + return default_llseek(file, off, origin); +} + static const struct file_operations pstore_file_operations = { - .open = simple_open, - .read = pstore_file_read, - .llseek = default_llseek, + .open = pstore_file_open, + .read = pstore_file_read, + .llseek = pstore_file_llseek, + .release = seq_release, }; /* @@ -215,6 +315,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, case PSTORE_TYPE_CONSOLE: sprintf(name, "console-%s", psname); break; + case PSTORE_TYPE_FTRACE: + sprintf(name, "ftrace-%s", psname); + break; case PSTORE_TYPE_MCE: sprintf(name, "mce-%s-%lld", psname, id); break; diff --git a/trunk/fs/pstore/internal.h b/trunk/fs/pstore/internal.h index 3bde461c3f34..958c48d8905c 100644 --- a/trunk/fs/pstore/internal.h +++ b/trunk/fs/pstore/internal.h @@ -1,6 +1,49 @@ +#ifndef __PSTORE_INTERNAL_H__ +#define __PSTORE_INTERNAL_H__ + +#include + +#if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB) +#define PSTORE_CPU_IN_IP 0x1 +#elif NR_CPUS <= 4 && defined(CONFIG_ARM) +#define PSTORE_CPU_IN_IP 0x3 +#endif + +struct pstore_ftrace_record { + unsigned long ip; + unsigned long parent_ip; +#ifndef PSTORE_CPU_IN_IP + unsigned int cpu; +#endif +}; + +static inline void +pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) +{ +#ifndef PSTORE_CPU_IN_IP + rec->cpu = cpu; +#else + rec->ip |= cpu; +#endif +} + +static inline unsigned int +pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) +{ +#ifndef PSTORE_CPU_IN_IP + return rec->cpu; +#else + return rec->ip & PSTORE_CPU_IN_IP; +#endif +} + +extern struct pstore_info *psinfo; + extern void pstore_set_kmsg_bytes(int); extern void pstore_get_records(int); extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, char *data, size_t size, struct timespec time, struct pstore_info *psi); extern int pstore_is_mounted(void); + +#endif diff --git a/trunk/fs/pstore/platform.c b/trunk/fs/pstore/platform.c index 6b3ff045fe6e..29996e8793a7 100644 --- a/trunk/fs/pstore/platform.c +++ b/trunk/fs/pstore/platform.c @@ -61,7 +61,7 @@ static DECLARE_WORK(pstore_work, pstore_dowork); * calls to pstore_register() */ static DEFINE_SPINLOCK(pstore_lock); -static struct pstore_info *psinfo; +struct pstore_info *psinfo; static char *backend; @@ -188,6 +188,14 @@ static void pstore_register_console(void) static void pstore_register_console(void) {} #endif +static int pstore_write_compat(enum pstore_type_id type, + enum kmsg_dump_reason reason, + u64 *id, unsigned int part, + size_t size, struct pstore_info *psi) +{ + return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi); +} + /* * platform specific persistent storage driver registers with * us here. If pstore is already mounted, call the platform @@ -212,6 +220,8 @@ int pstore_register(struct pstore_info *psi) return -EINVAL; } + if (!psi->write) + psi->write = pstore_write_compat; psinfo = psi; mutex_init(&psinfo->read_mutex); spin_unlock(&pstore_lock); diff --git a/trunk/fs/pstore/ram.c b/trunk/fs/pstore/ram.c index 58b93fbd117e..1dd108e0cc60 100644 --- a/trunk/fs/pstore/ram.c +++ b/trunk/fs/pstore/ram.c @@ -45,6 +45,10 @@ static ulong ramoops_console_size = MIN_MEM_SIZE; module_param_named(console_size, ramoops_console_size, ulong, 0400); MODULE_PARM_DESC(console_size, "size of kernel console log"); +static ulong ramoops_ftrace_size = MIN_MEM_SIZE; +module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); +MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); + static ulong mem_address; module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, @@ -63,21 +67,26 @@ MODULE_PARM_DESC(dump_oops, static int ramoops_ecc; module_param_named(ecc, ramoops_ecc, int, 0600); MODULE_PARM_DESC(ramoops_ecc, - "set to 1 to enable ECC support"); + "if non-zero, the option enables ECC support and specifies " + "ECC buffer size in bytes (1 is a special value, means 16 " + "bytes ECC)"); struct ramoops_context { struct persistent_ram_zone **przs; struct persistent_ram_zone *cprz; + struct persistent_ram_zone *fprz; phys_addr_t phys_addr; unsigned long size; size_t record_size; size_t console_size; + size_t ftrace_size; int dump_oops; - bool ecc; + int ecc_size; unsigned int max_dump_cnt; unsigned int dump_write_cnt; unsigned int dump_read_cnt; unsigned int console_read_cnt; + unsigned int ftrace_read_cnt; struct pstore_info pstore; }; @@ -135,6 +144,9 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, if (!prz) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); + if (!prz) + prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, + 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz) return 0; @@ -168,11 +180,12 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz) return len; } -static int ramoops_pstore_write(enum pstore_type_id type, - enum kmsg_dump_reason reason, - u64 *id, - unsigned int part, - size_t size, struct pstore_info *psi) + +static int ramoops_pstore_write_buf(enum pstore_type_id type, + enum kmsg_dump_reason reason, + u64 *id, unsigned int part, + const char *buf, size_t size, + struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz = cxt->przs[cxt->dump_write_cnt]; @@ -181,7 +194,12 @@ static int ramoops_pstore_write(enum pstore_type_id type, if (type == PSTORE_TYPE_CONSOLE) { if (!cxt->cprz) return -ENOMEM; - persistent_ram_write(cxt->cprz, cxt->pstore.buf, size); + persistent_ram_write(cxt->cprz, buf, size); + return 0; + } else if (type == PSTORE_TYPE_FTRACE) { + if (!cxt->fprz) + return -ENOMEM; + persistent_ram_write(cxt->fprz, buf, size); return 0; } @@ -210,7 +228,7 @@ static int ramoops_pstore_write(enum pstore_type_id type, hlen = ramoops_write_kmsg_hdr(prz); if (size + hlen > prz->buffer_size) size = prz->buffer_size - hlen; - persistent_ram_write(prz, cxt->pstore.buf, size); + persistent_ram_write(prz, buf, size); cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt; @@ -232,6 +250,9 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, case PSTORE_TYPE_CONSOLE: prz = cxt->cprz; break; + case PSTORE_TYPE_FTRACE: + prz = cxt->fprz; + break; default: return -EINVAL; } @@ -248,7 +269,7 @@ static struct ramoops_context oops_cxt = { .name = "ramoops", .open = ramoops_pstore_open, .read = ramoops_pstore_read, - .write = ramoops_pstore_write, + .write_buf = ramoops_pstore_write_buf, .erase = ramoops_pstore_erase, }, }; @@ -288,7 +309,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, for (i = 0; i < cxt->max_dump_cnt; i++) { size_t sz = cxt->record_size; - cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc); + cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc_size); if (IS_ERR(cxt->przs[i])) { err = PTR_ERR(cxt->przs[i]); dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", @@ -314,7 +335,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, if (*paddr + sz > *paddr + cxt->size) return -ENOMEM; - *prz = persistent_ram_new(*paddr, sz, cxt->ecc); + *prz = persistent_ram_new(*paddr, sz, cxt->ecc_size); if (IS_ERR(*prz)) { int err = PTR_ERR(*prz); @@ -345,7 +366,8 @@ static int __devinit ramoops_probe(struct platform_device *pdev) if (cxt->max_dump_cnt) goto fail_out; - if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size)) { + if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && + !pdata->ftrace_size)) { pr_err("The memory size and the record/console size must be " "non-zero\n"); goto fail_out; @@ -354,18 +376,20 @@ static int __devinit ramoops_probe(struct platform_device *pdev) pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); pdata->record_size = rounddown_pow_of_two(pdata->record_size); pdata->console_size = rounddown_pow_of_two(pdata->console_size); + pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); cxt->dump_read_cnt = 0; cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; cxt->record_size = pdata->record_size; cxt->console_size = pdata->console_size; + cxt->ftrace_size = pdata->ftrace_size; cxt->dump_oops = pdata->dump_oops; - cxt->ecc = pdata->ecc; + cxt->ecc_size = pdata->ecc_size; paddr = cxt->phys_addr; - dump_mem_sz = cxt->size - cxt->console_size; + dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size; err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); if (err) goto fail_out; @@ -374,9 +398,14 @@ static int __devinit ramoops_probe(struct platform_device *pdev) if (err) goto fail_init_cprz; - if (!cxt->przs && !cxt->cprz) { + err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size); + if (err) + goto fail_init_fprz; + + if (!cxt->przs && !cxt->cprz && !cxt->fprz) { pr_err("memory size too small, minimum is %lu\n", - cxt->console_size + cxt->record_size); + cxt->console_size + cxt->record_size + + cxt->ftrace_size); goto fail_cnt; } @@ -411,9 +440,9 @@ static int __devinit ramoops_probe(struct platform_device *pdev) record_size = pdata->record_size; dump_oops = pdata->dump_oops; - pr_info("attached 0x%lx@0x%llx, ecc: %s\n", + pr_info("attached 0x%lx@0x%llx, ecc: %d\n", cxt->size, (unsigned long long)cxt->phys_addr, - ramoops_ecc ? "on" : "off"); + cxt->ecc_size); return 0; @@ -423,6 +452,8 @@ static int __devinit ramoops_probe(struct platform_device *pdev) cxt->pstore.bufsize = 0; cxt->max_dump_cnt = 0; fail_cnt: + kfree(cxt->fprz); +fail_init_fprz: kfree(cxt->cprz); fail_init_cprz: ramoops_free_przs(cxt); @@ -477,8 +508,13 @@ static void ramoops_register_dummy(void) dummy_data->mem_address = mem_address; dummy_data->record_size = record_size; dummy_data->console_size = ramoops_console_size; + dummy_data->ftrace_size = ramoops_ftrace_size; dummy_data->dump_oops = dump_oops; - dummy_data->ecc = ramoops_ecc; + /* + * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC + * (using 1 byte for ECC isn't much of use anyway). + */ + dummy_data->ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc; dummy = platform_device_register_data(NULL, "ramoops", -1, dummy_data, sizeof(struct ramoops_platform_data)); diff --git a/trunk/fs/pstore/ram_core.c b/trunk/fs/pstore/ram_core.c index a5a7b13d358c..4dabbb8e4270 100644 --- a/trunk/fs/pstore/ram_core.c +++ b/trunk/fs/pstore/ram_core.c @@ -114,7 +114,7 @@ static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz, int ecc_size = prz->ecc_size; int size = prz->ecc_block_size; - if (!prz->ecc) + if (!prz->ecc_size) return; block = buffer->data + (start & ~(ecc_block_size - 1)); @@ -133,7 +133,7 @@ static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) { struct persistent_ram_buffer *buffer = prz->buffer; - if (!prz->ecc) + if (!prz->ecc_size) return; persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), @@ -146,7 +146,7 @@ static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) uint8_t *block; uint8_t *par; - if (!prz->ecc) + if (!prz->ecc_size) return; block = buffer->data; @@ -171,20 +171,21 @@ static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) } } -static int persistent_ram_init_ecc(struct persistent_ram_zone *prz) +static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, + int ecc_size) { int numerr; struct persistent_ram_buffer *buffer = prz->buffer; int ecc_blocks; size_t ecc_total; + int ecc_symsize = 8; + int ecc_poly = 0x11d; - if (!prz->ecc) + if (!ecc_size) return 0; prz->ecc_block_size = 128; - prz->ecc_size = 16; - prz->ecc_symsize = 8; - prz->ecc_poly = 0x11d; + prz->ecc_size = ecc_size; ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); ecc_total = (ecc_blocks + 1) * prz->ecc_size; @@ -202,8 +203,7 @@ static int persistent_ram_init_ecc(struct persistent_ram_zone *prz) * first consecutive root is 0 * primitive element to generate roots = 1 */ - prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, - prz->ecc_size); + prz->rs_decoder = init_rs(ecc_symsize, ecc_poly, 0, 1, prz->ecc_size); if (prz->rs_decoder == NULL) { pr_info("persistent_ram: init_rs failed\n"); return -EINVAL; @@ -391,13 +391,11 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, } static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz, - bool ecc) + int ecc_size) { int ret; - prz->ecc = ecc; - - ret = persistent_ram_init_ecc(prz); + ret = persistent_ram_init_ecc(prz, ecc_size); if (ret) return ret; @@ -445,7 +443,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz) struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start, size_t size, - bool ecc) + int ecc_size) { struct persistent_ram_zone *prz; int ret = -ENOMEM; @@ -460,7 +458,7 @@ struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start, if (ret) goto err; - ret = persistent_ram_post_init(prz, ecc); + ret = persistent_ram_post_init(prz, ecc_size); if (ret) goto err; diff --git a/trunk/include/linux/pstore.h b/trunk/include/linux/pstore.h index 1bd014b8e432..120443b0fda5 100644 --- a/trunk/include/linux/pstore.h +++ b/trunk/include/linux/pstore.h @@ -30,6 +30,7 @@ enum pstore_type_id { PSTORE_TYPE_DMESG = 0, PSTORE_TYPE_MCE = 1, PSTORE_TYPE_CONSOLE = 2, + PSTORE_TYPE_FTRACE = 3, PSTORE_TYPE_UNKNOWN = 255 }; @@ -48,11 +49,23 @@ struct pstore_info { int (*write)(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, size_t size, struct pstore_info *psi); + int (*write_buf)(enum pstore_type_id type, + enum kmsg_dump_reason reason, u64 *id, + unsigned int part, const char *buf, size_t size, + struct pstore_info *psi); int (*erase)(enum pstore_type_id type, u64 id, struct pstore_info *psi); void *data; }; + +#ifdef CONFIG_PSTORE_FTRACE +extern void pstore_ftrace_call(unsigned long ip, unsigned long parent_ip); +#else +static inline void pstore_ftrace_call(unsigned long ip, unsigned long parent_ip) +{ } +#endif + #ifdef CONFIG_PSTORE extern int pstore_register(struct pstore_info *); #else diff --git a/trunk/include/linux/pstore_ram.h b/trunk/include/linux/pstore_ram.h index e681af92c04b..af848e1593b9 100644 --- a/trunk/include/linux/pstore_ram.h +++ b/trunk/include/linux/pstore_ram.h @@ -33,7 +33,6 @@ struct persistent_ram_zone { size_t buffer_size; /* ECC correction */ - bool ecc; char *par_buffer; char *par_header; struct rs_control *rs_decoder; @@ -41,8 +40,6 @@ struct persistent_ram_zone { int bad_blocks; int ecc_block_size; int ecc_size; - int ecc_symsize; - int ecc_poly; char *old_log; size_t old_log_size; @@ -50,7 +47,7 @@ struct persistent_ram_zone { struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start, size_t size, - bool ecc); + int ecc_size); void persistent_ram_free(struct persistent_ram_zone *prz); void persistent_ram_zap(struct persistent_ram_zone *prz); @@ -75,8 +72,9 @@ struct ramoops_platform_data { unsigned long mem_address; unsigned long record_size; unsigned long console_size; + unsigned long ftrace_size; int dump_oops; - bool ecc; + int ecc_size; }; #endif diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index 49249c28690d..44ee11e31b82 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -3172,10 +3172,10 @@ static int tracing_set_tracer(const char *buf) } destroy_trace_option_files(topts); - current_trace = t; + current_trace = &nop_trace; - topts = create_trace_option_files(current_trace); - if (current_trace->use_max_tr) { + topts = create_trace_option_files(t); + if (t->use_max_tr) { int cpu; /* we need to make per cpu buffer sizes equivalent */ for_each_tracing_cpu(cpu) { @@ -3195,6 +3195,7 @@ static int tracing_set_tracer(const char *buf) goto out; } + current_trace = t; trace_branch_enable(tr); out: mutex_unlock(&trace_types_lock); diff --git a/trunk/kernel/trace/trace_functions.c b/trunk/kernel/trace/trace_functions.c index c7b0c6a7db09..a426f410c060 100644 --- a/trunk/kernel/trace/trace_functions.c +++ b/trunk/kernel/trace/trace_functions.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "trace.h" @@ -74,6 +75,14 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) preempt_enable_notrace(); } +/* Our two options */ +enum { + TRACE_FUNC_OPT_STACK = 0x1, + TRACE_FUNC_OPT_PSTORE = 0x2, +}; + +static struct tracer_flags func_flags; + static void function_trace_call(unsigned long ip, unsigned long parent_ip) { @@ -97,6 +106,12 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) disabled = atomic_inc_return(&data->disabled); if (likely(disabled == 1)) { + /* + * So far tracing doesn't support multiple buffers, so + * we make an explicit call for now. + */ + if (unlikely(func_flags.val & TRACE_FUNC_OPT_PSTORE)) + pstore_ftrace_call(ip, parent_ip); pc = preempt_count(); trace_function(tr, ip, parent_ip, flags, pc); } @@ -158,14 +173,12 @@ static struct ftrace_ops trace_stack_ops __read_mostly = .flags = FTRACE_OPS_FL_GLOBAL, }; -/* Our two options */ -enum { - TRACE_FUNC_OPT_STACK = 0x1, -}; - static struct tracer_opt func_opts[] = { #ifdef CONFIG_STACKTRACE { TRACER_OPT(func_stack_trace, TRACE_FUNC_OPT_STACK) }, +#endif +#ifdef CONFIG_PSTORE_FTRACE + { TRACER_OPT(func_pstore, TRACE_FUNC_OPT_PSTORE) }, #endif { } /* Always set a last empty entry */ }; @@ -204,10 +217,11 @@ static void tracing_stop_function_trace(void) static int func_set_flag(u32 old_flags, u32 bit, int set) { - if (bit == TRACE_FUNC_OPT_STACK) { + switch (bit) { + case TRACE_FUNC_OPT_STACK: /* do nothing if already set */ if (!!set == !!(func_flags.val & TRACE_FUNC_OPT_STACK)) - return 0; + break; if (set) { unregister_ftrace_function(&trace_ops); @@ -217,10 +231,14 @@ static int func_set_flag(u32 old_flags, u32 bit, int set) register_ftrace_function(&trace_ops); } - return 0; + break; + case TRACE_FUNC_OPT_PSTORE: + break; + default: + return -EINVAL; } - return -EINVAL; + return 0; } static struct tracer function_trace __read_mostly =