diff options
319 files changed, 27566 insertions, 5453 deletions
@@ -32,6 +32,7 @@ Brian Avery <b.avery@hp.com> Brian King <brking@us.ibm.com> Christoph Hellwig <hch@lst.de> Corey Minyard <minyard@acm.org> +Damian Hobson-Garcia <dhobsong@igel.co.jp> David Brownell <david-b@pacbell.net> David Woodhouse <dwmw2@shinybook.infradead.org> Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block index 4873c759d53..c1eb41cb987 100644 --- a/Documentation/ABI/testing/sysfs-block +++ b/Documentation/ABI/testing/sysfs-block @@ -142,3 +142,67 @@ Description: with the previous I/O request are enabled. When set to 2, all merge tries are disabled. The default value is 0 - which enables all types of merge tries. + +What: /sys/block/<disk>/discard_alignment +Date: May 2011 +Contact: Martin K. Petersen <martin.petersen@oracle.com> +Description: + Devices that support discard functionality may + internally allocate space in units that are bigger than + the exported logical block size. The discard_alignment + parameter indicates how many bytes the beginning of the + device is offset from the internal allocation unit's + natural alignment. + +What: /sys/block/<disk>/<partition>/discard_alignment +Date: May 2011 +Contact: Martin K. Petersen <martin.petersen@oracle.com> +Description: + Devices that support discard functionality may + internally allocate space in units that are bigger than + the exported logical block size. The discard_alignment + parameter indicates how many bytes the beginning of the + partition is offset from the internal allocation unit's + natural alignment. + +What: /sys/block/<disk>/queue/discard_granularity +Date: May 2011 +Contact: Martin K. Petersen <martin.petersen@oracle.com> +Description: + Devices that support discard functionality may + internally allocate space using units that are bigger + than the logical block size. The discard_granularity + parameter indicates the size of the internal allocation + unit in bytes if reported by the device. Otherwise the + discard_granularity will be set to match the device's + physical block size. A discard_granularity of 0 means + that the device does not support discard functionality. + +What: /sys/block/<disk>/queue/discard_max_bytes +Date: May 2011 +Contact: Martin K. Petersen <martin.petersen@oracle.com> +Description: + Devices that support discard functionality may have + internal limits on the number of bytes that can be + trimmed or unmapped in a single operation. Some storage + protocols also have inherent limits on the number of + blocks that can be described in a single command. The + discard_max_bytes parameter is set by the device driver + to the maximum number of bytes that can be discarded in + a single operation. Discard requests issued to the + device must not exceed this limit. A discard_max_bytes + value of 0 means that the device does not support + discard functionality. + +What: /sys/block/<disk>/queue/discard_zeroes_data +Date: May 2011 +Contact: Martin K. Petersen <martin.petersen@oracle.com> +Description: + Devices that support discard functionality may return + stale or random data when a previously discarded block + is read back. This can cause problems if the filesystem + expects discarded blocks to be explicitly cleared. If a + device reports that it deterministically returns zeroes + when a discarded area is read the discard_zeroes_data + parameter will be set to one. Otherwise it will be 0 and + the result of reading a discarded area is undefined. diff --git a/Documentation/blockdev/cciss.txt b/Documentation/blockdev/cciss.txt index 89698e8df7d..c00c6a5ab21 100644 --- a/Documentation/blockdev/cciss.txt +++ b/Documentation/blockdev/cciss.txt @@ -169,3 +169,18 @@ is issued which positions the tape to a known position. Typically you must rewind the tape (by issuing "mt -f /dev/st0 rewind" for example) before i/o can proceed again to a tape drive which was reset. +There is a cciss_tape_cmds module parameter which can be used to make cciss +allocate more commands for use by tape drives. Ordinarily only a few commands +(6) are allocated for tape drives because tape drives are slow and +infrequently used and the primary purpose of Smart Array controllers is to +act as a RAID controller for disk drives, so the vast majority of commands +are allocated for disk devices. However, if you have more than a few tape +drives attached to a smart array, the default number of commands may not be +enought (for example, if you have 8 tape drives, you could only rewind 6 +at one time with the default number of commands.) The cciss_tape_cmds module +parameter allows more commands (up to 16 more) to be allocated for use by +tape drives. For example: + + insmod cciss.ko cciss_tape_cmds=16 + +Or, as a kernel boot parameter passed in via grub: cciss.cciss_tape_cmds=8 diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index b22abba78fe..13de64c7f0a 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt @@ -25,6 +25,8 @@ Other applications are described in the following papers: http://xcpu.org/papers/cellfs-talk.pdf * PROSE I/O: Using 9p to enable Application Partitions http://plan9.escet.urjc.es/iwp9/cready/PROSE_iwp9_2006.pdf + * VirtFS: A Virtualization Aware File System pass-through + http://goo.gl/3WPDg USAGE ===== @@ -130,31 +132,20 @@ OPTIONS RESOURCES ========= -Our current recommendation is to use Inferno (http://www.vitanuova.com/nferno/index.html) -as the 9p server. You can start a 9p server under Inferno by issuing the -following command: - ; styxlisten -A tcp!*!564 export '#U*' +Protocol specifications are maintained on github: +http://ericvh.github.com/9p-rfc/ -The -A specifies an unauthenticated export. The 564 is the port # (you may -have to choose a higher port number if running as a normal user). The '#U*' -specifies exporting the root of the Linux name space. You may specify a -subset of the namespace by extending the path: '#U*'/tmp would just export -/tmp. For more information, see the Inferno manual pages covering styxlisten -and export. +9p client and server implementations are listed on +http://9p.cat-v.org/implementations -A Linux version of the 9p server is now maintained under the npfs project -on sourceforge (http://sourceforge.net/projects/npfs). The currently -maintained version is the single-threaded version of the server (named spfs) -available from the same SVN repository. +A 9p2000.L server is being developed by LLNL and can be found +at http://code.google.com/p/diod/ There are user and developer mailing lists available through the v9fs project on sourceforge (http://sourceforge.net/projects/v9fs). -A stand-alone version of the module (which should build for any 2.6 kernel) -is available via (http://github.com/ericvh/9p-sac/tree/master) - -News and other information is maintained on SWiK (http://swik.net/v9fs) -and the Wiki (http://sf.net/apps/mediawiki/v9fs/index.php). +News and other information is maintained on a Wiki. +(http://sf.net/apps/mediawiki/v9fs/index.php). Bug reports may be issued through the kernel.org bugzilla (http://bugzilla.kernel.org) diff --git a/Documentation/hwmon/emc6w201 b/Documentation/hwmon/emc6w201 new file mode 100644 index 00000000000..32f355aaf56 --- /dev/null +++ b/Documentation/hwmon/emc6w201 @@ -0,0 +1,42 @@ +Kernel driver emc6w201 +====================== + +Supported chips: + * SMSC EMC6W201 + Prefix: 'emc6w201' + Addresses scanned: I2C 0x2c, 0x2d, 0x2e + Datasheet: Not public + +Author: Jean Delvare <khali@linux-fr.org> + + +Description +----------- + +From the datasheet: + +"The EMC6W201 is an environmental monitoring device with automatic fan +control capability and enhanced system acoustics for noise suppression. +This ACPI compliant device provides hardware monitoring for up to six +voltages (including its own VCC) and five external thermal sensors, +measures the speed of up to five fans, and controls the speed of +multiple DC fans using three Pulse Width Modulator (PWM) outputs. Note +that it is possible to control more than three fans by connecting two +fans to one PWM output. The EMC6W201 will be available in a 36-pin +QFN package." + +The device is functionally close to the EMC6D100 series, but is +register-incompatible. + +The driver currently only supports the monitoring of the voltages, +temperatures and fan speeds. Limits can be changed. Alarms are not +supported, and neither is fan speed control. + + +Known Systems With EMC6W201 +--------------------------- + +The EMC6W201 is a rare device, only found on a few systems, made in +2005 and 2006. Known systems with this device: +* Dell Precision 670 workstation +* Gigabyte 2CEWH mainboard diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index df02245d141..84d2623810f 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -6,6 +6,10 @@ Supported chips: Prefix: 'f71808e' Addresses scanned: none, address read from Super I/O config space Datasheet: Not public + * Fintek F71808A + Prefix: 'f71808a' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power new file mode 100644 index 00000000000..a92918e0bd6 --- /dev/null +++ b/Documentation/hwmon/fam15h_power @@ -0,0 +1,37 @@ +Kernel driver fam15h_power +========================== + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'fam15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <andreas.herrmann3@amd.com> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers: + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_crit (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor. diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp index d2b56a4fd1f..0393c89277c 100644 --- a/Documentation/hwmon/k10temp +++ b/Documentation/hwmon/k10temp @@ -11,6 +11,7 @@ Supported chips: Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra) * AMD Family 12h processors: "Llano" * AMD Family 14h processors: "Brazos" (C/E/G-Series) +* AMD Family 15h processors: "Bulldozer" Prefix: 'k10temp' Addresses scanned: PCI space @@ -40,7 +41,7 @@ Description ----------- This driver permits reading of the internal temperature sensor of AMD -Family 10h/11h/12h/14h processors. +Family 10h/11h/12h/14h/15h processors. All these processors have a sensor, but on those for Socket F or AM2+, the sensor may return inconsistent values (erratum 319). The driver diff --git a/Documentation/hwmon/max6650 b/Documentation/hwmon/max6650 index c565650fcfc..58d9644a2bd 100644 --- a/Documentation/hwmon/max6650 +++ b/Documentation/hwmon/max6650 @@ -2,9 +2,13 @@ Kernel driver max6650 ===================== Supported chips: - * Maxim 6650 / 6651 + * Maxim MAX6650 Prefix: 'max6650' - Addresses scanned: I2C 0x1b, 0x1f, 0x48, 0x4b + Addresses scanned: none + Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf + * Maxim MAX6651 + Prefix: 'max6651' + Addresses scanned: none Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf Authors: @@ -15,10 +19,10 @@ Authors: Description ----------- -This driver implements support for the Maxim 6650/6651 +This driver implements support for the Maxim MAX6650 and MAX6651. -The 2 devices are very similar, but the Maxim 6550 has a reduced feature -set, e.g. only one fan-input, instead of 4 for the 6651. +The 2 devices are very similar, but the MAX6550 has a reduced feature +set, e.g. only one fan-input, instead of 4 for the MAX6651. The driver is not able to distinguish between the 2 devices. @@ -36,6 +40,13 @@ fan1_div rw sets the speed range the inputs can handle. Legal values are 1, 2, 4, and 8. Use lower values for faster fans. +Usage notes +----------- + +This driver does not auto-detect devices. You will have to instantiate the +devices explicitly. Please see Documentation/i2c/instantiating-devices for +details. + Module parameters ----------------- diff --git a/MAINTAINERS b/MAINTAINERS index 59cd2f5a112..a26c9ee7703 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -287,35 +287,35 @@ F: sound/pci/ad1889.* AD525X ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/AD5254 S: Supported F: drivers/misc/ad525x_dpot.c AD5398 CURRENT REGULATOR DRIVER (AD5398/AD5821) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/AD5398 S: Supported F: drivers/regulator/ad5398.c AD714X CAPACITANCE TOUCH SENSOR DRIVER (AD7142/3/7/8/7A) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/AD7142 S: Supported F: drivers/input/misc/ad714x.c AD7877 TOUCHSCREEN DRIVER M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/AD7877 S: Supported F: drivers/input/touchscreen/ad7877.c AD7879 TOUCHSCREEN DRIVER (AD7879/AD7889) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/AD7879 S: Supported F: drivers/input/touchscreen/ad7879.c @@ -341,7 +341,7 @@ F: drivers/net/wireless/adm8211.* ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/ADP5520 S: Supported F: drivers/mfd/adp5520.c @@ -352,7 +352,7 @@ F: drivers/input/keyboard/adp5520-keys.c ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/ADP5588 S: Supported F: drivers/input/keyboard/adp5588-keys.c @@ -360,7 +360,7 @@ F: drivers/gpio/adp5588-gpio.c ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/ADP8860 S: Supported F: drivers/video/backlight/adp8860_bl.c @@ -387,7 +387,7 @@ F: drivers/hwmon/adt7475.c ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346) M: Michael Hennerich <michael.hennerich@analog.com> -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org W: http://wiki.analog.com/ADXL345 S: Supported F: drivers/input/misc/adxl34x.c @@ -483,6 +483,13 @@ F: drivers/tty/serial/altera_jtaguart.c F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h +AMD FAM15H PROCESSOR POWER MONITORING DRIVER +M: Andreas Herrmann <andreas.herrmann3@amd.com> +L: lm-sensors@lm-sensors.org +S: Maintained +F: Documentation/hwmon/fam15h_power +F: drivers/hwmon/fam15h_power.c + AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER M: Thomas Dahlmann <dahlmann.thomas@arcor.de> L: linux-geode@lists.infradead.org (moderated for non-subscribers) @@ -526,7 +533,7 @@ S: Maintained F: drivers/infiniband/hw/amso1100/ ANALOG DEVICES INC ASOC CODEC DRIVERS -L: device-driver-devel@blackfin.uclinux.org +L: device-drivers-devel@blackfin.uclinux.org L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://wiki.analog.com/ S: Supported @@ -220,6 +220,14 @@ ifeq ($(ARCH),sh64) SRCARCH := sh endif +# Additional ARCH settings for tile +ifeq ($(ARCH),tilepro) + SRCARCH := tile +endif +ifeq ($(ARCH),tilegx) + SRCARCH := tile +endif + # Where to locate arch specific headers hdr-arch := $(SRCARCH) @@ -1009,7 +1017,8 @@ include/generated/utsrelease.h: include/config/kernel.release FORCE PHONY += headerdep headerdep: - $(Q)find include/ -name '*.h' | xargs --max-args 1 scripts/headerdep.pl + $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \ + $(srctree)/scripts/headerdep.pl -I$(srctree)/include # --------------------------------------------------------------------------- @@ -1417,13 +1426,15 @@ tags TAGS cscope gtags: FORCE # Scripts to check various things for consistency # --------------------------------------------------------------------------- +PHONY += includecheck versioncheck coccicheck namespacecheck export_report + includecheck: - find * $(RCS_FIND_IGNORE) \ + find $(srctree)/* $(RCS_FIND_IGNORE) \ -name '*.[hcS]' -type f -print | sort \ | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl versioncheck: - find * $(RCS_FIND_IGNORE) \ + find $(srctree)/* $(RCS_FIND_IGNORE) \ -name '*.[hcS]' -type f -print | sort \ | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index e2507f66f9d..612b27000c3 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -30,6 +30,11 @@ obj-$(CONFIG_ARCH_SH7377) += entry-intc.o obj-$(CONFIG_ARCH_SH7372) += entry-intc.o obj-$(CONFIG_ARCH_SH73A0) += entry-gic.o +# PM objects +obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o +obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o + # Board objects obj-$(CONFIG_MACH_G3EVM) += board-g3evm.o obj-$(CONFIG_MACH_G4EVM) += board-g4evm.o diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 3e6f0aab460..c95258c274c 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -34,6 +34,8 @@ #include <linux/input/sh_keysc.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> +#include <linux/mmc/sh_mobile_sdhi.h> +#include <linux/mfd/tmio.h> #include <linux/sh_clk.h> #include <video/sh_mobile_lcdc.h> #include <video/sh_mipi_dsi.h> @@ -156,10 +158,19 @@ static struct resource sh_mmcif_resources[] = { }, }; +static struct sh_mmcif_dma sh_mmcif_dma = { + .chan_priv_rx = { + .slave_id = SHDMA_SLAVE_MMCIF_RX, + }, + .chan_priv_tx = { + .slave_id = SHDMA_SLAVE_MMCIF_TX, + }, +}; static struct sh_mmcif_plat_data sh_mmcif_platdata = { .sup_pclk = 0, .ocr = MMC_VDD_165_195, .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, + .dma = &sh_mmcif_dma, }; static struct platform_device mmc_device = { @@ -296,11 +307,13 @@ static struct platform_device lcdc0_device = { /* MIPI-DSI */ static struct resource mipidsi0_resources[] = { [0] = { + .name = "DSI0", .start = 0xfeab0000, .end = 0xfeab3fff, .flags = IORESOURCE_MEM, }, [1] = { + .name = "DSI0", .start = 0xfeab4000, .end = 0xfeab7fff, .flags = IORESOURCE_MEM, @@ -325,6 +338,89 @@ static struct platform_device mipidsi0_device = { }, }; +static struct sh_mobile_sdhi_info sdhi0_info = { + .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, + .tmio_caps = MMC_CAP_SD_HIGHSPEED, + .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, +}; + +static struct resource sdhi0_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0xee100000, + .end = 0xee1000ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(83), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = gic_spi(84), + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = gic_spi(85), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi0_device = { + .name = "sh_mobile_sdhi", + .id = 0, + .num_resources = ARRAY_SIZE(sdhi0_resources), + .resource = sdhi0_resources, + .dev = { + .platform_data = &sdhi0_info, + }, +}; + +void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) +{ + gpio_set_value(GPIO_PORT114, state); +} + +static struct sh_mobile_sdhi_info sh_sdhi1_platdata = { + .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, + .tmio_caps = MMC_CAP_NONREMOVABLE, + .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .set_pwr = ag5evm_sdhi1_set_pwr, +}; + +static struct resource sdhi1_resources[] = { + [0] = { + .name = "SDHI1", + .start = 0xee120000, + .end = 0xee1200ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(87), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = gic_spi(88), + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = gic_spi(89), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi1_device = { + .name = "sh_mobile_sdhi", + .id = 1, + .dev = { + .platform_data = &sh_sdhi1_platdata, + }, + .num_resources = ARRAY_SIZE(sdhi1_resources), + .resource = sdhi1_resources, +}; + static struct platform_device *ag5evm_devices[] __initdata = { ð_device, &keysc_device, @@ -333,6 +429,8 @@ static struct platform_device *ag5evm_devices[] __initdata = { &irda_device, &lcdc0_device, &mipidsi0_device, + &sdhi0_device, + &sdhi1_device, }; static struct map_desc ag5evm_io_desc[] __initdata = { @@ -454,6 +552,26 @@ static void __init ag5evm_init(void) /* MIPI-DSI clock setup */ __raw_writel(0x2a809010, DSI0PHYCR); + /* enable SDHI0 on CN15 [SD I/F] */ + gpio_request(GPIO_FN_SDHICD0, NULL); + gpio_request(GPIO_FN_SDHIWP0, NULL); + gpio_request(GPIO_FN_SDHICMD0, NULL); + gpio_request(GPIO_FN_SDHICLK0, NULL); + gpio_request(GPIO_FN_SDHID0_3, NULL); + gpio_request(GPIO_FN_SDHID0_2, NULL); + gpio_request(GPIO_FN_SDHID0_1, NULL); + gpio_request(GPIO_FN_SDHID0_0, NULL); + + /* enable SDHI1 on CN4 [WLAN I/F] */ + gpio_request(GPIO_FN_SDHICLK1, NULL); + gpio_request(GPIO_FN_SDHICMD1_PU, NULL); + gpio_request(GPIO_FN_SDHID1_3_PU, NULL); + gpio_request(GPIO_FN_SDHID1_2_PU, NULL); + gpio_request(GPIO_FN_SDHID1_1_PU, NULL); + gpio_request(GPIO_FN_SDHID1_0_PU, NULL); + gpio_request(GPIO_PORT114, "sdhi1_power"); + gpio_direction_output(GPIO_PORT114, 0); + #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff); diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 1e35fa976d6..08acb6ec813 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -316,8 +316,16 @@ static struct resource sdhi0_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0e00) /* SDHI0 */, - .flags = IORESOURCE_IRQ, + .start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */, + .flags = IORESOURCE_IRQ, }, }; @@ -349,8 +357,16 @@ static struct resource sdhi1_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0e80), - .flags = IORESOURCE_IRQ, + .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */ + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */ + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */ + .flags = IORESOURCE_IRQ, }, }; @@ -980,11 +996,6 @@ static void __init hdmi_init_pm_clock(void) goto out; } - ret = clk_enable(&sh7372_pllc2_clk); - if (ret < 0) { - pr_err("Cannot enable pllc2 clock\n"); - goto out; - } pr_debug("PLLC2 set frequency %lu\n", rate); ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); @@ -1343,6 +1354,7 @@ static void __init ap4evb_init(void) hdmi_init_pm_clock(); fsi_init_pm_clock(); + sh7372_pm_init(); } static void __init ap4evb_timer_init(void) diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c index c87a7b7c583..8e3c5559f27 100644 --- a/arch/arm/mach-shmobile/board-g4evm.c +++ b/arch/arm/mach-shmobile/board-g4evm.c @@ -205,7 +205,7 @@ static struct resource sdhi0_resources[] = { [0] = { .name = "SDHI0", .start = 0xe6d50000, - .end = 0xe6d50nff, + .end = 0xe6d500ff, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 7da2ca24229..448ddbe4333 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -43,6 +43,7 @@ #include <linux/sh_intc.h> #include <linux/tca6416_keypad.h> #include <linux/usb/r8a66597.h> +#include <linux/usb/renesas_usbhs.h> #include <video/sh_mobile_hdmi.h> #include <video/sh_mobile_lcdc.h> @@ -143,7 +144,30 @@ * open | external VBUS | Function * * *1 - * CN31 is used as Host in Linux. + * CN31 is used as + * CONFIG_USB_R8A66597_HCD Host + * CONFIG_USB_RENESAS_USBHS Function + * + * CAUTION + * + * renesas_usbhs driver can use external interrupt mode + * (which come from USB-PHY) or autonomy mode (it use own interrupt) + * for detecting connection/disconnection when Function. + * USB will be power OFF while it has been disconnecting + * if external interrupt mode, and it is always power ON if autonomy mode, + * + * mackerel can not use external interrupt (IRQ7-PORT167) mode on "USB0", + * because Touchscreen is using IRQ7-PORT40. + * It is impossible to use IRQ7 demux on this board. + * + * We can use external interrupt mode USB-Function on "USB1". + * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. + * But don't select both drivers in same time. + * These uses same IRQ number for request_irq(), and aren't supporting + * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE. + * + * Actually these are old/new version of USB driver. + * This mean its register will be broken if it supports SHARD IRQ, */ /* @@ -185,6 +209,7 @@ * FIXME !! * * gpio_no_direction + * gpio_pull_down * are quick_hack. * * current gpio frame work doesn't have @@ -196,6 +221,16 @@ static void __init gpio_no_direction(u32 addr) __raw_writeb(0x00, addr); } +static void __init gpio_pull_down(u32 addr) +{ + u8 data = __raw_readb(addr); + + data &= 0x0F; + data |= 0xA0; + + __raw_writeb(data, addr); +} + /* MTD */ static struct mtd_partition nor_flash_partitions[] = { { @@ -458,12 +493,6 @@ static void __init hdmi_init_pm_clock(void) goto out; } - ret = clk_enable(&sh7372_pllc2_clk); - if (ret < 0) { - pr_err("Cannot enable pllc2 clock\n"); - goto out; - } - pr_debug("PLLC2 set frequency %lu\n", rate); ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); @@ -515,6 +544,157 @@ static struct platform_device usb1_host_device = { .resource = usb1_host_resources, }; +/* USB1 (Function) */ +#define USB_PHY_MODE (1 << 4) +#define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) +#define USB_PHY_ON (1 << 1) +#define USB_PHY_OFF (1 << 0) +#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) + +struct usbhs_private { + unsigned int irq; + unsigned int usbphyaddr; + unsigned int usbcrcaddr; + struct renesas_usbhs_platform_info info; +}; + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), \ + struct usbhs_private, info) + +#define usbhs_is_connected(priv) \ + (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) + +static int usbhs1_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static int usbhs1_get_vbus(struct platform_device *pdev) +{ + return usbhs_is_connected(usbhs_get_priv(pdev)); +} + +static irqreturn_t usbhs1_interrupt(int irq, void *data) +{ + struct platform_device *pdev = data; + struct usbhs_private *priv = usbhs_get_priv(pdev); + + dev_dbg(&pdev->dev, "%s\n", __func__); + + renesas_usbhs_call_notify_hotplug(pdev); + + /* clear status */ + __raw_writew(__raw_readw(priv->usbphyaddr) | USB_PHY_INT_CLR, + priv->usbphyaddr); + + return IRQ_HANDLED; +} + +static int usbhs1_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + int ret; + + irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH); + + /* clear interrupt status */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); + + ret = request_irq(priv->irq, usbhs1_interrupt, 0, + dev_name(&pdev->dev), pdev); + if (ret) { + dev_err(&pdev->dev, "request_irq err\n"); + return ret; + } + + /* enable USB phy interrupt */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->usbphyaddr); + + return 0; +} + +static void usbhs1_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* clear interrupt status */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); + + free_irq(priv->irq, pdev); +} + +static void usbhs1_phy_reset(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* init phy */ + __raw_writew(0x8a0a, priv->usbcrcaddr); +} + +static u32 usbhs1_pipe_cfg[] = { + USB_ENDPOINT_XFER_CONTROL, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, +}; + +static struct usbhs_private usbhs1_private = { + .irq = evt2irq(0x0300), /* IRQ8 */ + .usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */ + .usbcrcaddr = 0xE6058130, /* USBCR4 */ + .info = { + .platform_callback = { + .hardware_init = usbhs1_hardware_init, + .hardware_exit = usbhs1_hardware_exit, + .phy_reset = usbhs1_phy_reset, + .get_id = usbhs1_get_id, + .get_vbus = usbhs1_get_vbus, + }, + .driver_param = { + .buswait_bwait = 4, + .pipe_type = usbhs1_pipe_cfg, + .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), + }, + }, +}; + +static struct resource usbhs1_resources[] = { + [0] = { + .name = "USBHS", + .start = 0xE68B0000, + .end = 0xE68B00E6 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1ce0) /* USB1_USB1I0 */, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs1_device = { + .name = "renesas_usbhs", + .id = 1, + .dev = { + .platform_data = &usbhs1_private.info, + }, + .num_resources = ARRAY_SIZE(usbhs1_resources), + .resource = usbhs1_resources, +}; + + /* LED */ static struct gpio_led mackerel_leds[] = { { @@ -690,7 +870,15 @@ static struct resource sdhi0_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0e00) /* SDHI0 */, + .start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */, .flags = IORESOURCE_IRQ, }, }; @@ -705,7 +893,7 @@ static struct platform_device sdhi0_device = { }, }; -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) /* SDHI1 */ static struct sh_mobile_sdhi_info sdhi1_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, @@ -725,7 +913,15 @@ static struct resource sdhi1_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0e80), + .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */ + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */ + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */ .flags = IORESOURCE_IRQ, }, }; @@ -768,7 +964,15 @@ static struct resource sdhi2_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x1200), + .start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */ + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */ + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */ .flags = IORESOURCE_IRQ, }, }; @@ -803,6 +1007,15 @@ static struct resource sh_mmcif_resources[] = { }, }; +static struct sh_mmcif_dma sh_mmcif_dma = { + .chan_priv_rx = { + .slave_id = SHDMA_SLAVE_MMCIF_RX, + }, + .chan_priv_tx = { + .slave_id = SHDMA_SLAVE_MMCIF_TX, + }, +}; + static struct sh_mmcif_plat_data sh_mmcif_plat = { .sup_pclk = 0, .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, @@ -810,6 +1023,7 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = { MMC_CAP_8_BIT_DATA | MMC_CAP_NEEDS_POLL, .get_cd = slot_cn7_get_cd, + .dma = &sh_mmcif_dma, }; static struct platform_device sh_mmcif_device = { @@ -858,37 +1072,23 @@ static struct soc_camera_link camera_link = { .priv = &camera_info, }; -static void dummy_release(struct device *dev) +static struct platform_device *camera_device; + +static void mackerel_camera_release(struct device *dev) { + soc_camera_platform_release(&camera_device); } -static struct platform_device camera_device = { - .name = "soc_camera_platform", - .dev = { - .platform_data = &camera_info, - .release = dummy_release, - }, -}; - static int mackerel_camera_add(struct soc_camera_link *icl, struct device *dev) { - if (icl != &camera_link) - return -ENODEV; - - camera_info.dev = dev; - - return platform_device_register(&camera_device); + return soc_camera_platform_add(icl, dev, &camera_device, &camera_link, + mackerel_camera_release, 0); } static void mackerel_camera_del(struct soc_camera_link *icl) { - if (icl != &camera_link) - return; - - platform_device_unregister(&camera_device); - memset(&camera_device.dev.kobj, 0, - sizeof(camera_device.dev.kobj)); + soc_camera_platform_del(icl, camera_device, &camera_link); } static struct sh_mobile_ceu_info sh_mobile_ceu_info = { @@ -935,12 +1135,13 @@ static struct platform_device *mackerel_devices[] __initdata = { &smc911x_device, &lcdc_device, &usb1_host_device, + &usbhs1_device, &leds_device, &fsi_device, &fsi_ak4643_device, &fsi_hdmi_device, &sdhi0_device, -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) &sdhi1_device, #endif &sdhi2_device, @@ -1030,6 +1231,7 @@ static void __init mackerel_map_io(void) #define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define GPIO_PORT168CR 0xE60520A8 #define SRCR4 0xe61580bc #define USCCR1 0xE6058144 static void __init mackerel_init(void) @@ -1088,6 +1290,7 @@ static void __init mackerel_init(void) gpio_request(GPIO_FN_OVCN_1_114, NULL); gpio_request(GPIO_FN_EXTLP_1, NULL); gpio_request(GPIO_FN_OVCN2_1, NULL); + gpio_pull_down(GPIO_PORT168CR); /* setup USB phy */ __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ @@ -1140,7 +1343,7 @@ static void __init mackerel_init(void) gpio_request(GPIO_FN_SDHID0_1, NULL); gpio_request(GPIO_FN_SDHID0_0, NULL); -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) /* enable SDHI1 */ gpio_request(GPIO_FN_SDHICMD1, NULL); gpio_request(GPIO_FN_SDHICLK1, NULL); @@ -1216,6 +1419,7 @@ static void __init mackerel_init(void) platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); hdmi_init_pm_clock(); + sh7372_pm_init(); } static void __init mackerel_timer_init(void) diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index e9731b5a73e..d17eb66f4ac 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -44,6 +44,11 @@ #define DSI1PCKCR 0xe6150098 #define PLLC01CR 0xe6150028 #define PLLC2CR 0xe615002c +#define RMSTPCR0 0xe6150110 +#define RMSTPCR1 0xe6150114 +#define RMSTPCR2 0xe6150118 +#define RMSTPCR3 0xe615011c +#define RMSTPCR4 0xe6150120 #define SMSTPCR0 0xe6150130 #define SMSTPCR1 0xe6150134 #define SMSTPCR2 0xe6150138 @@ -421,9 +426,6 @@ static unsigned long fsidiv_recalc(struct clk *clk) value = __raw_readl(clk->mapping->base); - if ((value & 0x3) != 0x3) - return 0; - value >>= 16; if (value < 2) return 0; @@ -504,7 +506,7 @@ static struct clk *late_main_clks[] = { enum { MSTP001, MSTP131, MSTP130, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, - MSTP118, MSTP117, MSTP116, + MSTP118, MSTP117, MSTP116, MSTP113, MSTP106, MSTP101, MSTP100, MSTP223, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, @@ -527,6 +529,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ + [MSTP113] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 13, 0), /* MERAM */ [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */ [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */ [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ @@ -617,6 +620,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ + CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */ CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */ CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ @@ -634,6 +638,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */ + CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */ @@ -644,6 +649,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */ CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ + CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), @@ -655,6 +661,13 @@ void __init sh7372_clock_init(void) { int k, ret = 0; + /* make sure MSTP bits on the RT/SH4AL-DSP side are off */ + __raw_writel(0xe4ef8087, RMSTPCR0); + __raw_writel(0xffffffff, RMSTPCR1); + __raw_writel(0x37c7f7ff, RMSTPCR2); + __raw_writel(0xffffffff, RMSTPCR3); + __raw_writel(0xffe0fffd, RMSTPCR4); + for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 7e58904c1c8..bcacb1e8cf8 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -266,7 +266,8 @@ enum { MSTP001, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, MSTP219, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP331, MSTP329, MSTP325, MSTP323, MSTP312, + MSTP331, MSTP329, MSTP325, MSTP323, MSTP318, + MSTP314, MSTP313, MSTP312, MSTP311, MSTP411, MSTP410, MSTP403, MSTP_NR }; @@ -295,7 +296,11 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP318] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* SY-DMAC */ + [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */ + [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ + [MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */ [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ @@ -313,6 +318,9 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), + CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]), + CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]), + CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), @@ -341,7 +349,11 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP318]), /* SY-DMAC */ + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ @@ -351,6 +363,11 @@ void __init sh73a0_clock_init(void) { int k, ret = 0; + /* Set SDHI clocks to a known state */ + __raw_writel(0x108, SD0CKCR); + __raw_writel(0x108, SD1CKCR); + __raw_writel(0x108, SD2CKCR); + /* detect main clock parent */ switch ((__raw_readl(CKSCR) >> 24) & 0x03) { case 0: diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c new file mode 100644 index 00000000000..2e44f11f592 --- /dev/null +++ b/arch/arm/mach-shmobile/cpuidle.c @@ -0,0 +1,92 @@ +/* + * CPUIdle support code for SH-Mobile ARM + * + * Copyright (C) 2011 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/pm.h> +#include <linux/cpuidle.h> +#include <linux/suspend.h> +#include <linux/module.h> +#include <linux/err.h> +#include <asm/system.h> +#include <asm/io.h> + +static void shmobile_enter_wfi(void) +{ + cpu_do_idle(); +} + +void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = { + shmobile_enter_wfi, /* regular sleep mode */ +}; + +static int shmobile_cpuidle_enter(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + ktime_t before, after; + int requested_state = state - &dev->states[0]; + + dev->last_state = &dev->states[requested_state]; + before = ktime_get(); + + local_irq_disable(); + local_fiq_disable(); + + shmobile_cpuidle_modes[requested_state](); + + local_irq_enable(); + local_fiq_enable(); + + after = ktime_get(); + return ktime_to_ns(ktime_sub(after, before)) >> 10; +} + +static struct cpuidle_device shmobile_cpuidle_dev; +static struct cpuidle_driver shmobile_cpuidle_driver = { + .name = "shmobile_cpuidle", + .owner = THIS_MODULE, +}; + +void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev); + +static int shmobile_cpuidle_init(void) +{ + struct cpuidle_device *dev = &shmobile_cpuidle_dev; + struct cpuidle_state *state; + int i; + + cpuidle_register_driver(&shmobile_cpuidle_driver); + + for (i = 0; i < CPUIDLE_STATE_MAX; i++) { + dev->states[i].name[0] = '\0'; + dev->states[i].desc[0] = '\0'; + dev->states[i].enter = shmobile_cpuidle_enter; + } + + i = CPUIDLE_DRIVER_STATE_START; + + state = &dev->states[i++]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); + strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN); + state->exit_latency = 1; + state->target_residency = 1 * 2; + state->power_usage = 3; + state->flags = 0; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + + dev->safe_state = state; + dev->state_count = i; + + if (shmobile_cpuidle_setup) + shmobile_cpuidle_setup(dev); + + cpuidle_register_device(dev); + + return 0; +} +late_initcall(shmobile_cpuidle_init); diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index d4cec6b4c7d..26079d933d9 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -24,4 +24,4 @@ .align 12 ENTRY(shmobile_secondary_vector) ldr pc, 1f -1: .long secondary_startup - PAGE_OFFSET + PHYS_OFFSET +1: .long secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 013ac0ee825..06aecb31d9c 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -8,6 +8,10 @@ struct clk; extern int clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *); extern void shmobile_handle_irq_gic(struct pt_regs *); +extern struct platform_suspend_ops shmobile_suspend_ops; +struct cpuidle_device; +extern void (*shmobile_cpuidle_modes[])(void); +extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev); extern void sh7367_init_irq(void); extern void sh7367_add_early_devices(void); @@ -30,6 +34,9 @@ extern void sh7372_add_early_devices(void); extern void sh7372_add_standard_devices(void); extern void sh7372_clock_init(void); extern void sh7372_pinmux_init(void); +extern void sh7372_pm_init(void); +extern void sh7372_cpu_suspend(void); +extern void sh7372_cpu_resume(void); extern struct clk sh7372_extal1_clk; extern struct clk sh7372_extal2_clk; diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt index 3029aba3868..9f134dfeffd 100644 --- a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt +++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt @@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C ED 0xFE400354, 0x01AD8002 LIST "SCIF0 - Serial port for earlyprintk" -EB 0xE6053098, 0x11 EB 0xE6053098, 0xe1 EW 0xE6C40000, 0x0000 EB 0xE6C40004, 0x19 -EW 0xE6C40008, 0x3000 +EW 0xE6C40008, 0x0030 diff --git a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt index 3029aba3868..9f134dfeffd 100644 --- a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt +++ b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt @@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C ED 0xFE400354, 0x01AD8002 LIST "SCIF0 - Serial port for earlyprintk" -EB 0xE6053098, 0x11 EB 0xE6053098, 0xe1 EW 0xE6C40000, 0x0000 EB 0xE6C40004, 0x19 -EW 0xE6C40008, 0x3000 +EW 0xE6C40008, 0x0030 diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 5736efcca60..df20d767017 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -435,6 +435,7 @@ enum { /* DMA slave IDs */ enum { + SHDMA_SLAVE_INVALID, SHDMA_SLAVE_SCIF0_TX, SHDMA_SLAVE_SCIF0_RX, SHDMA_SLAVE_SCIF1_TX, diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index ceb2cdc92bf..216c3d695ef 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h @@ -463,5 +463,35 @@ enum { GPIO_FN_FSIAIBT_PU, GPIO_FN_FSIAISLD_PU, }; +/* DMA slave IDs */ +enum { + SHDMA_SLAVE_INVALID, + SHDMA_SLAVE_SCIF0_TX, + SHDMA_SLAVE_SCIF0_RX, + SHDMA_SLAVE_SCIF1_TX, + SHDMA_SLAVE_SCIF1_RX, + SHDMA_SLAVE_SCIF2_TX, + SHDMA_SLAVE_SCIF2_RX, + SHDMA_SLAVE_SCIF3_TX, + SHDMA_SLAVE_SCIF3_RX, + SHDMA_SLAVE_SCIF4_TX, + SHDMA_SLAVE_SCIF4_RX, + SHDMA_SLAVE_SCIF5_TX, + SHDMA_SLAVE_SCIF5_RX, + SHDMA_SLAVE_SCIF6_TX, + SHDMA_SLAVE_SCIF6_RX, + SHDMA_SLAVE_SCIF7_TX, + SHDMA_SLAVE_SCIF7_RX, + SHDMA_SLAVE_SCIF8_TX, + SHDMA_SLAVE_SCIF8_RX, + SHDMA_SLAVE_SDHI0_TX, + SHDMA_SLAVE_SDHI0_RX, + SHDMA_SLAVE_SDHI1_TX, + SHDMA_SLAVE_SDHI1_RX, + SHDMA_SLAVE_SDHI2_TX, + SHDMA_SLAVE_SDHI2_RX, + SHDMA_SLAVE_MMCIF_TX, + SHDMA_SLAVE_MMCIF_RX, +}; #endif /* __ASM_SH73A0_H__ */ diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index 7a4960f9c1e..3b28743c77e 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c @@ -27,8 +27,6 @@ enum { UNUSED_INTCA = 0, - ENABLED, - DISABLED, /* interrupt sources INTCA */ IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A, @@ -49,14 +47,14 @@ enum { MSIOF2, MSIOF1, SCIFA4, SCIFA5, SCIFB, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, - SDHI0, - SDHI1, + SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3, + SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2, IRREM, IRDA, TPU0, TTI20, DDM, - SDHI2, + SDHI2_SDHI2I0, SDHI2_SDHI2I1, SDHI2_SDHI2I2, SDHI2_SDHI2I3, RWDT0, DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3, DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR, @@ -84,7 +82,7 @@ enum { /* interrupt groups INTCA */ DMAC1_1, DMAC1_2, DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT, - AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1 + AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1, SDHI0, SDHI1, SDHI2 }; static struct intc_vect intca_vectors[] __initdata = { @@ -125,17 +123,17 @@ static struct intc_vect intca_vectors[] __initdata = { INTC_VECT(SCIFB, 0x0d60), INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0), INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0), - INTC_VECT(SDHI0, 0x0e00), INTC_VECT(SDHI0, 0x0e20), - INTC_VECT(SDHI0, 0x0e40), INTC_VECT(SDHI0, 0x0e60), - INTC_VECT(SDHI1, 0x0e80), INTC_VECT(SDHI1, 0x0ea0), - INTC_VECT(SDHI1, 0x0ec0), + INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20), + INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60), + INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0), + INTC_VECT(SDHI1_SDHI1I2, 0x0ec0), INTC_VECT(IRREM, 0x0f60), INTC_VECT(IRDA, 0x0480), INTC_VECT(TPU0, 0x04a0), INTC_VECT(TTI20, 0x1100), INTC_VECT(DDM, 0x1140), - INTC_VECT(SDHI2, 0x1200), INTC_VECT(SDHI2, 0x1220), - INTC_VECT(SDHI2, 0x1240), INTC_VECT(SDHI2, 0x1260), + INTC_VECT(SDHI2_SDHI2I0, 0x1200), INTC_VECT(SDHI2_SDHI2I1, 0x1220), + INTC_VECT(SDHI2_SDHI2I2, 0x1240), INTC_VECT(SDHI2_SDHI2I3, 0x1260), INTC_VECT(RWDT0, 0x1280), INTC_VECT(DMAC1_1_DEI0, 0x2000), INTC_VECT(DMAC1_1_DEI1, 0x2020), INTC_VECT(DMAC1_1_DEI2, 0x2040), INTC_VECT(DMAC1_1_DEI3, 0x2060), @@ -195,6 +193,12 @@ static struct intc_group intca_groups[] __initdata = { INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1), + INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1, + SDHI0_SDHI0I2, SDHI0_SDHI0I3), + INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1, + SDHI1_SDHI1I2), + INTC_GROUP(SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1, + SDHI2_SDHI2I2, SDHI2_SDHI2I3), INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM), }; @@ -230,10 +234,10 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { { SCIFB, SCIFA5, SCIFA4, MSIOF1, 0, 0, MSIOF2, 0 } }, { 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */ - { DISABLED, ENABLED, ENABLED, ENABLED, + { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0, FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } }, { 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */ - { 0, ENABLED, ENABLED, ENABLED, + { 0, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0, TTI20, USBHSDMAC0_USHDMI, 0, 0 } }, { 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */ { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10, @@ -248,7 +252,7 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { { 0, 0, TPU0, 0, 0, 0, 0, 0 } }, { 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */ - { DISABLED, DISABLED, ENABLED, ENABLED, + { SDHI2_SDHI2I3, SDHI2_SDHI2I2, SDHI2_SDHI2I1, SDHI2_SDHI2I0, 0, CMT3, 0, RWDT0 } }, { 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */ { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0, @@ -354,14 +358,10 @@ static struct intc_mask_reg intca_ack_registers[] __initdata = { { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } }, }; -static struct intc_desc intca_desc __initdata = { - .name = "sh7372-intca", - .force_enable = ENABLED, - .force_disable = DISABLED, - .hw = INTC_HW_DESC(intca_vectors, intca_groups, - intca_mask_registers, intca_prio_registers, - intca_sense_registers, intca_ack_registers), -}; +static DECLARE_INTC_DESC_ACK(intca_desc, "sh7372-intca", + intca_vectors, intca_groups, + intca_mask_registers, intca_prio_registers, + intca_sense_registers, intca_ack_registers); enum { UNUSED_INTCS = 0, diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c new file mode 100644 index 00000000000..8e4aadf14c9 --- /dev/null +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -0,0 +1,108 @@ +/* + * sh7372 Power management support + * + * Copyright (C) 2011 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/pm.h> +#include <linux/suspend.h> +#include <linux/cpuidle.h> +#include <linux/module.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/tlbflush.h> +#include <mach/common.h> + +#define SMFRAM 0xe6a70000 +#define SYSTBCR 0xe6150024 +#define SBAR 0xe6180020 +#define APARMBAREA 0xe6f10020 + +static void sh7372_enter_core_standby(void) +{ + void __iomem *smfram = (void __iomem *)SMFRAM; + + __raw_writel(0, APARMBAREA); /* translate 4k */ + __raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */ + __raw_writel(0x10, SYSTBCR); /* enable core standby */ + + __raw_writel(0, smfram + 0x3c); /* clear page table address */ + + sh7372_cpu_suspend(); + cpu_init(); + + /* if page table address is non-NULL then we have been powered down */ + if (__raw_readl(smfram + 0x3c)) { + __raw_writel(__raw_readl(smfram + 0x40), + __va(__raw_readl(smfram + 0x3c))); + + flush_tlb_all(); + set_cr(__raw_readl(smfram + 0x38)); + } + + __raw_writel(0, SYSTBCR); /* disable core standby */ + __raw_writel(0, SBAR); /* disable reset vector translation */ +} + +#ifdef CONFIG_CPU_IDLE +static void sh7372_cpuidle_setup(struct cpuidle_device *dev) +{ + struct cpuidle_state *state; + int i = dev->state_count; + + state = &dev->states[i]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); + strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); + state->exit_latency = 10; + state->target_residency = 20 + 10; + state->power_usage = 1; /* perhaps not */ + state->flags = 0; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + shmobile_cpuidle_modes[i] = sh7372_enter_core_standby; + + dev->state_count = i + 1; +} + +static void sh7372_cpuidle_init(void) +{ + shmobile_cpuidle_setup = sh7372_cpuidle_setup; +} +#else +static void sh7372_cpuidle_init(void) {} +#endif + +#ifdef CONFIG_SUSPEND +static int sh7372_enter_suspend(suspend_state_t suspend_state) +{ + sh7372_enter_core_standby(); + return 0; +} + +static void sh7372_suspend_init(void) +{ + shmobile_suspend_ops.enter = sh7372_enter_suspend; +} +#else +static void sh7372_suspend_init(void) {} +#endif + +#define DBGREG1 0xe6100020 +#define DBGREG9 0xe6100040 + +void __init sh7372_pm_init(void) +{ + /* enable DBG hardware block to kick SYSC */ + __raw_writel(0x0000a500, DBGREG9); + __raw_writel(0x0000a501, DBGREG9); + __raw_writel(0x00000000, DBGREG1); + + sh7372_suspend_init(); + sh7372_cpuidle_init(); +} diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index ce28141662d..2c10190dbb5 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/uio_driver.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> @@ -195,6 +196,214 @@ static struct platform_device cmt10_device = { .num_resources = ARRAY_SIZE(cmt10_resources), }; +/* VPU */ +static struct uio_info vpu_platform_data = { + .name = "VPU5", + .version = "0", + .irq = intcs_evt2irq(0x980), +}; + +static struct resource vpu_resources[] = { + [0] = { + .name = "VPU", + .start = 0xfe900000, + .end = 0xfe902807, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device vpu_device = { + .name = "uio_pdrv_genirq", + .id = 0, + .dev = { + .platform_data = &vpu_platform_data, + }, + .resource = vpu_resources, + .num_resources = ARRAY_SIZE(vpu_resources), +}; + +/* VEU0 */ +static struct uio_info veu0_platform_data = { + .name = "VEU0", + .version = "0", + .irq = intcs_evt2irq(0x700), +}; + +static struct resource veu0_resources[] = { + [0] = { + .name = "VEU0", + .start = 0xfe920000, + .end = 0xfe9200b7, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu0_device = { + .name = "uio_pdrv_genirq", + .id = 1, + .dev = { + .platform_data = &veu0_platform_data, + }, + .resource = veu0_resources, + .num_resources = ARRAY_SIZE(veu0_resources), +}; + +/* VEU1 */ +static struct uio_info veu1_platform_data = { + .name = "VEU1", + .version = "0", + .irq = intcs_evt2irq(0x720), +}; + +static struct resource veu1_resources[] = { + [0] = { + .name = "VEU1", + .start = 0xfe924000, + .end = 0xfe9240b7, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu1_device = { + .name = "uio_pdrv_genirq", + .id = 2, + .dev = { + .platform_data = &veu1_platform_data, + }, + .resource = veu1_resources, + .num_resources = ARRAY_SIZE(veu1_resources), +}; + +/* VEU2 */ +static struct uio_info veu2_platform_data = { + .name = "VEU2", + .version = "0", + .irq = intcs_evt2irq(0x740), +}; + +static struct resource veu2_resources[] = { + [0] = { + .name = "VEU2", + .start = 0xfe928000, + .end = 0xfe9280b7, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu2_device = { + .name = "uio_pdrv_genirq", + .id = 3, + .dev = { + .platform_data = &veu2_platform_data, + }, + .resource = veu2_resources, + .num_resources = ARRAY_SIZE(veu2_resources), +}; + +/* VEU3 */ +static struct uio_info veu3_platform_data = { + .name = "VEU3", + .version = "0", + .irq = intcs_evt2irq(0x760), +}; + +static struct resource veu3_resources[] = { + [0] = { + .name = "VEU3", + .start = 0xfe92c000, + .end = 0xfe92c0b7, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu3_device = { + .name = "uio_pdrv_genirq", + .id = 4, + .dev = { + .platform_data = &veu3_platform_data, + }, + .resource = veu3_resources, + .num_resources = ARRAY_SIZE(veu3_resources), +}; + +/* VEU2H */ +static struct uio_info veu2h_platform_data = { + .name = "VEU2H", + .version = "0", + .irq = intcs_evt2irq(0x520), +}; + +static struct resource veu2h_resources[] = { + [0] = { + .name = "VEU2H", + .start = 0xfe93c000, + .end = 0xfe93c27b, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu2h_device = { + .name = "uio_pdrv_genirq", + .id = 5, + .dev = { + .platform_data = &veu2h_platform_data, + }, + .resource = veu2h_resources, + .num_resources = ARRAY_SIZE(veu2h_resources), +}; + +/* JPU */ +static struct uio_info jpu_platform_data = { + .name = "JPU", + .version = "0", + .irq = intcs_evt2irq(0x560), +}; + +static struct resource jpu_resources[] = { + [0] = { + .name = "JPU", + .start = 0xfe980000, + .end = 0xfe9902d3, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device jpu_device = { + .name = "uio_pdrv_genirq", + .id = 6, + .dev = { + .platform_data = &jpu_platform_data, + }, + .resource = jpu_resources, + .num_resources = ARRAY_SIZE(jpu_resources), +}; + +/* SPU1 */ +static struct uio_info spu1_platform_data = { + .name = "SPU1", + .version = "0", + .irq = evt2irq(0xfc0), +}; + +static struct resource spu1_resources[] = { + [0] = { + .name = "SPU1", + .start = 0xfe300000, + .end = 0xfe3fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device spu1_device = { + .name = "uio_pdrv_genirq", + .id = 7, + .dev = { + .platform_data = &spu1_platform_data, + }, + .resource = spu1_resources, + .num_resources = ARRAY_SIZE(spu1_resources), +}; + static struct platform_device *sh7367_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -206,10 +415,24 @@ static struct platform_device *sh7367_early_devices[] __initdata = { &cmt10_device, }; +static struct platform_device *sh7367_devices[] __initdata = { + &vpu_device, + &veu0_device, + &veu1_device, + &veu2_device, + &veu3_device, + &veu2h_device, + &jpu_device, + &spu1_device, +}; + void __init sh7367_add_standard_devices(void) { platform_add_devices(sh7367_early_devices, ARRAY_SIZE(sh7367_early_devices)); + + platform_add_devices(sh7367_devices, + ARRAY_SIZE(sh7367_devices)); } #define SYMSTPCR2 0xe6158048 diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index ff0494f3d00..cd807eea69e 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/uio_driver.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> @@ -601,6 +602,214 @@ static struct platform_device dma2_device = { }, }; +/* VPU */ +static struct uio_info vpu_platform_data = { + .name = "VPU5HG", + .version = "0", + .irq = intcs_evt2irq(0x980), +}; + +static struct resource vpu_resources[] = { + [0] = { + .name = "VPU", + .start = 0xfe900000, + .end = 0xfe900157, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device vpu_device = { + .name = "uio_pdrv_genirq", + .id = 0, + .dev = { + .platform_data = &vpu_platform_data, + }, + .resource = vpu_resources, + .num_resources = ARRAY_SIZE(vpu_resources), +}; + +/* VEU0 */ +static struct uio_info veu0_platform_data = { + .name = "VEU0", + .version = "0", + .irq = intcs_evt2irq(0x700), +}; + +static struct resource veu0_resources[] = { + [0] = { + .name = "VEU0", + .start = 0xfe920000, + .end = 0xfe9200cb, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu0_device = { + .name = "uio_pdrv_genirq", + .id = 1, + .dev = { + .platform_data = &veu0_platform_data, + }, + .resource = veu0_resources, + .num_resources = ARRAY_SIZE(veu0_resources), +}; + +/* VEU1 */ +static struct uio_info veu1_platform_data = { + .name = "VEU1", + .version = "0", + .irq = intcs_evt2irq(0x720), +}; + +static struct resource veu1_resources[] = { + [0] = { + .name = "VEU1", + .start = 0xfe924000, + .end = 0xfe9240cb, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu1_device = { + .name = "uio_pdrv_genirq", + .id = 2, + .dev = { + .platform_data = &veu1_platform_data, + }, + .resource = veu1_resources, + .num_resources = ARRAY_SIZE(veu1_resources), +}; + +/* VEU2 */ +static struct uio_info veu2_platform_data = { + .name = "VEU2", + .version = "0", + .irq = intcs_evt2irq(0x740), +}; + +static struct resource veu2_resources[] = { + [0] = { + .name = "VEU2", + .start = 0xfe928000, + .end = 0xfe928307, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu2_device = { + .name = "uio_pdrv_genirq", + .id = 3, + .dev = { + .platform_data = &veu2_platform_data, + }, + .resource = veu2_resources, + .num_resources = ARRAY_SIZE(veu2_resources), +}; + +/* VEU3 */ +static struct uio_info veu3_platform_data = { + .name = "VEU3", + .version = "0", + .irq = intcs_evt2irq(0x760), +}; + +static struct resource veu3_resources[] = { + [0] = { + .name = "VEU3", + .start = 0xfe92c000, + .end = 0xfe92c307, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu3_device = { + .name = "uio_pdrv_genirq", + .id = 4, + .dev = { + .platform_data = &veu3_platform_data, + }, + .resource = veu3_resources, + .num_resources = ARRAY_SIZE(veu3_resources), +}; + +/* JPU */ +static struct uio_info jpu_platform_data = { + .name = "JPU", + .version = "0", + .irq = intcs_evt2irq(0x560), +}; + +static struct resource jpu_resources[] = { + [0] = { + .name = "JPU", + .start = 0xfe980000, + .end = 0xfe9902d3, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device jpu_device = { + .name = "uio_pdrv_genirq", + .id = 5, + .dev = { + .platform_data = &jpu_platform_data, + }, + .resource = jpu_resources, + .num_resources = ARRAY_SIZE(jpu_resources), +}; + +/* SPU2DSP0 */ +static struct uio_info spu0_platform_data = { + .name = "SPU2DSP0", + .version = "0", + .irq = evt2irq(0x1800), +}; + +static struct resource spu0_resources[] = { + [0] = { + .name = "SPU2DSP0", + .start = 0xfe200000, + .end = 0xfe2fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device spu0_device = { + .name = "uio_pdrv_genirq", + .id = 6, + .dev = { + .platform_data = &spu0_platform_data, + }, + .resource = spu0_resources, + .num_resources = ARRAY_SIZE(spu0_resources), +}; + +/* SPU2DSP1 */ +static struct uio_info spu1_platform_data = { + .name = "SPU2DSP1", + .version = "0", + .irq = evt2irq(0x1820), +}; + +static struct resource spu1_resources[] = { + [0] = { + .name = "SPU2DSP1", + .start = 0xfe300000, + .end = 0xfe3fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device spu1_device = { + .name = "uio_pdrv_genirq", + .id = 7, + .dev = { + .platform_data = &spu1_platform_data, + }, + .resource = spu1_resources, + .num_resources = ARRAY_SIZE(spu1_resources), +}; + static struct platform_device *sh7372_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -620,6 +829,14 @@ static struct platform_device *sh7372_late_devices[] __initdata = { &dma0_device, &dma1_device, &dma2_device, + &vpu_device, + &veu0_device, + &veu1_device, + &veu2_device, + &veu3_device, + &jpu_device, + &spu0_device, + &spu1_device, }; void __init sh7372_add_standard_devices(void) diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c index 8099b0b8a93..bb405b8e459 100644 --- a/arch/arm/mach-shmobile/setup-sh7377.c +++ b/arch/arm/mach-shmobile/setup-sh7377.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/uio_driver.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> @@ -38,7 +39,7 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00) }, }; @@ -57,7 +58,7 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20) }, }; @@ -76,7 +77,7 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40) }, }; @@ -95,7 +96,7 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60) }, }; @@ -114,7 +115,7 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20) }, }; @@ -133,7 +134,7 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40) }, }; @@ -152,7 +153,7 @@ static struct plat_sci_port scif6_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) }, }; @@ -171,7 +172,7 @@ static struct plat_sci_port scif7_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFB, .irqs = { evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60) }, }; @@ -215,6 +216,214 @@ static struct platform_device cmt10_device = { .num_resources = ARRAY_SIZE(cmt10_resources), }; +/* VPU */ +static struct uio_info vpu_platform_data = { + .name = "VPU5HG", + .version = "0", + .irq = intcs_evt2irq(0x980), +}; + +static struct resource vpu_resources[] = { + [0] = { + .name = "VPU", + .start = 0xfe900000, + .end = 0xfe900157, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device vpu_device = { + .name = "uio_pdrv_genirq", + .id = 0, + .dev = { + .platform_data = &vpu_platform_data, + }, + .resource = vpu_resources, + .num_resources = ARRAY_SIZE(vpu_resources), +}; + +/* VEU0 */ +static struct uio_info veu0_platform_data = { + .name = "VEU0", + .version = "0", + .irq = intcs_evt2irq(0x700), +}; + +static struct resource veu0_resources[] = { + [0] = { + .name = "VEU0", + .start = 0xfe920000, + .end = 0xfe9200cb, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu0_device = { + .name = "uio_pdrv_genirq", + .id = 1, + .dev = { + .platform_data = &veu0_platform_data, + }, + .resource = veu0_resources, + .num_resources = ARRAY_SIZE(veu0_resources), +}; + +/* VEU1 */ +static struct uio_info veu1_platform_data = { + .name = "VEU1", + .version = "0", + .irq = intcs_evt2irq(0x720), +}; + +static struct resource veu1_resources[] = { + [0] = { + .name = "VEU1", + .start = 0xfe924000, + .end = 0xfe9240cb, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu1_device = { + .name = "uio_pdrv_genirq", + .id = 2, + .dev = { + .platform_data = &veu1_platform_data, + }, + .resource = veu1_resources, + .num_resources = ARRAY_SIZE(veu1_resources), +}; + +/* VEU2 */ +static struct uio_info veu2_platform_data = { + .name = "VEU2", + .version = "0", + .irq = intcs_evt2irq(0x740), +}; + +static struct resource veu2_resources[] = { + [0] = { + .name = "VEU2", + .start = 0xfe928000, + .end = 0xfe928307, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu2_device = { + .name = "uio_pdrv_genirq", + .id = 3, + .dev = { + .platform_data = &veu2_platform_data, + }, + .resource = veu2_resources, + .num_resources = ARRAY_SIZE(veu2_resources), +}; + +/* VEU3 */ +static struct uio_info veu3_platform_data = { + .name = "VEU3", + .version = "0", + .irq = intcs_evt2irq(0x760), +}; + +static struct resource veu3_resources[] = { + [0] = { + .name = "VEU3", + .start = 0xfe92c000, + .end = 0xfe92c307, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device veu3_device = { + .name = "uio_pdrv_genirq", + .id = 4, + .dev = { + .platform_data = &veu3_platform_data, + }, + .resource = veu3_resources, + .num_resources = ARRAY_SIZE(veu3_resources), +}; + +/* JPU */ +static struct uio_info jpu_platform_data = { + .name = "JPU", + .version = "0", + .irq = intcs_evt2irq(0x560), +}; + +static struct resource jpu_resources[] = { + [0] = { + .name = "JPU", + .start = 0xfe980000, + .end = 0xfe9902d3, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device jpu_device = { + .name = "uio_pdrv_genirq", + .id = 5, + .dev = { + .platform_data = &jpu_platform_data, + }, + .resource = jpu_resources, + .num_resources = ARRAY_SIZE(jpu_resources), +}; + +/* SPU2DSP0 */ +static struct uio_info spu0_platform_data = { + .name = "SPU2DSP0", + .version = "0", + .irq = evt2irq(0x1800), +}; + +static struct resource spu0_resources[] = { + [0] = { + .name = "SPU2DSP0", + .start = 0xfe200000, + .end = 0xfe2fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device spu0_device = { + .name = "uio_pdrv_genirq", + .id = 6, + .dev = { + .platform_data = &spu0_platform_data, + }, + .resource = spu0_resources, + .num_resources = ARRAY_SIZE(spu0_resources), +}; + +/* SPU2DSP1 */ +static struct uio_info spu1_platform_data = { + .name = "SPU2DSP1", + .version = "0", + .irq = evt2irq(0x1820), +}; + +static struct resource spu1_resources[] = { + [0] = { + .name = "SPU2DSP1", + .start = 0xfe300000, + .end = 0xfe3fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device spu1_device = { + .name = "uio_pdrv_genirq", + .id = 7, + .dev = { + .platform_data = &spu1_platform_data, + }, + .resource = spu1_resources, + .num_resources = ARRAY_SIZE(spu1_resources), +}; + static struct platform_device *sh7377_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -227,10 +436,24 @@ static struct platform_device *sh7377_early_devices[] __initdata = { &cmt10_device, }; +static struct platform_device *sh7377_devices[] __initdata = { + &vpu_device, + &veu0_device, + &veu1_device, + &veu2_device, + &veu3_device, + &jpu_device, + &spu0_device, + &spu1_device, +}; + void __init sh7377_add_standard_devices(void) { platform_add_devices(sh7377_early_devices, ARRAY_SIZE(sh7377_early_devices)); + + platform_add_devices(sh7377_devices, + ARRAY_SIZE(sh7377_devices)); } #define SMSTPCR3 0xe615013c diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 685c40a2f5e..e46821c0a62 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -27,9 +27,11 @@ #include <linux/input.h> #include <linux/io.h> #include <linux/serial_sci.h> +#include <linux/sh_dma.h> #include <linux/sh_intc.h> #include <linux/sh_timer.h> #include <mach/hardware.h> +#include <mach/sh73a0.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -392,6 +394,242 @@ static struct platform_device i2c4_device = { .num_resources = ARRAY_SIZE(i2c4_resources), }; +/* Transmit sizes and respective CHCR register values */ +enum { + XMIT_SZ_8BIT = 0, + XMIT_SZ_16BIT = 1, + XMIT_SZ_32BIT = 2, + XMIT_SZ_64BIT = 7, + XMIT_SZ_128BIT = 3, + XMIT_SZ_256BIT = 4, + XMIT_SZ_512BIT = 5, +}; + +/* log2(size / 8) - used to calculate number of transfers */ +#define TS_SHIFT { \ + [XMIT_SZ_8BIT] = 0, \ + [XMIT_SZ_16BIT] = 1, \ + [XMIT_SZ_32BIT] = 2, \ + [XMIT_SZ_64BIT] = 3, \ + [XMIT_SZ_128BIT] = 4, \ + [XMIT_SZ_256BIT] = 5, \ + [XMIT_SZ_512BIT] = 6, \ +} + +#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | (((i) & 0xc) << (20 - 2))) +#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) +#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) + +static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SCIF0_TX, + .addr = 0xe6c40020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x21, + }, { + .slave_id = SHDMA_SLAVE_SCIF0_RX, + .addr = 0xe6c40024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x22, + }, { + .slave_id = SHDMA_SLAVE_SCIF1_TX, + .addr = 0xe6c50020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x25, + }, { + .slave_id = SHDMA_SLAVE_SCIF1_RX, + .addr = 0xe6c50024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x26, + }, { + .slave_id = SHDMA_SLAVE_SCIF2_TX, + .addr = 0xe6c60020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x29, + }, { + .slave_id = SHDMA_SLAVE_SCIF2_RX, + .addr = 0xe6c60024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x2a, + }, { + .slave_id = SHDMA_SLAVE_SCIF3_TX, + .addr = 0xe6c70020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x2d, + }, { + .slave_id = SHDMA_SLAVE_SCIF3_RX, + .addr = 0xe6c70024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x2e, + }, { + .slave_id = SHDMA_SLAVE_SCIF4_TX, + .addr = 0xe6c80020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x39, + }, { + .slave_id = SHDMA_SLAVE_SCIF4_RX, + .addr = 0xe6c80024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x3a, + }, { + .slave_id = SHDMA_SLAVE_SCIF5_TX, + .addr = 0xe6cb0020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x35, + }, { + .slave_id = SHDMA_SLAVE_SCIF5_RX, + .addr = 0xe6cb0024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x36, + }, { + .slave_id = SHDMA_SLAVE_SCIF6_TX, + .addr = 0xe6cc0020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x1d, + }, { + .slave_id = SHDMA_SLAVE_SCIF6_RX, + .addr = 0xe6cc0024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x1e, + }, { + .slave_id = SHDMA_SLAVE_SCIF7_TX, + .addr = 0xe6cd0020, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x19, + }, { + .slave_id = SHDMA_SLAVE_SCIF7_RX, + .addr = 0xe6cd0024, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x1a, + }, { + .slave_id = SHDMA_SLAVE_SCIF8_TX, + .addr = 0xe6c30040, + .chcr = CHCR_TX(XMIT_SZ_8BIT), + .mid_rid = 0x3d, + }, { + .slave_id = SHDMA_SLAVE_SCIF8_RX, + .addr = 0xe6c30060, + .chcr = CHCR_RX(XMIT_SZ_8BIT), + .mid_rid = 0x3e, + }, { + .slave_id = SHDMA_SLAVE_SDHI0_TX, + .addr = 0xee100030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xc1, + }, { + .slave_id = SHDMA_SLAVE_SDHI0_RX, + .addr = 0xee100030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xc2, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_TX, + .addr = 0xee120030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xc9, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_RX, + .addr = 0xee120030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xca, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_TX, + .addr = 0xee140030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xcd, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_RX, + .addr = 0xee140030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xce, + }, { + .slave_id = SHDMA_SLAVE_MMCIF_TX, + .addr = 0xe6bd0034, + .chcr = CHCR_TX(XMIT_SZ_32BIT), + .mid_rid = 0xd1, + }, { + .slave_id = SHDMA_SLAVE_MMCIF_RX, + .addr = 0xe6bd0034, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0xd2, + }, +}; + +#define DMAE_CHANNEL(_offset) \ + { \ + .offset = _offset - 0x20, \ + .dmars = _offset - 0x20 + 0x40, \ + } + +static const struct sh_dmae_channel sh73a0_dmae_channels[] = { + DMAE_CHANNEL(0x8000), + DMAE_CHANNEL(0x8080), + DMAE_CHANNEL(0x8100), + DMAE_CHANNEL(0x8180), + DMAE_CHANNEL(0x8200), + DMAE_CHANNEL(0x8280), + DMAE_CHANNEL(0x8300), + DMAE_CHANNEL(0x8380), + DMAE_CHANNEL(0x8400), + DMAE_CHANNEL(0x8480), + DMAE_CHANNEL(0x8500), + DMAE_CHANNEL(0x8580), + DMAE_CHANNEL(0x8600), + DMAE_CHANNEL(0x8680), + DMAE_CHANNEL(0x8700), + DMAE_CHANNEL(0x8780), + DMAE_CHANNEL(0x8800), + DMAE_CHANNEL(0x8880), + DMAE_CHANNEL(0x8900), + DMAE_CHANNEL(0x8980), +}; + +static const unsigned int ts_shift[] = TS_SHIFT; + +static struct sh_dmae_pdata sh73a0_dmae_platform_data = { + .slave = sh73a0_dmae_slaves, + .slave_num = ARRAY_SIZE(sh73a0_dmae_slaves), + .channel = sh73a0_dmae_channels, + .channel_num = ARRAY_SIZE(sh73a0_dmae_channels), + .ts_low_shift = 3, + .ts_low_mask = 0x18, + .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */ + .ts_high_mask = 0x00300000, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_DME, +}; + +static struct resource sh73a0_dmae_resources[] = { + { + /* Registers including DMAOR and channels including DMARSx */ + .start = 0xfe000020, + .end = 0xfe008a00 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error IRQ */ + .start = gic_spi(129), + .end = gic_spi(129), + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-19 */ + .start = gic_spi(109), + .end = gic_spi(128), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dma0_device = { + .name = "sh-dma-engine", + .id = 0, + .resource = sh73a0_dmae_resources, + .num_resources = ARRAY_SIZE(sh73a0_dmae_resources), + .dev = { + .platform_data = &sh73a0_dmae_platform_data, + }, +}; + static struct platform_device *sh73a0_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -413,10 +651,16 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { &i2c2_device, &i2c3_device, &i2c4_device, + &dma0_device, }; +#define SRCR2 0xe61580b0 + void __init sh73a0_add_standard_devices(void) { + /* Clear software reset bit on SY-DMAC module */ + __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); + platform_add_devices(sh73a0_early_devices, ARRAY_SIZE(sh73a0_early_devices)); platform_add_devices(sh73a0_late_devices, diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S new file mode 100644 index 00000000000..d37d3ca4d18 --- /dev/null +++ b/arch/arm/mach-shmobile/sleep-sh7372.S @@ -0,0 +1,260 @@ +/* + * sh7372 lowlevel sleep code for "Core Standby Mode" + * + * Copyright (C) 2011 Magnus Damm + * + * In "Core Standby Mode" the ARM core is off, but L2 cache is still on + * + * Based on mach-omap2/sleep34xx.S + * + * (C) Copyright 2007 Texas Instruments + * Karthik Dasu <karthik-dp@ti.com> + * + * (C) Copyright 2004 Texas Instruments, <www.ti.com> + * Richard Woodruff <r-woodruff2@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#define SMFRAM 0xe6a70000 + + .align +kernel_flush: + .word v7_flush_dcache_all + + .align 3 +ENTRY(sh7372_cpu_suspend) + stmfd sp!, {r0-r12, lr} @ save registers on stack + + ldr r8, =SMFRAM + + mov r4, sp @ Store sp + mrs r5, spsr @ Store spsr + mov r6, lr @ Store lr + stmia r8!, {r4-r6} + + mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register + mrc p15, 0, r5, c2, c0, 0 @ TTBR0 + mrc p15, 0, r6, c2, c0, 1 @ TTBR1 + mrc p15, 0, r7, c2, c0, 2 @ TTBCR + stmia r8!, {r4-r7} + + mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register + mrc p15, 0, r5, c10, c2, 0 @ PRRR + mrc p15, 0, r6, c10, c2, 1 @ NMRR + stmia r8!,{r4-r6} + + mrc p15, 0, r4, c13, c0, 1 @ Context ID + mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address + mrs r7, cpsr @ Store current cpsr + stmia r8!, {r4-r7} + + mrc p15, 0, r4, c1, c0, 0 @ save control register + stmia r8!, {r4} + + /* + * jump out to kernel flush routine + * - reuse that code is better + * - it executes in a cached space so is faster than refetch per-block + * - should be faster and will change with kernel + * - 'might' have to copy address, load and jump to it + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. + */ + ldr r1, kernel_flush + mov lr, pc + bx r1 + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 data cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + ldr r1, kernel_flush + blx r1 + /* + * The kernel doesn't interwork: v7_flush_dcache_all in particluar will + * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled. + * This sequence switches back to ARM. Note that .align may insert a + * nop: bx pc needs to be word-aligned in order to work. + */ + THUMB( .thumb ) + THUMB( .align ) + THUMB( bx pc ) + THUMB( nop ) + .arm + + /* Data memory barrier and Data sync barrier */ + dsb + dmb + +/* + * =================================== + * == WFI instruction => Enter idle == + * =================================== + */ + wfi @ wait for interrupt + +/* + * =================================== + * == Resume path for non-OFF modes == + * =================================== + */ + mrc p15, 0, r0, c1, c0, 0 + tst r0, #(1 << 2) @ Check C bit enabled? + orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared + mcreq p15, 0, r0, c1, c0, 0 + isb + +/* + * =================================== + * == Exit point from non-OFF modes == + * =================================== + */ + ldmfd sp!, {r0-r12, pc} @ restore regs and return + + .pool + + .align 12 + .text + .global sh7372_cpu_resume +sh7372_cpu_resume: + + mov r1, #0 + /* + * Invalidate all instruction caches to PoU + * and flush branch target cache + */ + mcr p15, 0, r1, c7, c5, 0 + + ldr r3, =SMFRAM + + ldmia r3!, {r4-r6} + mov sp, r4 @ Restore sp + msr spsr_cxsf, r5 @ Restore spsr + mov lr, r6 @ Restore lr + + ldmia r3!, {r4-r7} + mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register + mcr p15, 0, r5, c2, c0, 0 @ TTBR0 + mcr p15, 0, r6, c2, c0, 1 @ TTBR1 + mcr p15, 0, r7, c2, c0, 2 @ TTBCR + + ldmia r3!,{r4-r6} + mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register + mcr p15, 0, r5, c10, c2, 0 @ PRRR + mcr p15, 0, r6, c10, c2, 1 @ NMRR + + ldmia r3!,{r4-r7} + mcr p15, 0, r4, c13, c0, 1 @ Context ID + mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address + msr cpsr, r7 @ store cpsr + + /* Starting to enable MMU here */ + mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl + /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */ + and r7, #0x7 + cmp r7, #0x0 + beq usettbr0 +ttbr_error: + /* + * More work needs to be done to support N[0:2] value other than 0 + * So looping here so that the error can be detected + */ + b ttbr_error + + .align +cache_pred_disable_mask: + .word 0xFFFFE7FB +ttbrbit_mask: + .word 0xFFFFC000 +table_index_mask: + .word 0xFFF00000 +table_entry: + .word 0x00000C02 +usettbr0: + + mrc p15, 0, r2, c2, c0, 0 + ldr r5, ttbrbit_mask + and r2, r5 + mov r4, pc + ldr r5, table_index_mask + and r4, r5 @ r4 = 31 to 20 bits of pc + /* Extract the value to be written to table entry */ + ldr r6, table_entry + /* r6 has the value to be written to table entry */ + add r6, r6, r4 + /* Getting the address of table entry to modify */ + lsr r4, #18 + /* r2 has the location which needs to be modified */ + add r2, r4 + ldr r4, [r2] + str r6, [r2] /* modify the table entry */ + + mov r7, r6 + mov r5, r2 + mov r6, r4 + /* r5 = original page table address */ + /* r6 = original page table data */ + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array + mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB + mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB + + /* + * Restore control register. This enables the MMU. + * The caches and prediction are not enabled here, they + * will be enabled after restoring the MMU table entry. + */ + ldmia r3!, {r4} + stmia r3!, {r5} /* save original page table address */ + stmia r3!, {r6} /* save original page table data */ + stmia r3!, {r7} /* save modified page table data */ + + ldr r2, cache_pred_disable_mask + and r4, r2 + mcr p15, 0, r4, c1, c0, 0 + dsb + isb + + ldr r0, =restoremmu_on + bx r0 + +/* + * ============================== + * == Exit point from OFF mode == + * ============================== + */ +restoremmu_on: + + ldmfd sp!, {r0-r12, pc} @ restore regs and return diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index a156d2108df..3ffdbc92ba8 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -59,6 +59,11 @@ unsigned int __init sh73a0_get_core_count(void) { void __iomem *scu_base = scu_base_addr(); +#ifdef CONFIG_HAVE_ARM_TWD + /* twd_base needs to be initialized before percpu_timer_setup() */ + twd_base = (void __iomem *)0xf0000600; +#endif + return scu_get_core_count(scu_base); } @@ -82,10 +87,6 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) void __init sh73a0_smp_prepare_cpus(void) { -#ifdef CONFIG_HAVE_ARM_TWD - twd_base = (void __iomem *)0xf0000600; -#endif - scu_enable(scu_base_addr()); /* Map the reset vector (in headsmp.S) */ diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c new file mode 100644 index 00000000000..c1febe13f70 --- /dev/null +++ b/arch/arm/mach-shmobile/suspend.c @@ -0,0 +1,47 @@ +/* + * Suspend-to-RAM support code for SH-Mobile ARM + * + * Copyright (C) 2011 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/pm.h> +#include <linux/suspend.h> +#include <linux/module.h> +#include <linux/err.h> +#include <asm/system.h> +#include <asm/io.h> + +static int shmobile_suspend_default_enter(suspend_state_t suspend_state) +{ + cpu_do_idle(); + return 0; +} + +static int shmobile_suspend_begin(suspend_state_t state) +{ + disable_hlt(); + return 0; +} + +static void shmobile_suspend_end(void) +{ + enable_hlt(); +} + +struct platform_suspend_ops shmobile_suspend_ops = { + .begin = shmobile_suspend_begin, + .end = shmobile_suspend_end, + .enter = shmobile_suspend_default_enter, + .valid = suspend_valid_only_mem, +}; + +static int __init shmobile_suspend_init(void) +{ + suspend_set_ops(&shmobile_suspend_ops); + return 0; +} +late_initcall(shmobile_suspend_init); diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 58626013aa3..54429d01595 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -12,9 +12,12 @@ menu "Ux500 SoC" config UX500_SOC_DB5500 bool "DB5500" + select MFD_DB5500_PRCMU config UX500_SOC_DB8500 bool "DB8500" + select MFD_DB8500_PRCMU + select REGULATOR_DB8500_PRCMU endmenu diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index b549a8fb423..1694916e682 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -5,7 +5,7 @@ obj-y := clock.o cpu.o devices.o devices-common.o \ id.o usb.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o -obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o +obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ @@ -17,4 +17,4 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o -obj-$(CONFIG_CPU_FREQ) += cpufreq.o + diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index c9dc2eff3cb..c01bc19e3c5 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -188,6 +188,8 @@ void __init u5500_map_io(void) ux500_map_io(); iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); + + _PRCMU_BASE = __io_address(U5500_PRCMU_BASE); } static int usb_db5500_rx_dma_cfg[] = { diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 516126cb357..c3c417656bd 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -87,6 +87,8 @@ void __init u8500_map_io(void) iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); else if (cpu_is_u8500v2()) iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); + + _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); } static struct resource db8500_pmu_resources[] = { @@ -129,9 +131,14 @@ static struct platform_device db8500_pmu_device = { .dev.platform_data = &db8500_pmu_platdata, }; +static struct platform_device db8500_prcmu_device = { + .name = "db8500-prcmu", +}; + static struct platform_device *platform_devs[] __initdata = { &u8500_dma40_device, &db8500_pmu_device, + &db8500_prcmu_device, }; static resource_size_t __initdata db8500_gpio_base[] = { diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 5a43107c623..1da23bb87c1 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -8,6 +8,8 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/mfd/db8500-prcmu.h> +#include <linux/mfd/db5500-prcmu.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> @@ -19,10 +21,11 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> -#include <mach/prcmu.h> #include "clock.h" +void __iomem *_PRCMU_BASE; + #ifdef CONFIG_CACHE_L2X0 static void __iomem *l2x0_base; #endif @@ -47,6 +50,8 @@ void __init ux500_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ + if (cpu_is_u5500()) + db5500_prcmu_early_init(); if (cpu_is_u8500()) prcmu_early_init(); clk_init(); diff --git a/arch/arm/mach-ux500/cpufreq.c b/arch/arm/mach-ux500/cpufreq.c deleted file mode 100644 index 5c5b747f134..00000000000 --- a/arch/arm/mach-ux500/cpufreq.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * CPU frequency scaling for u8500 - * Inspired by linux/arch/arm/mach-davinci/cpufreq.c - * - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * Author: Martin Persson <martin.persson@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - * - */ - -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/cpufreq.h> -#include <linux/delay.h> - -#include <mach/hardware.h> -#include <mach/prcmu.h> -#include <mach/prcmu-defs.h> - -#define DRIVER_NAME "cpufreq-u8500" -#define CPUFREQ_NAME "u8500" - -static struct device *dev; - -static struct cpufreq_frequency_table freq_table[] = { - [0] = { - .index = 0, - .frequency = 200000, - }, - [1] = { - .index = 1, - .frequency = 300000, - }, - [2] = { - .index = 2, - .frequency = 600000, - }, - [3] = { - /* Used for CPU_OPP_MAX, if available */ - .index = 3, - .frequency = CPUFREQ_TABLE_END, - }, - [4] = { - .index = 4, - .frequency = CPUFREQ_TABLE_END, - }, -}; - -static enum prcmu_cpu_opp index2opp[] = { - CPU_OPP_EXT_CLK, - CPU_OPP_50, - CPU_OPP_100, - CPU_OPP_MAX -}; - -static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - -static int u8500_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - struct cpufreq_freqs freqs; - unsigned int index; - int ret = 0; - - /* - * Ensure desired rate is within allowed range. Some govenors - * (ondemand) will just pass target_freq=0 to get the minimum. - */ - if (target_freq < policy->cpuinfo.min_freq) - target_freq = policy->cpuinfo.min_freq; - if (target_freq > policy->cpuinfo.max_freq) - target_freq = policy->cpuinfo.max_freq; - - ret = cpufreq_frequency_table_target(policy, freq_table, - target_freq, relation, &index); - if (ret < 0) { - dev_err(dev, "Could not look up next frequency\n"); - return ret; - } - - freqs.old = policy->cur; - freqs.new = freq_table[index].frequency; - freqs.cpu = policy->cpu; - - if (freqs.old == freqs.new) { - dev_dbg(dev, "Current and target frequencies are equal\n"); - return 0; - } - - dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new); - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - ret = prcmu_set_cpu_opp(index2opp[index]); - if (ret < 0) { - dev_err(dev, "Failed to set OPP level\n"); - return ret; - } - - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return ret; -} - -static unsigned int u8500_cpufreq_getspeed(unsigned int cpu) -{ - int i; - - for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++) - ; - return freq_table[i].frequency; -} - -static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy) -{ - int res; - - BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table)); - - if (cpu_is_u8500v2()) { - freq_table[1].frequency = 400000; - freq_table[2].frequency = 800000; - if (prcmu_has_arm_maxopp()) - freq_table[3].frequency = 1000000; - } - - /* get policy fields based on the table */ - res = cpufreq_frequency_table_cpuinfo(policy, freq_table); - if (!res) - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - else { - dev_err(dev, "u8500-cpufreq : Failed to read policy table\n"); - return res; - } - - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; - policy->cur = u8500_cpufreq_getspeed(policy->cpu); - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - - /* - * FIXME : Need to take time measurement across the target() - * function with no/some/all drivers in the notification - * list. - */ - policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */ - - /* policy sharing between dual CPUs */ - cpumask_copy(policy->cpus, &cpu_present_map); - - policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; - - return res; -} - -static struct freq_attr *u8500_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; -static int u8500_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct cpufreq_driver u8500_driver = { - .owner = THIS_MODULE, - .flags = CPUFREQ_STICKY, - .verify = u8500_cpufreq_verify_speed, - .target = u8500_cpufreq_target, - .get = u8500_cpufreq_getspeed, - .init = u8500_cpu_init, - .exit = u8500_cpu_exit, - .name = CPUFREQ_NAME, - .attr = u8500_cpufreq_attr, -}; - -static int __init u8500_cpufreq_probe(struct platform_device *pdev) -{ - dev = &pdev->dev; - return cpufreq_register_driver(&u8500_driver); -} - -static int __exit u8500_cpufreq_remove(struct platform_device *pdev) -{ - return cpufreq_unregister_driver(&u8500_driver); -} - -static struct platform_driver u8500_cpufreq_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .remove = __exit_p(u8500_cpufreq_remove), -}; - -static int __init u8500_cpufreq_init(void) -{ - return platform_driver_probe(&u8500_cpufreq_driver, - &u8500_cpufreq_probe); -} - -device_initcall(u8500_cpufreq_init); diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index bd88c1e7406..6ad98329410 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -17,6 +17,8 @@ #define U5500_GIC_DIST_BASE 0xA0411000 #define U5500_GIC_CPU_BASE 0xA0410100 #define U5500_DMA_BASE 0x90030000 +#define U5500_STM_BASE 0x90020000 +#define U5500_STM_REG_BASE (U5500_STM_BASE + 0xF000) #define U5500_MCDE_BASE 0xA0400000 #define U5500_MODEM_BASE 0xB0000000 #define U5500_L2CC_BASE 0xA0412000 @@ -29,7 +31,9 @@ #define U5500_NAND0_BASE 0x60000000 #define U5500_NAND1_BASE 0x70000000 #define U5500_TWD_BASE 0xa0410600 +#define U5500_ICN_BASE 0xA0040000 #define U5500_B2R2_BASE 0xa0200000 +#define U5500_BOOT_ROM_BASE 0x90000000 #define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000) #define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000) @@ -60,6 +64,7 @@ #define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000) #define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000) #define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000) +#define U5500_PRCMU_TCDM_BASE (U5500_PER4_BASE + 0x18000) #define U5500_SPI0_BASE (U5500_PER5_BASE + 0x0000) #define U5500_SPI1_BASE (U5500_PER5_BASE + 0x1000) @@ -83,7 +88,7 @@ #define U5500_HASH0_BASE (U5500_PER6_BASE + 0x1000) #define U5500_HASH1_BASE (U5500_PER6_BASE + 0x2000) #define U5500_PKA_BASE (U5500_PER6_BASE + 0x4000) -#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5000) +#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5100) #define U5500_MTU0_BASE (U5500_PER6_BASE + 0x6000) #define U5500_MTU1_BASE (U5500_PER6_BASE + 0x7000) #define U5500_CR_BASE (U5500_PER6_BASE + 0x8000) @@ -114,8 +119,19 @@ #define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) #define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) -#define U5500_ESRAM_BASE 0x40000000 +#define U5500_ACCCON_BASE_SEC (0xBFFF0000) +#define U5500_ACCCON_BASE (0xBFFF1000) +#define U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET (0x00000020) +#define U5500_ACCCON_ACC_CPU_CTRL_OFFSET (0x000000BC) + +#define U5500_ESRAM_BASE 0x40000000 #define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000 #define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET) +#define U5500_MCDE_SIZE 0x1000 +#define U5500_DSI_LINK_SIZE 0x1000 +#define U5500_DSI_LINK_COUNT 0x2 +#define U5500_DSI_LINK1_BASE (U5500_MCDE_BASE + U5500_MCDE_SIZE) +#define U5500_DSI_LINK2_BASE (U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE) + #endif diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 16647b25537..049997109cf 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -15,8 +15,13 @@ #define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE) #define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE) #define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE) -/* Use bank 4 for DMA LCPA */ -#define U8500_DMA_LCPA_BASE U8500_ESRAM_BANK4 +/* + * on V1 DMA uses 4KB for logical parameters position is right after the 64KB + * reserved for security + */ +#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000 + +#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET) #define U8500_DMA_LCPA_BASE_ED (U8500_ESRAM_BANK4 + 0x4000) #define U8500_PER3_BASE 0x80000000 @@ -27,9 +32,12 @@ #define U8500_B2R2_BASE 0x80130000 #define U8500_HSEM_BASE 0x80140000 #define U8500_PER4_BASE 0x80150000 +#define U8500_TPIU_BASE 0x80190000 #define U8500_ICN_BASE 0x81000000 #define U8500_BOOT_ROM_BASE 0x90000000 +/* ASIC ID is at 0xbf4 offset within this region */ +#define U8500_ASIC_ID_BASE 0x9001D000 #define U8500_PER6_BASE 0xa03c0000 #define U8500_PER5_BASE 0xa03e0000 @@ -70,13 +78,15 @@ /* per6 base addresses */ #define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000) -#define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000) -#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000) +#define U8500_HASH0_BASE (U8500_PER6_BASE + 0x1000) +#define U8500_HASH1_BASE (U8500_PER6_BASE + 0x2000) +#define U8500_PKA_BASE (U8500_PER6_BASE + 0x4000) +#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x5100) #define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */ #define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */ #define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */ -#define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000) -#define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000) +#define U8500_CRYP0_BASE (U8500_PER6_BASE + 0xa000) +#define U8500_CRYP1_BASE (U8500_PER6_BASE + 0xb000) #define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000) /* per5 base addresses */ @@ -93,7 +103,8 @@ #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000) -#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) +#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) +#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) /* per3 base addresses */ #define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) @@ -124,6 +135,7 @@ #define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000) #define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000) #define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000) +#define U8500_MSP3_BASE (U8500_PER1_BASE + 0x5000) #define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000) #define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000) #define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000) @@ -143,4 +155,15 @@ #define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80) #define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE +#define U8500_MCDE_SIZE 0x1000 +#define U8500_DSI_LINK_SIZE 0x1000 +#define U8500_DSI_LINK1_BASE (U8500_MCDE_BASE + U8500_MCDE_SIZE) +#define U8500_DSI_LINK2_BASE (U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE) +#define U8500_DSI_LINK3_BASE (U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE) +#define U8500_DSI_LINK_COUNT 0x3 + +/* Modem and APE physical addresses */ +#define U8500_MODEM_BASE 0xe000000 +#define U8500_APE_BASE 0x6000000 + #endif diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index bf63f2631ba..2c6f71049f2 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -35,6 +35,7 @@ #ifndef __ASSEMBLY__ #include <mach/id.h> +extern void __iomem *_PRCMU_BASE; #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h index f1288d10b6a..02b541a37ee 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/include/mach/id.h @@ -75,6 +75,26 @@ static inline bool __attribute_const__ cpu_is_u8500v2(void) return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0); } +static inline bool cpu_is_u8500v20(void) +{ + return cpu_is_u8500() && (dbx500_revision() == 0xB0); +} + +static inline bool cpu_is_u8500v21(void) +{ + return cpu_is_u8500() && (dbx500_revision() == 0xB1); +} + +static inline bool cpu_is_u8500v20_or_later(void) +{ + return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); +} + +static inline bool ux500_is_svp(void) +{ + return false; +} + #define ux500_unknown_soc() BUG() #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index 97ef55f8493..47969909836 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -50,6 +50,11 @@ #define MOP500_IRQ_END MOP500_NR_IRQS +/* + * We may have several boards, but only one will run at a + * time, so the one with most IRQs will bump this ahead, + * but the IRQ_BOARD_START remains the same for either board. + */ #if MOP500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END #define IRQ_BOARD_END MOP500_IRQ_END diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h new file mode 100644 index 00000000000..29d972c7717 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_IRQS_BOARD_U5500_H +#define __MACH_IRQS_BOARD_U5500_H + +#define AB5500_NR_IRQS 5 +#define IRQ_AB5500_BASE IRQ_BOARD_START +#define IRQ_AB5500_END (IRQ_AB5500_BASE + AB5500_NR_IRQS) + +#define U5500_IRQ_END IRQ_AB5500_END + +#if IRQ_BOARD_END < U5500_IRQ_END +#undef IRQ_BOARD_END +#define IRQ_BOARD_END U5500_IRQ_END +#endif + +#endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h index bfa123dbec3..77239776a6f 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h @@ -83,4 +83,31 @@ #define IRQ_DB5500_GPIO6 (IRQ_SHPI_START + 125) #define IRQ_DB5500_GPIO7 (IRQ_SHPI_START + 126) +#ifdef CONFIG_UX500_SOC_DB5500 + +/* + * After the GPIO ones we reserve a range of IRQ:s in which virtual + * IRQ:s representing modem IRQ:s can be allocated + */ +#define IRQ_MODEM_EVENTS_BASE IRQ_SOC_START +#define IRQ_MODEM_EVENTS_NBR 72 +#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR) + +/* List of virtual IRQ:s that are allocated from the range above */ +#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43) +#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45) +#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41) + +/* + * We may have several SoCs, but only one will run at a + * time, so the one with most IRQs will bump this ahead, + * but the IRQ_SOC_START remains the same for either SoC. + */ +#if IRQ_SOC_END < IRQ_MODEM_EVENTS_END +#undef IRQ_SOC_END +#define IRQ_SOC_END IRQ_MODEM_EVENTS_END +#endif + +#endif /* CONFIG_UX500_SOC_DB5500 */ + #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-db8500.h b/arch/arm/mach-ux500/include/mach/irqs-db8500.h index 8b5d9f0a163..68bc1497460 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-db8500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-db8500.h @@ -93,4 +93,58 @@ #define IRQ_DB8500_GPIO7 (IRQ_SHPI_START + 126) #define IRQ_DB8500_GPIO8 (IRQ_SHPI_START + 127) +#define IRQ_CA_WAKE_REQ_ED (IRQ_SHPI_START + 71) +#define IRQ_AC_READ_NOTIFICATION_0_ED (IRQ_SHPI_START + 66) +#define IRQ_AC_READ_NOTIFICATION_1_ED (IRQ_SHPI_START + 64) +#define IRQ_CA_MSG_PEND_NOTIFICATION_0_ED (IRQ_SHPI_START + 67) +#define IRQ_CA_MSG_PEND_NOTIFICATION_1_ED (IRQ_SHPI_START + 65) + +#define IRQ_CA_WAKE_REQ_V1 (IRQ_SHPI_START + 83) +#define IRQ_AC_READ_NOTIFICATION_0_V1 (IRQ_SHPI_START + 78) +#define IRQ_AC_READ_NOTIFICATION_1_V1 (IRQ_SHPI_START + 76) +#define IRQ_CA_MSG_PEND_NOTIFICATION_0_V1 (IRQ_SHPI_START + 79) +#define IRQ_CA_MSG_PEND_NOTIFICATION_1_V1 (IRQ_SHPI_START + 77) + +#ifdef CONFIG_UX500_SOC_DB8500 + +/* Virtual interrupts corresponding to the PRCMU wakeups. */ +#define IRQ_PRCMU_BASE IRQ_SOC_START +#define NUM_PRCMU_WAKEUPS (IRQ_PRCMU_END - IRQ_PRCMU_BASE) + +#define IRQ_PRCMU_RTC (IRQ_PRCMU_BASE) +#define IRQ_PRCMU_RTT0 (IRQ_PRCMU_BASE + 1) +#define IRQ_PRCMU_RTT1 (IRQ_PRCMU_BASE + 2) +#define IRQ_PRCMU_HSI0 (IRQ_PRCMU_BASE + 3) +#define IRQ_PRCMU_HSI1 (IRQ_PRCMU_BASE + 4) +#define IRQ_PRCMU_CA_WAKE (IRQ_PRCMU_BASE + 5) +#define IRQ_PRCMU_USB (IRQ_PRCMU_BASE + 6) +#define IRQ_PRCMU_ABB (IRQ_PRCMU_BASE + 7) +#define IRQ_PRCMU_ABB_FIFO (IRQ_PRCMU_BASE + 8) +#define IRQ_PRCMU_ARM (IRQ_PRCMU_BASE + 9) +#define IRQ_PRCMU_MODEM_SW_RESET_REQ (IRQ_PRCMU_BASE + 10) +#define IRQ_PRCMU_GPIO0 (IRQ_PRCMU_BASE + 11) +#define IRQ_PRCMU_GPIO1 (IRQ_PRCMU_BASE + 12) +#define IRQ_PRCMU_GPIO2 (IRQ_PRCMU_BASE + 13) +#define IRQ_PRCMU_GPIO3 (IRQ_PRCMU_BASE + 14) +#define IRQ_PRCMU_GPIO4 (IRQ_PRCMU_BASE + 15) +#define IRQ_PRCMU_GPIO5 (IRQ_PRCMU_BASE + 16) +#define IRQ_PRCMU_GPIO6 (IRQ_PRCMU_BASE + 17) +#define IRQ_PRCMU_GPIO7 (IRQ_PRCMU_BASE + 18) +#define IRQ_PRCMU_GPIO8 (IRQ_PRCMU_BASE + 19) +#define IRQ_PRCMU_CA_SLEEP (IRQ_PRCMU_BASE + 20) +#define IRQ_PRCMU_HOTMON_LOW (IRQ_PRCMU_BASE + 21) +#define IRQ_PRCMU_HOTMON_HIGH (IRQ_PRCMU_BASE + 22) +#define IRQ_PRCMU_END (IRQ_PRCMU_BASE + 23) + +/* + * We may have several SoCs, but only one will run at a + * time, so the one with most IRQs will bump this ahead, + * but the IRQ_SOC_START remains the same for either SoC. + */ +#if IRQ_SOC_END < IRQ_PRCMU_END +#undef IRQ_SOC_END +#define IRQ_SOC_END IRQ_PRCMU_END +#endif + +#endif /* CONFIG_UX500_SOC_DB8500 */ #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index ba1294c13c4..9db68d264c5 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -10,49 +10,47 @@ #ifndef ASM_ARCH_IRQS_H #define ASM_ARCH_IRQS_H -#include <mach/irqs-db5500.h> -#include <mach/irqs-db8500.h> +#include <mach/hardware.h> -#define IRQ_LOCALTIMER 29 -#define IRQ_LOCALWDOG 30 +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 /* Shared Peripheral Interrupt (SHPI) */ #define IRQ_SHPI_START 32 -/* Interrupt numbers generic for shared peripheral */ +/* + * MTU0 preserved for now until plat-nomadik is taught not to use it. Don't + * add any other IRQs here, use the irqs-dbx500.h files. + */ #define IRQ_MTU0 (IRQ_SHPI_START + 4) -/* There are 128 shared peripheral interrupts assigned to - * INTID[160:32]. The first 32 interrupts are reserved. - */ -#define DBX500_NR_INTERNAL_IRQS 161 +#define DBX500_NR_INTERNAL_IRQS 160 /* After chip-specific IRQ numbers we have the GPIO ones */ #define NOMADIK_NR_GPIO 288 #define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + DBX500_NR_INTERNAL_IRQS) #define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS) -#define IRQ_BOARD_START NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) +#define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) + +#define IRQ_SOC_START IRQ_GPIO_END +/* This will be overridden by SoC-specific irq headers */ +#define IRQ_SOC_END IRQ_SOC_START +#include <mach/irqs-db5500.h> +#include <mach/irqs-db8500.h> + +#define IRQ_BOARD_START IRQ_SOC_END /* This will be overridden by board-specific irq headers */ -#define IRQ_BOARD_END IRQ_BOARD_START +#define IRQ_BOARD_END IRQ_BOARD_START #ifdef CONFIG_MACH_U8500 #include <mach/irqs-board-mop500.h> #endif -/* - * After the board specific IRQ:s we reserve a range of IRQ:s in which virtual - * IRQ:s representing modem IRQ:s can be allocated - */ -#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1) -#define IRQ_MODEM_EVENTS_NBR 72 -#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR) - -/* List of virtual IRQ:s that are allocated from the range above */ -#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43) -#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45) -#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41) +#ifdef CONFIG_MACH_U5500 +#include <mach/irqs-board-u5500.h> +#endif -#define NR_IRQS IRQ_MODEM_EVENTS_END +#define NR_IRQS IRQ_BOARD_END #endif /* ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-defs.h b/arch/arm/mach-ux500/include/mach/prcmu-defs.h deleted file mode 100644 index 848ba64b561..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-defs.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * Author: Martin Persson <martin.persson@stericsson.com> - * - * License Terms: GNU General Public License v2 - * - * PRCM Unit definitions - */ - -#ifndef __MACH_PRCMU_DEFS_H -#define __MACH_PRCMU_DEFS_H - -enum prcmu_cpu_opp { - CPU_OPP_INIT = 0x00, - CPU_OPP_NO_CHANGE = 0x01, - CPU_OPP_100 = 0x02, - CPU_OPP_50 = 0x03, - CPU_OPP_MAX = 0x04, - CPU_OPP_EXT_CLK = 0x07 -}; -enum prcmu_ape_opp { - APE_OPP_NO_CHANGE = 0x00, - APE_OPP_100 = 0x02, - APE_OPP_50 = 0x03, -}; - -#endif /* __MACH_PRCMU_DEFS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h deleted file mode 100644 index c49e456162e..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> - * - * License Terms: GNU General Public License v2 - * - * PRCM Unit f/w API - */ -#ifndef __MACH_PRCMU_H -#define __MACH_PRCMU_H -#include <mach/prcmu-defs.h> - -void __init prcmu_early_init(void); -int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); -int prcmu_set_ape_opp(enum prcmu_ape_opp opp); -int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp); -int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, - enum prcmu_cpu_opp cpu_opp); -int prcmu_get_ape_opp(void); -int prcmu_get_cpu_opp(void); -bool prcmu_has_arm_maxopp(void); - -#endif /* __MACH_PRCMU_H */ diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c deleted file mode 100644 index c522d26ef34..00000000000 --- a/arch/arm/mach-ux500/prcmu.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> - * - * U8500 PRCM Unit interface driver - * - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/jiffies.h> -#include <linux/bitops.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <mach/prcmu-regs.h> -#include <mach/prcmu-defs.h> - -/* Global var to runtime determine TCDM base for v2 or v1 */ -static __iomem void *tcdm_base; - -#define _MBOX_HEADER (tcdm_base + 0xFE8) -#define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0) - -#define REQ_MB1 (tcdm_base + 0xFD0) -#define REQ_MB5 (tcdm_base + 0xE44) - -#define REQ_MB1_ARMOPP (REQ_MB1 + 0x0) -#define REQ_MB1_APEOPP (REQ_MB1 + 0x1) -#define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2) - -#define ACK_MB1 (tcdm_base + 0xE04) -#define ACK_MB5 (tcdm_base + 0xDF4) - -#define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0) -#define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1) - -#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) -#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) -#define REQ_MB5_I2C_REG (REQ_MB5 + 2) -#define REQ_MB5_I2C_VAL (REQ_MB5 + 3) - -#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) -#define ACK_MB5_I2C_VAL (ACK_MB5 + 3) - -#define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4) -#define PRCM_AVS_ISMODEENABLE 7 -#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE) - -#define I2C_WRITE(slave) \ - (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) -#define I2C_READ(slave) \ - (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0)) -#define I2C_STOP_EN BIT(3) - -enum mb1_h { - MB1H_ARM_OPP = 1, - MB1H_APE_OPP, - MB1H_ARM_APE_OPP, -}; - -static struct { - struct mutex lock; - struct completion work; - struct { - u8 arm_opp; - u8 ape_opp; - u8 arm_status; - u8 ape_status; - } ack; -} mb1_transfer; - -enum ack_mb5_status { - I2C_WR_OK = 0x01, - I2C_RD_OK = 0x02, -}; - -#define MBOX_BIT BIT -#define NUM_MBOX 8 - -static struct { - struct mutex lock; - struct completion work; - bool failed; - struct { - u8 status; - u8 value; - } ack; -} mb5_transfer; - -/** - * prcmu_abb_read() - Read register value(s) from the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The read out value(s). - * @size: The number of registers to read. - * - * Reads register value(s) from the ABB. - * @size has to be 1 for the current firmware version. - */ -int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if (size != 1) - return -EINVAL; - - r = mutex_lock_interruptible(&mb5_transfer.lock); - if (r) - return r; - - while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - - writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP); - writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS); - writeb(reg, REQ_MB5_I2C_REG); - - writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); - if (!wait_for_completion_timeout(&mb5_transfer.work, - msecs_to_jiffies(500))) { - pr_err("prcmu: prcmu_abb_read timed out.\n"); - r = -EIO; - goto unlock_and_return; - } - r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO); - if (!r) - *value = mb5_transfer.ack.value; - -unlock_and_return: - mutex_unlock(&mb5_transfer.lock); - return r; -} -EXPORT_SYMBOL(prcmu_abb_read); - -/** - * prcmu_abb_write() - Write register value(s) to the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The value(s) to write. - * @size: The number of registers to write. - * - * Reads register value(s) from the ABB. - * @size has to be 1 for the current firmware version. - */ -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if (size != 1) - return -EINVAL; - - r = mutex_lock_interruptible(&mb5_transfer.lock); - if (r) - return r; - - - while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - - writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP); - writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS); - writeb(reg, REQ_MB5_I2C_REG); - writeb(*value, REQ_MB5_I2C_VAL); - - writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); - if (!wait_for_completion_timeout(&mb5_transfer.work, - msecs_to_jiffies(500))) { - pr_err("prcmu: prcmu_abb_write timed out.\n"); - r = -EIO; - goto unlock_and_return; - } - r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO); - -unlock_and_return: - mutex_unlock(&mb5_transfer.lock); - return r; -} -EXPORT_SYMBOL(prcmu_abb_write); - -static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp, - enum prcmu_cpu_opp cpu_opp) -{ - bool do_ape; - bool do_arm; - int err = 0; - - do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP)); - do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP)); - - mutex_lock(&mb1_transfer.lock); - - while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(0, MBOX_HEADER_REQ_MB0); - writeb(cpu_opp, REQ_MB1_ARMOPP); - writeb(ape_opp, REQ_MB1_APEOPP); - writeb(0, REQ_MB1_BOOSTOPP); - writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); - wait_for_completion(&mb1_transfer.work); - if ((do_ape) && (mb1_transfer.ack.ape_status != 0)) - err = -EIO; - if ((do_arm) && (mb1_transfer.ack.arm_status != 0)) - err = -EIO; - - mutex_unlock(&mb1_transfer.lock); - - return err; -} - -/** - * prcmu_set_ape_opp() - Set the OPP of the APE. - * @opp: The OPP to set. - * - * This function sets the OPP of the APE. - */ -int prcmu_set_ape_opp(enum prcmu_ape_opp opp) -{ - return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE); -} -EXPORT_SYMBOL(prcmu_set_ape_opp); - -/** - * prcmu_set_cpu_opp() - Set the OPP of the CPU. - * @opp: The OPP to set. - * - * This function sets the OPP of the CPU. - */ -int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp) -{ - return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp); -} -EXPORT_SYMBOL(prcmu_set_cpu_opp); - -/** - * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU. - * @ape_opp: The APE OPP to set. - * @cpu_opp: The CPU OPP to set. - * - * This function sets the OPPs of the APE and the CPU. - */ -int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, - enum prcmu_cpu_opp cpu_opp) -{ - return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp); -} -EXPORT_SYMBOL(prcmu_set_ape_cpu_opps); - -/** - * prcmu_get_ape_opp() - Get the OPP of the APE. - * - * This function gets the OPP of the APE. - */ -enum prcmu_ape_opp prcmu_get_ape_opp(void) -{ - return readb(ACK_MB1_CURR_APEOPP); -} -EXPORT_SYMBOL(prcmu_get_ape_opp); - -/** - * prcmu_get_cpu_opp() - Get the OPP of the CPU. - * - * This function gets the OPP of the CPU. The OPP is specified in %%. - * PRCMU_OPP_EXT is a special OPP value, not specified in %%. - */ -int prcmu_get_cpu_opp(void) -{ - return readb(ACK_MB1_CURR_ARMOPP); -} -EXPORT_SYMBOL(prcmu_get_cpu_opp); - -bool prcmu_has_arm_maxopp(void) -{ - return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK) - == PRCM_AVS_ISMODEENABLE_MASK; -} - -static void read_mailbox_0(void) -{ - writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_1(void) -{ - mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP); - mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP); - complete(&mb1_transfer.work); - writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_2(void) -{ - writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_3(void) -{ - writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_4(void) -{ - writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_5(void) -{ - mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS); - mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL); - complete(&mb5_transfer.work); - writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_6(void) -{ - writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR); -} - -static void read_mailbox_7(void) -{ - writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR); -} - -static void (* const read_mailbox[NUM_MBOX])(void) = { - read_mailbox_0, - read_mailbox_1, - read_mailbox_2, - read_mailbox_3, - read_mailbox_4, - read_mailbox_5, - read_mailbox_6, - read_mailbox_7 -}; - -static irqreturn_t prcmu_irq_handler(int irq, void *data) -{ - u32 bits; - u8 n; - - bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1)); - if (unlikely(!bits)) - return IRQ_NONE; - - for (n = 0; bits; n++) { - if (bits & MBOX_BIT(n)) { - bits -= MBOX_BIT(n); - read_mailbox[n](); - } - } - return IRQ_HANDLED; -} - -void __init prcmu_early_init(void) -{ - if (cpu_is_u8500v11() || cpu_is_u8500ed()) { - tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1); - } else if (cpu_is_u8500v2()) { - tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); - } else { - pr_err("prcmu: Unsupported chip version\n"); - BUG(); - } -} - -static int __init prcmu_init(void) -{ - if (cpu_is_u8500ed()) { - pr_err("prcmu: Unsupported chip version\n"); - return 0; - } - - mutex_init(&mb1_transfer.lock); - init_completion(&mb1_transfer.work); - mutex_init(&mb5_transfer.lock); - init_completion(&mb5_transfer.work); - - /* Clean up the mailbox interrupts after pre-kernel code. */ - writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); - - return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0, - "prcmu", NULL); -} - -arch_initcall(prcmu_init); diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 8addb1220b4..a18180f2d00 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -24,11 +24,13 @@ config BLACKFIN select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_IDE + select HAVE_IRQ_WORK select HAVE_KERNEL_GZIP if RAMKERNEL select HAVE_KERNEL_BZIP2 if RAMKERNEL select HAVE_KERNEL_LZMA if RAMKERNEL select HAVE_KERNEL_LZO if RAMKERNEL select HAVE_OPROFILE + select HAVE_PERF_EVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select HAVE_GENERIC_HARDIRQS select GENERIC_ATOMIC64 diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 19ccfb3b67d..e2a3d4c8ab9 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -23,7 +23,7 @@ config DEBUG_VERBOSE Most people should say N here. config DEBUG_MMRS - bool "Generate Blackfin MMR tree" + tristate "Generate Blackfin MMR tree" select DEBUG_FS help Create a tree of Blackfin MMRs via the debugfs tree. If diff --git a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig index 95cf2ba9de1..8465b3e6b86 100644 --- a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig @@ -121,13 +121,11 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set # CONFIG_LOGO_BLACKFIN_VGA16 is not set -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_SOC=m -CONFIG_SND_BF5XX_I2S=m -CONFIG_SND_BF5XX_SOC_SSM2602=m -CONFIG_SND_BF5XX_AC97=m -CONFIG_SND_BF5XX_SOC_AD1980=m +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_BF5XX_I2S=y +CONFIG_SND_BF5XX_SOC_SSM2602=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 8be8e33fac5..5e7321b2604 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -96,7 +96,7 @@ CONFIG_SERIAL_BFIN_UART1=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=m -CONFIG_I2C_BLACKFIN_TWI=m +CONFIG_I2C_BLACKFIN_TWI=y CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 CONFIG_SPI=y CONFIG_SPI_BFIN=y @@ -115,13 +115,11 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set # CONFIG_LOGO_BLACKFIN_VGA16 is not set -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_SOC=m -CONFIG_SND_BF5XX_I2S=m -CONFIG_SND_BF5XX_SOC_SSM2602=m -CONFIG_SND_BF5XX_AC97=m -CONFIG_SND_BF5XX_SOC_AD1980=m +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_BF5XX_I2S=y +CONFIG_SND_BF5XX_SOC_SSM2602=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index 0aafde6c8c2..b90d3792ed5 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -99,8 +99,6 @@ CONFIG_SND_PCM_OSS=m CONFIG_SND_SOC=m CONFIG_SND_BF5XX_I2S=m CONFIG_SND_BF5XX_SOC_AD73311=m -CONFIG_SND_BF5XX_AC97=m -CONFIG_SND_BF5XX_SOC_AD1980=m # CONFIG_USB_SUPPORT is not set CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_BFIN=y diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index c9077fb5813..005362537a7 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -110,8 +110,6 @@ CONFIG_SND_PCM_OSS=m CONFIG_SND_SOC=m CONFIG_SND_BF5XX_I2S=m CONFIG_SND_BF5XX_SOC_AD73311=m -CONFIG_SND_BF5XX_AC97=m -CONFIG_SND_BF5XX_SOC_AD1980=m # CONFIG_USB_SUPPORT is not set CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_BFIN=y diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index 121cc04d877..17bcbf60bca 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -49,16 +49,6 @@ extern void dump_bfin_trace_buffer(void); #define dump_bfin_trace_buffer() #endif -/* init functions only */ -extern int init_arch_irq(void); -extern void init_exception_vectors(void); -extern void program_IAR(void); - -extern asmlinkage void lower_to_irq14(void); -extern asmlinkage void bfin_return_from_exception(void); -extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs); -extern int bfin_internal_set_wake(unsigned int irq, unsigned int state); - extern void *l1_data_A_sram_alloc(size_t); extern void *l1_data_B_sram_alloc(size_t); extern void *l1_inst_sram_alloc(size_t); diff --git a/arch/blackfin/include/asm/bfin_pfmon.h b/arch/blackfin/include/asm/bfin_pfmon.h new file mode 100644 index 00000000000..accd47e2db4 --- /dev/null +++ b/arch/blackfin/include/asm/bfin_pfmon.h @@ -0,0 +1,44 @@ +/* + * Blackfin Performance Monitor definitions + * + * Copyright 2005-2011 Analog Devices Inc. + * + * Licensed under the ADI BSD license or GPL-2 (or later). + */ + +#ifndef __ASM_BFIN_PFMON_H__ +#define __ASM_BFIN_PFMON_H__ + +/* PFCTL Masks */ +#define PFMON_MASK 0xff +#define PFCEN_MASK 0x3 +#define PFCEN_DISABLE 0x0 +#define PFCEN_ENABLE_USER 0x1 +#define PFCEN_ENABLE_SUPV 0x2 +#define PFCEN_ENABLE_ALL (PFCEN_ENABLE_USER | PFCEN_ENABLE_SUPV) + +#define PFPWR_P 0 +#define PEMUSW0_P 2 +#define PFCEN0_P 3 +#define PFMON0_P 5 +#define PEMUSW1_P 13 +#define PFCEN1_P 14 +#define PFMON1_P 16 +#define PFCNT0_P 24 +#define PFCNT1_P 25 + +#define PFPWR (1 << PFPWR_P) +#define PEMUSW(n, x) ((x) << ((n) ? PEMUSW1_P : PEMUSW0_P)) +#define PEMUSW0 PEMUSW(0, 1) +#define PEMUSW1 PEMUSW(1, 1) +#define PFCEN(n, x) ((x) << ((n) ? PFCEN1_P : PFCEN0_P)) +#define PFCEN0 PFCEN(0, PFCEN_MASK) +#define PFCEN1 PFCEN(1, PFCEN_MASK) +#define PFCNT(n, x) ((x) << ((n) ? PFCNT1_P : PFCNT0_P)) +#define PFCNT0 PFCNT(0, 1) +#define PFCNT1 PFCNT(1, 1) +#define PFMON(n, x) ((x) << ((n) ? PFMON1_P : PFMON0_P)) +#define PFMON0 PFMON(0, PFMON_MASK) +#define PFMON1 PFMON(1, PFMON_MASK) + +#endif diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h index d27600c262c..f8568a31d0a 100644 --- a/arch/blackfin/include/asm/bfin_sport.h +++ b/arch/blackfin/include/asm/bfin_sport.h @@ -100,6 +100,10 @@ struct sport_register { }; #undef __BFP +struct bfin_snd_platform_data { + const unsigned short *pin_req; +}; + #define bfin_read_sport_rx32(base) \ ({ \ struct sport_register *__mmrs = (void *)base; \ diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 77135b62818..9a5b2c572eb 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -39,8 +39,13 @@ extern void blackfin_invalidate_entire_icache(void); static inline void flush_icache_range(unsigned start, unsigned end) { -#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) - blackfin_dcache_flush_range(start, end); +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) + if (end <= physical_mem_end) + blackfin_dcache_flush_range(start, end); +#endif +#if defined(CONFIG_BFIN_L2_WRITEBACK) + if (start >= L2_START && end <= L2_START + L2_LENGTH) + blackfin_dcache_flush_range(start, end); #endif /* Make sure all write buffers in the data side of the core @@ -52,9 +57,17 @@ static inline void flush_icache_range(unsigned start, unsigned end) * the pipeline. */ SSYNC(); -#if defined(CONFIG_BFIN_ICACHE) - blackfin_icache_flush_range(start, end); - flush_icache_range_others(start, end); +#if defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) + if (end <= physical_mem_end) { + blackfin_icache_flush_range(start, end); + flush_icache_range_others(start, end); + } +#endif +#if defined(CONFIG_BFIN_L2_ICACHEABLE) + if (start >= L2_START && end <= L2_START + L2_LENGTH) { + blackfin_icache_flush_range(start, end); + flush_icache_range_others(start, end); + } #endif } diff --git a/arch/blackfin/include/asm/cpu.h b/arch/blackfin/include/asm/cpu.h index 16883e582e3..05043786da2 100644 --- a/arch/blackfin/include/asm/cpu.h +++ b/arch/blackfin/include/asm/cpu.h @@ -10,11 +10,8 @@ #include <linux/percpu.h> -struct task_struct; - struct blackfin_cpudata { struct cpu cpu; - struct task_struct *idle; unsigned int imemctl; unsigned int dmemctl; }; diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h index 7600fe0696a..82367901145 100644 --- a/arch/blackfin/include/asm/def_LPBlackfin.h +++ b/arch/blackfin/include/asm/def_LPBlackfin.h @@ -52,10 +52,10 @@ #define bfin_read(addr) \ ({ \ - sizeof(*(addr)) == 1 ? bfin_read8(addr) : \ - sizeof(*(addr)) == 2 ? bfin_read16(addr) : \ - sizeof(*(addr)) == 4 ? bfin_read32(addr) : \ - ({ BUG(); 0; }); \ + sizeof(*(addr)) == 1 ? bfin_read8(addr) : \ + sizeof(*(addr)) == 2 ? bfin_read16(addr) : \ + sizeof(*(addr)) == 4 ? bfin_read32(addr) : \ + ({ BUG(); 0; }); \ }) #define bfin_write(addr, val) \ do { \ @@ -69,13 +69,13 @@ do { \ #define bfin_write_or(addr, bits) \ do { \ - void *__addr = (void *)(addr); \ + typeof(addr) __addr = (addr); \ bfin_write(__addr, bfin_read(__addr) | (bits)); \ } while (0) #define bfin_write_and(addr, bits) \ do { \ - void *__addr = (void *)(addr); \ + typeof(addr) __addr = (addr); \ bfin_write(__addr, bfin_read(__addr) & (bits)); \ } while (0) diff --git a/arch/blackfin/include/asm/irq_handler.h b/arch/blackfin/include/asm/irq_handler.h index 7fbe42307b9..ee73f79aef1 100644 --- a/arch/blackfin/include/asm/irq_handler.h +++ b/arch/blackfin/include/asm/irq_handler.h @@ -10,6 +10,16 @@ #include <linux/types.h> #include <linux/linkage.h> +/* init functions only */ +extern int __init init_arch_irq(void); +extern void init_exception_vectors(void); +extern void __init program_IAR(void); +#ifdef init_mach_irq +extern void __init init_mach_irq(void); +#else +# define init_mach_irq() +#endif + /* BASE LEVEL interrupt handler routines */ asmlinkage void evt_exception(void); asmlinkage void trap(void); @@ -37,4 +47,19 @@ extern void return_from_exception(void); extern int bfin_request_exception(unsigned int exception, void (*handler)(void)); extern int bfin_free_exception(unsigned int exception, void (*handler)(void)); +extern asmlinkage void lower_to_irq14(void); +extern asmlinkage void bfin_return_from_exception(void); +extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs); +extern int bfin_internal_set_wake(unsigned int irq, unsigned int state); + +struct irq_data; +extern void bfin_handle_irq(unsigned irq); +extern void bfin_ack_noop(struct irq_data *); +extern void bfin_internal_mask_irq(unsigned int irq); +extern void bfin_internal_unmask_irq(unsigned int irq); + +struct irq_desc; +extern void bfin_demux_mac_status_irq(unsigned int, struct irq_desc *); +extern void bfin_demux_gpio_irq(unsigned int, struct irq_desc *); + #endif diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h index 8651afe1299..3ac0c72e9fe 100644 --- a/arch/blackfin/include/asm/kgdb.h +++ b/arch/blackfin/include/asm/kgdb.h @@ -103,7 +103,11 @@ static inline void arch_kgdb_breakpoint(void) asm("EXCPT 2;"); } #define BREAK_INSTR_SIZE 2 -#define CACHE_FLUSH_IS_SAFE 1 +#ifdef CONFIG_SMP +# define CACHE_FLUSH_IS_SAFE 0 +#else +# define CACHE_FLUSH_IS_SAFE 1 +#endif #define HW_INST_WATCHPOINT_NUM 6 #define HW_WATCHPOINT_NUM 8 #define TYPE_INST_WATCHPOINT 0 diff --git a/arch/blackfin/include/asm/perf_event.h b/arch/blackfin/include/asm/perf_event.h new file mode 100644 index 00000000000..3d2b1716322 --- /dev/null +++ b/arch/blackfin/include/asm/perf_event.h @@ -0,0 +1 @@ +#define MAX_HWEVENTS 2 diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h index 832d7c009a2..1066d63e62b 100644 --- a/arch/blackfin/include/asm/ptrace.h +++ b/arch/blackfin/include/asm/ptrace.h @@ -108,8 +108,6 @@ struct pt_regs { extern void show_regs(struct pt_regs *); #define arch_has_single_step() (1) -extern void user_enable_single_step(struct task_struct *child); -extern void user_disable_single_step(struct task_struct *child); /* common code demands this function */ #define ptrace_disable(child) user_disable_single_step(child) diff --git a/arch/blackfin/include/mach-common/irq.h b/arch/blackfin/include/mach-common/irq.h new file mode 100644 index 00000000000..cab14e911dc --- /dev/null +++ b/arch/blackfin/include/mach-common/irq.h @@ -0,0 +1,57 @@ +/* + * Common Blackfin IRQ definitions (i.e. the CEC) + * + * Copyright 2005-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later + */ + +#ifndef _MACH_COMMON_IRQ_H_ +#define _MACH_COMMON_IRQ_H_ + +/* + * Core events interrupt source definitions + * + * Event Source Event Name + * Emulation EMU 0 (highest priority) + * Reset RST 1 + * NMI NMI 2 + * Exception EVX 3 + * Reserved -- 4 + * Hardware Error IVHW 5 + * Core Timer IVTMR 6 + * Peripherals IVG7 7 + * Peripherals IVG8 8 + * Peripherals IVG9 9 + * Peripherals IVG10 10 + * Peripherals IVG11 11 + * Peripherals IVG12 12 + * Peripherals IVG13 13 + * Softirq IVG14 14 + * System Call IVG15 15 (lowest priority) + */ + +/* The ABSTRACT IRQ definitions */ +#define IRQ_EMU 0 /* Emulation */ +#define IRQ_RST 1 /* reset */ +#define IRQ_NMI 2 /* Non Maskable */ +#define IRQ_EVX 3 /* Exception */ +#define IRQ_UNUSED 4 /* - unused interrupt */ +#define IRQ_HWERR 5 /* Hardware Error */ +#define IRQ_CORETMR 6 /* Core timer */ + +#define BFIN_IRQ(x) ((x) + 7) + +#define IVG7 7 +#define IVG8 8 +#define IVG9 9 +#define IVG10 10 +#define IVG11 11 +#define IVG12 12 +#define IVG13 13 +#define IVG14 14 +#define IVG15 15 + +#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) + +#endif diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index ca5ccc77777..d550b24d9e9 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -33,7 +33,10 @@ obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_DEBUG_VERBOSE) += trace.o obj-$(CONFIG_BFIN_PSEUDODBG_INSNS) += pseudodbg.o +obj-$(CONFIG_PERF_EVENTS) += perf_event.o # the kgdb test puts code into L2 and without linker # relaxation, we need to force long calls to/from it CFLAGS_kgdb_test.o := -mlong-calls -O0 + +obj-$(CONFIG_DEBUG_MMRS) += debug-mmrs.o diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 6ce8dce753c..71dbaa4a48a 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -36,6 +36,11 @@ static int __init blackfin_dma_init(void) printk(KERN_INFO "Blackfin DMA Controller\n"); + +#if ANOMALY_05000480 + bfin_write_DMAC_TC_PER(0x0111); +#endif + for (i = 0; i < MAX_DMA_CHANNELS; i++) { atomic_set(&dma_ch[i].chan_status, 0); dma_ch[i].regs = dma_io_base_addr[i]; diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 170cf90735b..bcf8cf6fe41 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -10,10 +10,12 @@ #include <linux/module.h> #include <linux/err.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <asm/blackfin.h> #include <asm/gpio.h> #include <asm/portmux.h> #include <linux/irq.h> +#include <asm/irq_handler.h> #if ANOMALY_05000311 || ANOMALY_05000323 enum { @@ -534,7 +536,7 @@ static const unsigned int sic_iwr_irqs[] = { #if defined(BF533_FAMILY) IRQ_PROG_INTB #elif defined(BF537_FAMILY) - IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX + IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX #elif defined(BF538_FAMILY) IRQ_PORTF_INTB #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) @@ -1203,35 +1205,43 @@ void bfin_reset_boot_spi_cs(unsigned short pin) } #if defined(CONFIG_PROC_FS) -static int gpio_proc_read(char *buf, char **start, off_t offset, - int len, int *unused_i, void *unused_v) +static int gpio_proc_show(struct seq_file *m, void *v) { - int c, irq, gpio, outlen = 0; + int c, irq, gpio; for (c = 0; c < MAX_RESOURCES; c++) { irq = is_reserved(gpio_irq, c, 1); gpio = is_reserved(gpio, c, 1); if (!check_gpio(c) && (gpio || irq)) - len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, + seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, get_label(c), (gpio && irq) ? " *" : "", get_gpio_dir(c) ? "OUTPUT" : "INPUT"); else if (is_reserved(peri, c, 1)) - len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); + seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); else continue; - buf += len; - outlen += len; } - return outlen; + + return 0; } +static int gpio_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, gpio_proc_show, NULL); +} + +static const struct file_operations gpio_proc_ops = { + .open = gpio_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static __init int gpio_register_proc(void) { struct proc_dir_entry *proc_gpio; - proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); - if (proc_gpio) - proc_gpio->read_proc = gpio_proc_read; + proc_gpio = proc_create("gpio", S_IRUGO, NULL, &gpio_proc_ops); return proc_gpio != NULL; } __initcall(gpio_register_proc); diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 2c264b51566..c446591b961 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c @@ -11,6 +11,7 @@ #include <asm/cacheflush.h> #include <asm/io.h> +#include <asm/irq_handler.h> /* Allow people to have their own Blackfin exception handler in a module */ EXPORT_SYMBOL(bfin_return_from_exception); diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c new file mode 100644 index 00000000000..94b1d8a0256 --- /dev/null +++ b/arch/blackfin/kernel/debug-mmrs.c @@ -0,0 +1,1860 @@ +/* + * debugfs interface to core/system MMRs + * + * Copyright 2007-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later + */ + +#include <linux/debugfs.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/blackfin.h> +#include <asm/gpio.h> +#include <asm/bfin_can.h> +#include <asm/bfin_dma.h> +#include <asm/bfin_ppi.h> +#include <asm/bfin_serial.h> +#include <asm/bfin5xx_spi.h> +#include <asm/bfin_twi.h> + +/* Common code defines PORT_MUX on us, so redirect the MMR back locally */ +#ifdef BFIN_PORT_MUX +#undef PORT_MUX +#define PORT_MUX BFIN_PORT_MUX +#endif + +#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)addr) +#define d(name, bits, addr) _d(name, bits, addr, S_IRUSR|S_IWUSR) +#define d_RO(name, bits, addr) _d(name, bits, addr, S_IRUSR) +#define d_WO(name, bits, addr) _d(name, bits, addr, S_IWUSR) + +#define D_RO(name, bits) d_RO(#name, bits, name) +#define D_WO(name, bits) d_WO(#name, bits, name) +#define D32(name) d(#name, 32, name) +#define D16(name) d(#name, 16, name) + +#define REGS_OFF(peri, mmr) offsetof(struct bfin_##peri##_regs, mmr) +#define __REGS(peri, sname, rname) \ + do { \ + struct bfin_##peri##_regs r; \ + void *addr = (void *)(base + REGS_OFF(peri, rname)); \ + strcpy(_buf, sname); \ + if (sizeof(r.rname) == 2) \ + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, parent, addr); \ + else \ + debugfs_create_x32(buf, S_IRUSR|S_IWUSR, parent, addr); \ + } while (0) +#define REGS_STR_PFX(buf, pfx, num) \ + ({ \ + buf + (num >= 0 ? \ + sprintf(buf, #pfx "%i_", num) : \ + sprintf(buf, #pfx "_")); \ + }) +#define REGS_STR_PFX_C(buf, pfx, num) \ + ({ \ + buf + (num >= 0 ? \ + sprintf(buf, #pfx "%c_", 'A' + num) : \ + sprintf(buf, #pfx "_")); \ + }) + +/* + * Core registers (not memory mapped) + */ +extern u32 last_seqstat; + +static int debug_cclk_get(void *data, u64 *val) +{ + *val = get_cclk(); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_debug_cclk, debug_cclk_get, NULL, "0x%08llx\n"); + +static int debug_sclk_get(void *data, u64 *val) +{ + *val = get_sclk(); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_debug_sclk, debug_sclk_get, NULL, "0x%08llx\n"); + +#define DEFINE_SYSREG(sr, pre, post) \ +static int sysreg_##sr##_get(void *data, u64 *val) \ +{ \ + unsigned long tmp; \ + pre; \ + __asm__ __volatile__("%0 = " #sr ";" : "=d"(tmp)); \ + *val = tmp; \ + return 0; \ +} \ +static int sysreg_##sr##_set(void *data, u64 val) \ +{ \ + unsigned long tmp = val; \ + __asm__ __volatile__(#sr " = %0;" : : "d"(tmp)); \ + post; \ + return 0; \ +} \ +DEFINE_SIMPLE_ATTRIBUTE(fops_sysreg_##sr, sysreg_##sr##_get, sysreg_##sr##_set, "0x%08llx\n") + +DEFINE_SYSREG(cycles, , ); +DEFINE_SYSREG(cycles2, __asm__ __volatile__("%0 = cycles;" : "=d"(tmp)), ); +DEFINE_SYSREG(emudat, , ); +DEFINE_SYSREG(seqstat, , ); +DEFINE_SYSREG(syscfg, , CSYNC()); +#define D_SYSREG(sr) debugfs_create_file(#sr, S_IRUSR|S_IWUSR, parent, NULL, &fops_sysreg_##sr) + +/* + * CAN + */ +#define CAN_OFF(mmr) REGS_OFF(can, mmr) +#define __CAN(uname, lname) __REGS(can, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_can(struct dentry *parent, unsigned long base, int num) +{ + static struct dentry *am, *mb; + int i, j; + char buf[32], *_buf = REGS_STR_PFX(buf, CAN, num); + + if (!am) { + am = debugfs_create_dir("am", parent); + mb = debugfs_create_dir("mb", parent); + } + + __CAN(MC1, mc1); + __CAN(MD1, md1); + __CAN(TRS1, trs1); + __CAN(TRR1, trr1); + __CAN(TA1, ta1); + __CAN(AA1, aa1); + __CAN(RMP1, rmp1); + __CAN(RML1, rml1); + __CAN(MBTIF1, mbtif1); + __CAN(MBRIF1, mbrif1); + __CAN(MBIM1, mbim1); + __CAN(RFH1, rfh1); + __CAN(OPSS1, opss1); + + __CAN(MC2, mc2); + __CAN(MD2, md2); + __CAN(TRS2, trs2); + __CAN(TRR2, trr2); + __CAN(TA2, ta2); + __CAN(AA2, aa2); + __CAN(RMP2, rmp2); + __CAN(RML2, rml2); + __CAN(MBTIF2, mbtif2); + __CAN(MBRIF2, mbrif2); + __CAN(MBIM2, mbim2); + __CAN(RFH2, rfh2); + __CAN(OPSS2, opss2); + + __CAN(CLOCK, clock); + __CAN(TIMING, timing); + __CAN(DEBUG, debug); + __CAN(STATUS, status); + __CAN(CEC, cec); + __CAN(GIS, gis); + __CAN(GIM, gim); + __CAN(GIF, gif); + __CAN(CONTROL, control); + __CAN(INTR, intr); + __CAN(VERSION, version); + __CAN(MBTD, mbtd); + __CAN(EWR, ewr); + __CAN(ESR, esr); + /*__CAN(UCREG, ucreg); no longer exists */ + __CAN(UCCNT, uccnt); + __CAN(UCRC, ucrc); + __CAN(UCCNF, uccnf); + __CAN(VERSION2, version2); + + for (i = 0; i < 32; ++i) { + sprintf(_buf, "AM%02iL", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, am, + (u16 *)(base + CAN_OFF(msk[i].aml))); + sprintf(_buf, "AM%02iH", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, am, + (u16 *)(base + CAN_OFF(msk[i].amh))); + + for (j = 0; j < 3; ++j) { + sprintf(_buf, "MB%02i_DATA%i", i, j); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, mb, + (u16 *)(base + CAN_OFF(chl[i].data[j*2]))); + } + sprintf(_buf, "MB%02i_LENGTH", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, mb, + (u16 *)(base + CAN_OFF(chl[i].dlc))); + sprintf(_buf, "MB%02i_TIMESTAMP", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, mb, + (u16 *)(base + CAN_OFF(chl[i].tsv))); + sprintf(_buf, "MB%02i_ID0", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, mb, + (u16 *)(base + CAN_OFF(chl[i].id0))); + sprintf(_buf, "MB%02i_ID1", i); + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, mb, + (u16 *)(base + CAN_OFF(chl[i].id1))); + } +} +#define CAN(num) bfin_debug_mmrs_can(parent, CAN##num##_MC1, num) + +/* + * DMA + */ +#define __DMA(uname, lname) __REGS(dma, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_dma(struct dentry *parent, unsigned long base, int num, char mdma, const char *pfx) +{ + char buf[32], *_buf; + + if (mdma) + _buf = buf + sprintf(buf, "%s_%c%i_", pfx, mdma, num); + else + _buf = buf + sprintf(buf, "%s%i_", pfx, num); + + __DMA(NEXT_DESC_PTR, next_desc_ptr); + __DMA(START_ADDR, start_addr); + __DMA(CONFIG, config); + __DMA(X_COUNT, x_count); + __DMA(X_MODIFY, x_modify); + __DMA(Y_COUNT, y_count); + __DMA(Y_MODIFY, y_modify); + __DMA(CURR_DESC_PTR, curr_desc_ptr); + __DMA(CURR_ADDR, curr_addr); + __DMA(IRQ_STATUS, irq_status); + __DMA(PERIPHERAL_MAP, peripheral_map); + __DMA(CURR_X_COUNT, curr_x_count); + __DMA(CURR_Y_COUNT, curr_y_count); +} +#define _DMA(num, base, mdma, pfx) bfin_debug_mmrs_dma(parent, base, num, mdma, pfx "DMA") +#define DMA(num) _DMA(num, DMA##num##_NEXT_DESC_PTR, 0, "") +#define _MDMA(num, x) \ + do { \ + _DMA(num, x##DMA_D##num##_CONFIG, 'D', #x); \ + _DMA(num, x##DMA_S##num##_CONFIG, 'S', #x); \ + } while (0) +#define MDMA(num) _MDMA(num, M) +#define IMDMA(num) _MDMA(num, IM) + +/* + * EPPI + */ +#define __EPPI(uname, lname) __REGS(eppi, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_eppi(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, EPPI, num); + __EPPI(STATUS, status); + __EPPI(HCOUNT, hcount); + __EPPI(HDELAY, hdelay); + __EPPI(VCOUNT, vcount); + __EPPI(VDELAY, vdelay); + __EPPI(FRAME, frame); + __EPPI(LINE, line); + __EPPI(CLKDIV, clkdiv); + __EPPI(CONTROL, control); + __EPPI(FS1W_HBL, fs1w_hbl); + __EPPI(FS1P_AVPL, fs1p_avpl); + __EPPI(FS2W_LVB, fs2w_lvb); + __EPPI(FS2P_LAVF, fs2p_lavf); + __EPPI(CLIP, clip); +} +#define EPPI(num) bfin_debug_mmrs_eppi(parent, EPPI##num##_STATUS, num) + +/* + * General Purpose Timers + */ +#define GPTIMER_OFF(mmr) (TIMER0_##mmr - TIMER0_CONFIG) +#define __GPTIMER(name) \ + do { \ + strcpy(_buf, #name); \ + debugfs_create_x16(buf, S_IRUSR|S_IWUSR, parent, (u16 *)(base + GPTIMER_OFF(name))); \ + } while (0) +static void __init __maybe_unused +bfin_debug_mmrs_gptimer(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, TIMER, num); + __GPTIMER(CONFIG); + __GPTIMER(COUNTER); + __GPTIMER(PERIOD); + __GPTIMER(WIDTH); +} +#define GPTIMER(num) bfin_debug_mmrs_gptimer(parent, TIMER##num##_CONFIG, num) + +/* + * Handshake MDMA + */ +#define __HMDMA(uname, lname) __REGS(hmdma, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_hmdma(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, HMDMA, num); + __HMDMA(CONTROL, control); + __HMDMA(ECINIT, ecinit); + __HMDMA(BCINIT, bcinit); + __HMDMA(ECURGENT, ecurgent); + __HMDMA(ECOVERFLOW, ecoverflow); + __HMDMA(ECOUNT, ecount); + __HMDMA(BCOUNT, bcount); +} +#define HMDMA(num) bfin_debug_mmrs_hmdma(parent, HMDMA##num##_CONTROL, num) + +/* + * Port/GPIO + */ +#define bfin_gpio_regs gpio_port_t +#define __PORT(uname, lname) __REGS(gpio, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_port(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf; +#ifdef __ADSPBF54x__ + _buf = REGS_STR_PFX_C(buf, PORT, num); + __PORT(FER, port_fer); + __PORT(SET, data_set); + __PORT(CLEAR, data_clear); + __PORT(DIR_SET, dir_set); + __PORT(DIR_CLEAR, dir_clear); + __PORT(INEN, inen); + __PORT(MUX, port_mux); +#else + _buf = buf + sprintf(buf, "PORT%cIO_", num); + __PORT(CLEAR, data_clear); + __PORT(SET, data_set); + __PORT(TOGGLE, toggle); + __PORT(MASKA, maska); + __PORT(MASKA_CLEAR, maska_clear); + __PORT(MASKA_SET, maska_set); + __PORT(MASKA_TOGGLE, maska_toggle); + __PORT(MASKB, maskb); + __PORT(MASKB_CLEAR, maskb_clear); + __PORT(MASKB_SET, maskb_set); + __PORT(MASKB_TOGGLE, maskb_toggle); + __PORT(DIR, dir); + __PORT(POLAR, polar); + __PORT(EDGE, edge); + __PORT(BOTH, both); + __PORT(INEN, inen); +#endif + _buf[-1] = '\0'; + d(buf, 16, base + REGS_OFF(gpio, data)); +} +#define PORT(base, num) bfin_debug_mmrs_port(parent, base, num) + +/* + * PPI + */ +#define __PPI(uname, lname) __REGS(ppi, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_ppi(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, PPI, num); + __PPI(CONTROL, control); + __PPI(STATUS, status); + __PPI(COUNT, count); + __PPI(DELAY, delay); + __PPI(FRAME, frame); +} +#define PPI(num) bfin_debug_mmrs_ppi(parent, PPI##num##_STATUS, num) + +/* + * SPI + */ +#define __SPI(uname, lname) __REGS(spi, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_spi(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, SPI, num); + __SPI(CTL, ctl); + __SPI(FLG, flg); + __SPI(STAT, stat); + __SPI(TDBR, tdbr); + __SPI(RDBR, rdbr); + __SPI(BAUD, baud); + __SPI(SHADOW, shadow); +} +#define SPI(num) bfin_debug_mmrs_spi(parent, SPI##num##_REGBASE, num) + +/* + * SPORT + */ +static inline int sport_width(void *mmr) +{ + unsigned long lmmr = (unsigned long)mmr; + if ((lmmr & 0xff) == 0x10) + /* SPORT#_TX has 0x10 offset -> SPORT#_TCR2 has 0x04 offset */ + lmmr -= 0xc; + else + /* SPORT#_RX has 0x18 offset -> SPORT#_RCR2 has 0x24 offset */ + lmmr += 0xc; + /* extract SLEN field from control register 2 and add 1 */ + return (bfin_read16(lmmr) & 0x1f) + 1; +} +static int sport_set(void *mmr, u64 val) +{ + unsigned long flags; + local_irq_save(flags); + if (sport_width(mmr) <= 16) + bfin_write16(mmr, val); + else + bfin_write32(mmr, val); + local_irq_restore(flags); + return 0; +} +static int sport_get(void *mmr, u64 *val) +{ + unsigned long flags; + local_irq_save(flags); + if (sport_width(mmr) <= 16) + *val = bfin_read16(mmr); + else + *val = bfin_read32(mmr); + local_irq_restore(flags); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_sport, sport_get, sport_set, "0x%08llx\n"); +/*DEFINE_SIMPLE_ATTRIBUTE(fops_sport_ro, sport_get, NULL, "0x%08llx\n");*/ +DEFINE_SIMPLE_ATTRIBUTE(fops_sport_wo, NULL, sport_set, "0x%08llx\n"); +#define SPORT_OFF(mmr) (SPORT0_##mmr - SPORT0_TCR1) +#define _D_SPORT(name, perms, fops) \ + do { \ + strcpy(_buf, #name); \ + debugfs_create_file(buf, perms, parent, (void *)(base + SPORT_OFF(name)), fops); \ + } while (0) +#define __SPORT_RW(name) _D_SPORT(name, S_IRUSR|S_IWUSR, &fops_sport) +#define __SPORT_RO(name) _D_SPORT(name, S_IRUSR, &fops_sport_ro) +#define __SPORT_WO(name) _D_SPORT(name, S_IWUSR, &fops_sport_wo) +#define __SPORT(name, bits) \ + do { \ + strcpy(_buf, #name); \ + debugfs_create_x##bits(buf, S_IRUSR|S_IWUSR, parent, (u##bits *)(base + SPORT_OFF(name))); \ + } while (0) +static void __init __maybe_unused +bfin_debug_mmrs_sport(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, SPORT, num); + __SPORT(CHNL, 16); + __SPORT(MCMC1, 16); + __SPORT(MCMC2, 16); + __SPORT(MRCS0, 32); + __SPORT(MRCS1, 32); + __SPORT(MRCS2, 32); + __SPORT(MRCS3, 32); + __SPORT(MTCS0, 32); + __SPORT(MTCS1, 32); + __SPORT(MTCS2, 32); + __SPORT(MTCS3, 32); + __SPORT(RCLKDIV, 16); + __SPORT(RCR1, 16); + __SPORT(RCR2, 16); + __SPORT(RFSDIV, 16); + __SPORT_RW(RX); + __SPORT(STAT, 16); + __SPORT(TCLKDIV, 16); + __SPORT(TCR1, 16); + __SPORT(TCR2, 16); + __SPORT(TFSDIV, 16); + __SPORT_WO(TX); +} +#define SPORT(num) bfin_debug_mmrs_sport(parent, SPORT##num##_TCR1, num) + +/* + * TWI + */ +#define __TWI(uname, lname) __REGS(twi, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_twi(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, TWI, num); + __TWI(CLKDIV, clkdiv); + __TWI(CONTROL, control); + __TWI(SLAVE_CTL, slave_ctl); + __TWI(SLAVE_STAT, slave_stat); + __TWI(SLAVE_ADDR, slave_addr); + __TWI(MASTER_CTL, master_ctl); + __TWI(MASTER_STAT, master_stat); + __TWI(MASTER_ADDR, master_addr); + __TWI(INT_STAT, int_stat); + __TWI(INT_MASK, int_mask); + __TWI(FIFO_CTL, fifo_ctl); + __TWI(FIFO_STAT, fifo_stat); + __TWI(XMT_DATA8, xmt_data8); + __TWI(XMT_DATA16, xmt_data16); + __TWI(RCV_DATA8, rcv_data8); + __TWI(RCV_DATA16, rcv_data16); +} +#define TWI(num) bfin_debug_mmrs_twi(parent, TWI##num##_CLKDIV, num) + +/* + * UART + */ +#define __UART(uname, lname) __REGS(uart, #uname, lname) +static void __init __maybe_unused +bfin_debug_mmrs_uart(struct dentry *parent, unsigned long base, int num) +{ + char buf[32], *_buf = REGS_STR_PFX(buf, UART, num); +#ifdef BFIN_UART_BF54X_STYLE + __UART(DLL, dll); + __UART(DLH, dlh); + __UART(GCTL, gctl); + __UART(LCR, lcr); + __UART(MCR, mcr); + __UART(LSR, lsr); + __UART(MSR, msr); + __UART(SCR, scr); + __UART(IER_SET, ier_set); + __UART(IER_CLEAR, ier_clear); + __UART(THR, thr); + __UART(RBR, rbr); +#else + __UART(DLL, dll); + __UART(THR, thr); + __UART(RBR, rbr); + __UART(DLH, dlh); + __UART(IER, ier); + __UART(IIR, iir); + __UART(LCR, lcr); + __UART(MCR, mcr); + __UART(LSR, lsr); + __UART(MSR, msr); + __UART(SCR, scr); + __UART(GCTL, gctl); +#endif +} +#define UART(num) bfin_debug_mmrs_uart(parent, UART##num##_DLL, num) + +/* + * The actual debugfs generation + */ +static struct dentry *debug_mmrs_dentry; + +static int __init bfin_debug_mmrs_init(void) +{ + struct dentry *top, *parent; + + pr_info("debug-mmrs: setting up Blackfin MMR debugfs\n"); + + top = debugfs_create_dir("blackfin", NULL); + if (top == NULL) + return -1; + + parent = debugfs_create_dir("core_regs", top); + debugfs_create_file("cclk", S_IRUSR, parent, NULL, &fops_debug_cclk); + debugfs_create_file("sclk", S_IRUSR, parent, NULL, &fops_debug_sclk); + debugfs_create_x32("last_seqstat", S_IRUSR, parent, &last_seqstat); + D_SYSREG(cycles); + D_SYSREG(cycles2); + D_SYSREG(emudat); + D_SYSREG(seqstat); + D_SYSREG(syscfg); + + /* Core MMRs */ + parent = debugfs_create_dir("ctimer", top); + D32(TCNTL); + D32(TCOUNT); + D32(TPERIOD); + D32(TSCALE); + + parent = debugfs_create_dir("cec", top); + D32(EVT0); + D32(EVT1); + D32(EVT2); + D32(EVT3); + D32(EVT4); + D32(EVT5); + D32(EVT6); + D32(EVT7); + D32(EVT8); + D32(EVT9); + D32(EVT10); + D32(EVT11); + D32(EVT12); + D32(EVT13); + D32(EVT14); + D32(EVT15); + D32(EVT_OVERRIDE); + D32(IMASK); + D32(IPEND); + D32(ILAT); + D32(IPRIO); + + parent = debugfs_create_dir("debug", top); + D32(DBGSTAT); + D32(DSPID); + + parent = debugfs_create_dir("mmu", top); + D32(SRAM_BASE_ADDRESS); + D32(DCPLB_ADDR0); + D32(DCPLB_ADDR10); + D32(DCPLB_ADDR11); + D32(DCPLB_ADDR12); + D32(DCPLB_ADDR13); + D32(DCPLB_ADDR14); + D32(DCPLB_ADDR15); + D32(DCPLB_ADDR1); + D32(DCPLB_ADDR2); + D32(DCPLB_ADDR3); + D32(DCPLB_ADDR4); + D32(DCPLB_ADDR5); + D32(DCPLB_ADDR6); + D32(DCPLB_ADDR7); + D32(DCPLB_ADDR8); + D32(DCPLB_ADDR9); + D32(DCPLB_DATA0); + D32(DCPLB_DATA10); + D32(DCPLB_DATA11); + D32(DCPLB_DATA12); + D32(DCPLB_DATA13); + D32(DCPLB_DATA14); + D32(DCPLB_DATA15); + D32(DCPLB_DATA1); + D32(DCPLB_DATA2); + D32(DCPLB_DATA3); + D32(DCPLB_DATA4); + D32(DCPLB_DATA5); + D32(DCPLB_DATA6); + D32(DCPLB_DATA7); + D32(DCPLB_DATA8); + D32(DCPLB_DATA9); + D32(DCPLB_FAULT_ADDR); + D32(DCPLB_STATUS); + D32(DMEM_CONTROL); + D32(DTEST_COMMAND); + D32(DTEST_DATA0); + D32(DTEST_DATA1); + + D32(ICPLB_ADDR0); + D32(ICPLB_ADDR1); + D32(ICPLB_ADDR2); + D32(ICPLB_ADDR3); + D32(ICPLB_ADDR4); + D32(ICPLB_ADDR5); + D32(ICPLB_ADDR6); + D32(ICPLB_ADDR7); + D32(ICPLB_ADDR8); + D32(ICPLB_ADDR9); + D32(ICPLB_ADDR10); + D32(ICPLB_ADDR11); + D32(ICPLB_ADDR12); + D32(ICPLB_ADDR13); + D32(ICPLB_ADDR14); + D32(ICPLB_ADDR15); + D32(ICPLB_DATA0); + D32(ICPLB_DATA1); + D32(ICPLB_DATA2); + D32(ICPLB_DATA3); + D32(ICPLB_DATA4); + D32(ICPLB_DATA5); + D32(ICPLB_DATA6); + D32(ICPLB_DATA7); + D32(ICPLB_DATA8); + D32(ICPLB_DATA9); + D32(ICPLB_DATA10); + D32(ICPLB_DATA11); + D32(ICPLB_DATA12); + D32(ICPLB_DATA13); + D32(ICPLB_DATA14); + D32(ICPLB_DATA15); + D32(ICPLB_FAULT_ADDR); + D32(ICPLB_STATUS); + D32(IMEM_CONTROL); + if (!ANOMALY_05000481) { + D32(ITEST_COMMAND); + D32(ITEST_DATA0); + D32(ITEST_DATA1); + } + + parent = debugfs_create_dir("perf", top); + D32(PFCNTR0); + D32(PFCNTR1); + D32(PFCTL); + + parent = debugfs_create_dir("trace", top); + D32(TBUF); + D32(TBUFCTL); + D32(TBUFSTAT); + + parent = debugfs_create_dir("watchpoint", top); + D32(WPIACTL); + D32(WPIA0); + D32(WPIA1); + D32(WPIA2); + D32(WPIA3); + D32(WPIA4); + D32(WPIA5); + D32(WPIACNT0); + D32(WPIACNT1); + D32(WPIACNT2); + D32(WPIACNT3); + D32(WPIACNT4); + D32(WPIACNT5); + D32(WPDACTL); + D32(WPDA0); + D32(WPDA1); + D32(WPDACNT0); + D32(WPDACNT1); + D32(WPSTAT); + + /* System MMRs */ +#ifdef ATAPI_CONTROL + parent = debugfs_create_dir("atapi", top); + D16(ATAPI_CONTROL); + D16(ATAPI_DEV_ADDR); + D16(ATAPI_DEV_RXBUF); + D16(ATAPI_DEV_TXBUF); + D16(ATAPI_DMA_TFRCNT); + D16(ATAPI_INT_MASK); + D16(ATAPI_INT_STATUS); + D16(ATAPI_LINE_STATUS); + D16(ATAPI_MULTI_TIM_0); + D16(ATAPI_MULTI_TIM_1); + D16(ATAPI_MULTI_TIM_2); + D16(ATAPI_PIO_TFRCNT); + D16(ATAPI_PIO_TIM_0); + D16(ATAPI_PIO_TIM_1); + D16(ATAPI_REG_TIM_0); + D16(ATAPI_SM_STATE); + D16(ATAPI_STATUS); + D16(ATAPI_TERMINATE); + D16(ATAPI_UDMAOUT_TFRCNT); + D16(ATAPI_ULTRA_TIM_0); + D16(ATAPI_ULTRA_TIM_1); + D16(ATAPI_ULTRA_TIM_2); + D16(ATAPI_ULTRA_TIM_3); + D16(ATAPI_UMAIN_TFRCNT); + D16(ATAPI_XFER_LEN); +#endif + +#if defined(CAN_MC1) || defined(CAN0_MC1) || defined(CAN1_MC1) + parent = debugfs_create_dir("can", top); +# ifdef CAN_MC1 + bfin_debug_mmrs_can(parent, CAN_MC1, -1); +# endif +# ifdef CAN0_MC1 + CAN(0); +# endif +# ifdef CAN1_MC1 + CAN(1); +# endif +#endif + +#ifdef CNT_COMMAND + parent = debugfs_create_dir("counter", top); + D16(CNT_COMMAND); + D16(CNT_CONFIG); + D32(CNT_COUNTER); + D16(CNT_DEBOUNCE); + D16(CNT_IMASK); + D32(CNT_MAX); + D32(CNT_MIN); + D16(CNT_STATUS); +#endif + + parent = debugfs_create_dir("dmac", top); +#ifdef DMA_TC_CNT + D16(DMAC_TC_CNT); + D16(DMAC_TC_PER); +#endif +#ifdef DMAC0_TC_CNT + D16(DMAC0_TC_CNT); + D16(DMAC0_TC_PER); +#endif +#ifdef DMAC1_TC_CNT + D16(DMAC1_TC_CNT); + D16(DMAC1_TC_PER); +#endif +#ifdef DMAC1_PERIMUX + D16(DMAC1_PERIMUX); +#endif + +#ifdef __ADSPBF561__ + /* XXX: should rewrite the MMR map */ +# define DMA0_NEXT_DESC_PTR DMA2_0_NEXT_DESC_PTR +# define DMA1_NEXT_DESC_PTR DMA2_1_NEXT_DESC_PTR +# define DMA2_NEXT_DESC_PTR DMA2_2_NEXT_DESC_PTR +# define DMA3_NEXT_DESC_PTR DMA2_3_NEXT_DESC_PTR +# define DMA4_NEXT_DESC_PTR DMA2_4_NEXT_DESC_PTR +# define DMA5_NEXT_DESC_PTR DMA2_5_NEXT_DESC_PTR +# define DMA6_NEXT_DESC_PTR DMA2_6_NEXT_DESC_PTR +# define DMA7_NEXT_DESC_PTR DMA2_7_NEXT_DESC_PTR +# define DMA8_NEXT_DESC_PTR DMA2_8_NEXT_DESC_PTR +# define DMA9_NEXT_DESC_PTR DMA2_9_NEXT_DESC_PTR +# define DMA10_NEXT_DESC_PTR DMA2_10_NEXT_DESC_PTR +# define DMA11_NEXT_DESC_PTR DMA2_11_NEXT_DESC_PTR +# define DMA12_NEXT_DESC_PTR DMA1_0_NEXT_DESC_PTR +# define DMA13_NEXT_DESC_PTR DMA1_1_NEXT_DESC_PTR +# define DMA14_NEXT_DESC_PTR DMA1_2_NEXT_DESC_PTR +# define DMA15_NEXT_DESC_PTR DMA1_3_NEXT_DESC_PTR +# define DMA16_NEXT_DESC_PTR DMA1_4_NEXT_DESC_PTR +# define DMA17_NEXT_DESC_PTR DMA1_5_NEXT_DESC_PTR +# define DMA18_NEXT_DESC_PTR DMA1_6_NEXT_DESC_PTR +# define DMA19_NEXT_DESC_PTR DMA1_7_NEXT_DESC_PTR +# define DMA20_NEXT_DESC_PTR DMA1_8_NEXT_DESC_PTR +# define DMA21_NEXT_DESC_PTR DMA1_9_NEXT_DESC_PTR +# define DMA22_NEXT_DESC_PTR DMA1_10_NEXT_DESC_PTR +# define DMA23_NEXT_DESC_PTR DMA1_11_NEXT_DESC_PTR +#endif + parent = debugfs_create_dir("dma", top); + DMA(0); + DMA(1); + DMA(1); + DMA(2); + DMA(3); + DMA(4); + DMA(5); + DMA(6); + DMA(7); +#ifdef DMA8_NEXT_DESC_PTR + DMA(8); + DMA(9); + DMA(10); + DMA(11); +#endif +#ifdef DMA12_NEXT_DESC_PTR + DMA(12); + DMA(13); + DMA(14); + DMA(15); + DMA(16); + DMA(17); + DMA(18); + DMA(19); +#endif +#ifdef DMA20_NEXT_DESC_PTR + DMA(20); + DMA(21); + DMA(22); + DMA(23); +#endif + + parent = debugfs_create_dir("ebiu_amc", top); + D32(EBIU_AMBCTL0); + D32(EBIU_AMBCTL1); + D16(EBIU_AMGCTL); +#ifdef EBIU_MBSCTL + D16(EBIU_MBSCTL); + D32(EBIU_ARBSTAT); + D32(EBIU_MODE); + D16(EBIU_FCTL); +#endif + +#ifdef EBIU_SDGCTL + parent = debugfs_create_dir("ebiu_sdram", top); +# ifdef __ADSPBF561__ + D32(EBIU_SDBCTL); +# else + D16(EBIU_SDBCTL); +# endif + D32(EBIU_SDGCTL); + D16(EBIU_SDRRC); + D16(EBIU_SDSTAT); +#endif + +#ifdef EBIU_DDRACCT + parent = debugfs_create_dir("ebiu_ddr", top); + D32(EBIU_DDRACCT); + D32(EBIU_DDRARCT); + D32(EBIU_DDRBRC0); + D32(EBIU_DDRBRC1); + D32(EBIU_DDRBRC2); + D32(EBIU_DDRBRC3); + D32(EBIU_DDRBRC4); + D32(EBIU_DDRBRC5); + D32(EBIU_DDRBRC6); + D32(EBIU_DDRBRC7); + D32(EBIU_DDRBWC0); + D32(EBIU_DDRBWC1); + D32(EBIU_DDRBWC2); + D32(EBIU_DDRBWC3); + D32(EBIU_DDRBWC4); + D32(EBIU_DDRBWC5); + D32(EBIU_DDRBWC6); + D32(EBIU_DDRBWC7); + D32(EBIU_DDRCTL0); + D32(EBIU_DDRCTL1); + D32(EBIU_DDRCTL2); + D32(EBIU_DDRCTL3); + D32(EBIU_DDRGC0); + D32(EBIU_DDRGC1); + D32(EBIU_DDRGC2); + D32(EBIU_DDRGC3); + D32(EBIU_DDRMCCL); + D32(EBIU_DDRMCEN); + D32(EBIU_DDRQUE); + D32(EBIU_DDRTACT); + D32(EBIU_ERRADD); + D16(EBIU_ERRMST); + D16(EBIU_RSTCTL); +#endif + +#ifdef EMAC_ADDRHI + parent = debugfs_create_dir("emac", top); + D32(EMAC_ADDRHI); + D32(EMAC_ADDRLO); + D32(EMAC_FLC); + D32(EMAC_HASHHI); + D32(EMAC_HASHLO); + D32(EMAC_MMC_CTL); + D32(EMAC_MMC_RIRQE); + D32(EMAC_MMC_RIRQS); + D32(EMAC_MMC_TIRQE); + D32(EMAC_MMC_TIRQS); + D32(EMAC_OPMODE); + D32(EMAC_RXC_ALIGN); + D32(EMAC_RXC_ALLFRM); + D32(EMAC_RXC_ALLOCT); + D32(EMAC_RXC_BROAD); + D32(EMAC_RXC_DMAOVF); + D32(EMAC_RXC_EQ64); + D32(EMAC_RXC_FCS); + D32(EMAC_RXC_GE1024); + D32(EMAC_RXC_LNERRI); + D32(EMAC_RXC_LNERRO); + D32(EMAC_RXC_LONG); + D32(EMAC_RXC_LT1024); + D32(EMAC_RXC_LT128); + D32(EMAC_RXC_LT256); + D32(EMAC_RXC_LT512); + D32(EMAC_RXC_MACCTL); + D32(EMAC_RXC_MULTI); + D32(EMAC_RXC_OCTET); + D32(EMAC_RXC_OK); + D32(EMAC_RXC_OPCODE); + D32(EMAC_RXC_PAUSE); + D32(EMAC_RXC_SHORT); + D32(EMAC_RXC_TYPED); + D32(EMAC_RXC_UNICST); + D32(EMAC_RX_IRQE); + D32(EMAC_RX_STAT); + D32(EMAC_RX_STKY); + D32(EMAC_STAADD); + D32(EMAC_STADAT); + D32(EMAC_SYSCTL); + D32(EMAC_SYSTAT); + D32(EMAC_TXC_1COL); + D32(EMAC_TXC_ABORT); + D32(EMAC_TXC_ALLFRM); + D32(EMAC_TXC_ALLOCT); + D32(EMAC_TXC_BROAD); + D32(EMAC_TXC_CRSERR); + D32(EMAC_TXC_DEFER); + D32(EMAC_TXC_DMAUND); + D32(EMAC_TXC_EQ64); + D32(EMAC_TXC_GE1024); + D32(EMAC_TXC_GT1COL); + D32(EMAC_TXC_LATECL); + D32(EMAC_TXC_LT1024); + D32(EMAC_TXC_LT128); + D32(EMAC_TXC_LT256); + D32(EMAC_TXC_LT512); + D32(EMAC_TXC_MACCTL); + D32(EMAC_TXC_MULTI); + D32(EMAC_TXC_OCTET); + D32(EMAC_TXC_OK); + D32(EMAC_TXC_UNICST); + D32(EMAC_TXC_XS_COL); + D32(EMAC_TXC_XS_DFR); + D32(EMAC_TX_IRQE); + D32(EMAC_TX_STAT); + D32(EMAC_TX_STKY); + D32(EMAC_VLAN1); + D32(EMAC_VLAN2); + D32(EMAC_WKUP_CTL); + D32(EMAC_WKUP_FFCMD); + D32(EMAC_WKUP_FFCRC0); + D32(EMAC_WKUP_FFCRC1); + D32(EMAC_WKUP_FFMSK0); + D32(EMAC_WKUP_FFMSK1); + D32(EMAC_WKUP_FFMSK2); + D32(EMAC_WKUP_FFMSK3); + D32(EMAC_WKUP_FFOFF); +# ifdef EMAC_PTP_ACCR + D32(EMAC_PTP_ACCR); + D32(EMAC_PTP_ADDEND); + D32(EMAC_PTP_ALARMHI); + D32(EMAC_PTP_ALARMLO); + D16(EMAC_PTP_CTL); + D32(EMAC_PTP_FOFF); + D32(EMAC_PTP_FV1); + D32(EMAC_PTP_FV2); + D32(EMAC_PTP_FV3); + D16(EMAC_PTP_ID_OFF); + D32(EMAC_PTP_ID_SNAP); + D16(EMAC_PTP_IE); + D16(EMAC_PTP_ISTAT); + D32(EMAC_PTP_OFFSET); + D32(EMAC_PTP_PPS_PERIOD); + D32(EMAC_PTP_PPS_STARTHI); + D32(EMAC_PTP_PPS_STARTLO); + D32(EMAC_PTP_RXSNAPHI); + D32(EMAC_PTP_RXSNAPLO); + D32(EMAC_PTP_TIMEHI); + D32(EMAC_PTP_TIMELO); + D32(EMAC_PTP_TXSNAPHI); + D32(EMAC_PTP_TXSNAPLO); +# endif +#endif + +#if defined(EPPI0_STATUS) || defined(EPPI1_STATUS) || defined(EPPI2_STATUS) + parent = debugfs_create_dir("eppi", top); +# ifdef EPPI0_STATUS + EPPI(0); +# endif +# ifdef EPPI1_STATUS + EPPI(1); +# endif +# ifdef EPPI2_STATUS + EPPI(2); +# endif +#endif + + parent = debugfs_create_dir("gptimer", top); +#ifdef TIMER_DISABLE + D16(TIMER_DISABLE); + D16(TIMER_ENABLE); + D32(TIMER_STATUS); +#endif +#ifdef TIMER_DISABLE0 + D16(TIMER_DISABLE0); + D16(TIMER_ENABLE0); + D32(TIMER_STATUS0); +#endif +#ifdef TIMER_DISABLE1 + D16(TIMER_DISABLE1); + D16(TIMER_ENABLE1); + D32(TIMER_STATUS1); +#endif + /* XXX: Should convert BF561 MMR names */ +#ifdef TMRS4_DISABLE + D16(TMRS4_DISABLE); + D16(TMRS4_ENABLE); + D32(TMRS4_STATUS); + D16(TMRS8_DISABLE); + D16(TMRS8_ENABLE); + D32(TMRS8_STATUS); +#endif + GPTIMER(0); + GPTIMER(1); + GPTIMER(2); +#ifdef TIMER3_CONFIG + GPTIMER(3); + GPTIMER(4); + GPTIMER(5); + GPTIMER(6); + GPTIMER(7); +#endif +#ifdef TIMER8_CONFIG + GPTIMER(8); + GPTIMER(9); + GPTIMER(10); +#endif +#ifdef TIMER11_CONFIG + GPTIMER(11); +#endif + +#ifdef HMDMA0_CONTROL + parent = debugfs_create_dir("hmdma", top); + HMDMA(0); + HMDMA(1); +#endif + +#ifdef HOST_CONTROL + parent = debugfs_create_dir("hostdp", top); + D16(HOST_CONTROL); + D16(HOST_STATUS); + D16(HOST_TIMEOUT); +#endif + +#ifdef IMDMA_S0_CONFIG + parent = debugfs_create_dir("imdma", top); + IMDMA(0); + IMDMA(1); +#endif + +#ifdef KPAD_CTL + parent = debugfs_create_dir("keypad", top); + D16(KPAD_CTL); + D16(KPAD_PRESCALE); + D16(KPAD_MSEL); + D16(KPAD_ROWCOL); + D16(KPAD_STAT); + D16(KPAD_SOFTEVAL); +#endif + + parent = debugfs_create_dir("mdma", top); + MDMA(0); + MDMA(1); +#ifdef MDMA_D2_CONFIG + MDMA(2); + MDMA(3); +#endif + +#ifdef MXVR_CONFIG + parent = debugfs_create_dir("mxvr", top); + D16(MXVR_CONFIG); +# ifdef MXVR_PLL_CTL_0 + D32(MXVR_PLL_CTL_0); +# endif + D32(MXVR_STATE_0); + D32(MXVR_STATE_1); + D32(MXVR_INT_STAT_0); + D32(MXVR_INT_STAT_1); + D32(MXVR_INT_EN_0); + D32(MXVR_INT_EN_1); + D16(MXVR_POSITION); + D16(MXVR_MAX_POSITION); + D16(MXVR_DELAY); + D16(MXVR_MAX_DELAY); + D32(MXVR_LADDR); + D16(MXVR_GADDR); + D32(MXVR_AADDR); + D32(MXVR_ALLOC_0); + D32(MXVR_ALLOC_1); + D32(MXVR_ALLOC_2); + D32(MXVR_ALLOC_3); + D32(MXVR_ALLOC_4); + D32(MXVR_ALLOC_5); + D32(MXVR_ALLOC_6); + D32(MXVR_ALLOC_7); + D32(MXVR_ALLOC_8); + D32(MXVR_ALLOC_9); + D32(MXVR_ALLOC_10); + D32(MXVR_ALLOC_11); + D32(MXVR_ALLOC_12); + D32(MXVR_ALLOC_13); + D32(MXVR_ALLOC_14); + D32(MXVR_SYNC_LCHAN_0); + D32(MXVR_SYNC_LCHAN_1); + D32(MXVR_SYNC_LCHAN_2); + D32(MXVR_SYNC_LCHAN_3); + D32(MXVR_SYNC_LCHAN_4); + D32(MXVR_SYNC_LCHAN_5); + D32(MXVR_SYNC_LCHAN_6); + D32(MXVR_SYNC_LCHAN_7); + D32(MXVR_DMA0_CONFIG); + D32(MXVR_DMA0_START_ADDR); + D16(MXVR_DMA0_COUNT); + D32(MXVR_DMA0_CURR_ADDR); + D16(MXVR_DMA0_CURR_COUNT); + D32(MXVR_DMA1_CONFIG); + D32(MXVR_DMA1_START_ADDR); + D16(MXVR_DMA1_COUNT); + D32(MXVR_DMA1_CURR_ADDR); + D16(MXVR_DMA1_CURR_COUNT); + D32(MXVR_DMA2_CONFIG); + D32(MXVR_DMA2_START_ADDR); + D16(MXVR_DMA2_COUNT); + D32(MXVR_DMA2_CURR_ADDR); + D16(MXVR_DMA2_CURR_COUNT); + D32(MXVR_DMA3_CONFIG); + D32(MXVR_DMA3_START_ADDR); + D16(MXVR_DMA3_COUNT); + D32(MXVR_DMA3_CURR_ADDR); + D16(MXVR_DMA3_CURR_COUNT); + D32(MXVR_DMA4_CONFIG); + D32(MXVR_DMA4_START_ADDR); + D16(MXVR_DMA4_COUNT); + D32(MXVR_DMA4_CURR_ADDR); + D16(MXVR_DMA4_CURR_COUNT); + D32(MXVR_DMA5_CONFIG); + D32(MXVR_DMA5_START_ADDR); + D16(MXVR_DMA5_COUNT); + D32(MXVR_DMA5_CURR_ADDR); + D16(MXVR_DMA5_CURR_COUNT); + D32(MXVR_DMA6_CONFIG); + D32(MXVR_DMA6_START_ADDR); + D16(MXVR_DMA6_COUNT); + D32(MXVR_DMA6_CURR_ADDR); + D16(MXVR_DMA6_CURR_COUNT); + D32(MXVR_DMA7_CONFIG); + D32(MXVR_DMA7_START_ADDR); + D16(MXVR_DMA7_COUNT); + D32(MXVR_DMA7_CURR_ADDR); + D16(MXVR_DMA7_CURR_COUNT); + D16(MXVR_AP_CTL); + D32(MXVR_APRB_START_ADDR); + D32(MXVR_APRB_CURR_ADDR); + D32(MXVR_APTB_START_ADDR); + D32(MXVR_APTB_CURR_ADDR); + D32(MXVR_CM_CTL); + D32(MXVR_CMRB_START_ADDR); + D32(MXVR_CMRB_CURR_ADDR); + D32(MXVR_CMTB_START_ADDR); + D32(MXVR_CMTB_CURR_ADDR); + D32(MXVR_RRDB_START_ADDR); + D32(MXVR_RRDB_CURR_ADDR); + D32(MXVR_PAT_DATA_0); + D32(MXVR_PAT_EN_0); + D32(MXVR_PAT_DATA_1); + D32(MXVR_PAT_EN_1); + D16(MXVR_FRAME_CNT_0); + D16(MXVR_FRAME_CNT_1); + D32(MXVR_ROUTING_0); + D32(MXVR_ROUTING_1); + D32(MXVR_ROUTING_2); + D32(MXVR_ROUTING_3); + D32(MXVR_ROUTING_4); + D32(MXVR_ROUTING_5); + D32(MXVR_ROUTING_6); + D32(MXVR_ROUTING_7); + D32(MXVR_ROUTING_8); + D32(MXVR_ROUTING_9); + D32(MXVR_ROUTING_10); + D32(MXVR_ROUTING_11); + D32(MXVR_ROUTING_12); + D32(MXVR_ROUTING_13); + D32(MXVR_ROUTING_14); +# ifdef MXVR_PLL_CTL_1 + D32(MXVR_PLL_CTL_1); +# endif + D16(MXVR_BLOCK_CNT); +# ifdef MXVR_CLK_CTL + D32(MXVR_CLK_CTL); +# endif +# ifdef MXVR_CDRPLL_CTL + D32(MXVR_CDRPLL_CTL); +# endif +# ifdef MXVR_FMPLL_CTL + D32(MXVR_FMPLL_CTL); +# endif +# ifdef MXVR_PIN_CTL + D16(MXVR_PIN_CTL); +# endif +# ifdef MXVR_SCLK_CNT + D16(MXVR_SCLK_CNT); +# endif +#endif + +#ifdef NFC_ADDR + parent = debugfs_create_dir("nfc", top); + D_WO(NFC_ADDR, 16); + D_WO(NFC_CMD, 16); + D_RO(NFC_COUNT, 16); + D16(NFC_CTL); + D_WO(NFC_DATA_RD, 16); + D_WO(NFC_DATA_WR, 16); + D_RO(NFC_ECC0, 16); + D_RO(NFC_ECC1, 16); + D_RO(NFC_ECC2, 16); + D_RO(NFC_ECC3, 16); + D16(NFC_IRQMASK); + D16(NFC_IRQSTAT); + D_WO(NFC_PGCTL, 16); + D_RO(NFC_READ, 16); + D16(NFC_RST); + D_RO(NFC_STAT, 16); +#endif + +#ifdef OTP_CONTROL + parent = debugfs_create_dir("otp", top); + D16(OTP_CONTROL); + D16(OTP_BEN); + D16(OTP_STATUS); + D32(OTP_TIMING); + D32(OTP_DATA0); + D32(OTP_DATA1); + D32(OTP_DATA2); + D32(OTP_DATA3); +#endif + +#ifdef PIXC_CTL + parent = debugfs_create_dir("pixc", top); + D16(PIXC_CTL); + D16(PIXC_PPL); + D16(PIXC_LPF); + D16(PIXC_AHSTART); + D16(PIXC_AHEND); + D16(PIXC_AVSTART); + D16(PIXC_AVEND); + D16(PIXC_ATRANSP); + D16(PIXC_BHSTART); + D16(PIXC_BHEND); + D16(PIXC_BVSTART); + D16(PIXC_BVEND); + D16(PIXC_BTRANSP); + D16(PIXC_INTRSTAT); + D32(PIXC_RYCON); + D32(PIXC_GUCON); + D32(PIXC_BVCON); + D32(PIXC_CCBIAS); + D32(PIXC_TC); +#endif + + parent = debugfs_create_dir("pll", top); + D16(PLL_CTL); + D16(PLL_DIV); + D16(PLL_LOCKCNT); + D16(PLL_STAT); + D16(VR_CTL); + D32(CHIPID); /* it's part of this hardware block */ + +#if defined(PPI_STATUS) || defined(PPI0_STATUS) || defined(PPI1_STATUS) + parent = debugfs_create_dir("ppi", top); +# ifdef PPI_STATUS + bfin_debug_mmrs_ppi(parent, PPI_STATUS, -1); +# endif +# ifdef PPI0_STATUS + PPI(0); +# endif +# ifdef PPI1_STATUS + PPI(1); +# endif +#endif + +#ifdef PWM_CTRL + parent = debugfs_create_dir("pwm", top); + D16(PWM_CTRL); + D16(PWM_STAT); + D16(PWM_TM); + D16(PWM_DT); + D16(PWM_GATE); + D16(PWM_CHA); + D16(PWM_CHB); + D16(PWM_CHC); + D16(PWM_SEG); + D16(PWM_SYNCWT); + D16(PWM_CHAL); + D16(PWM_CHBL); + D16(PWM_CHCL); + D16(PWM_LSI); + D16(PWM_STAT2); +#endif + +#ifdef RSI_CONFIG + parent = debugfs_create_dir("rsi", top); + D32(RSI_ARGUMENT); + D16(RSI_CEATA_CONTROL); + D16(RSI_CLK_CONTROL); + D16(RSI_COMMAND); + D16(RSI_CONFIG); + D16(RSI_DATA_CNT); + D16(RSI_DATA_CONTROL); + D16(RSI_DATA_LGTH); + D32(RSI_DATA_TIMER); + D16(RSI_EMASK); + D16(RSI_ESTAT); + D32(RSI_FIFO); + D16(RSI_FIFO_CNT); + D32(RSI_MASK0); + D32(RSI_MASK1); + D16(RSI_PID0); + D16(RSI_PID1); + D16(RSI_PID2); + D16(RSI_PID3); + D16(RSI_PWR_CONTROL); + D16(RSI_RD_WAIT_EN); + D32(RSI_RESPONSE0); + D32(RSI_RESPONSE1); + D32(RSI_RESPONSE2); + D32(RSI_RESPONSE3); + D16(RSI_RESP_CMD); + D32(RSI_STATUS); + D_WO(RSI_STATUSCL, 16); +#endif + +#ifdef RTC_ALARM + parent = debugfs_create_dir("rtc", top); + D32(RTC_ALARM); + D16(RTC_ICTL); + D16(RTC_ISTAT); + D16(RTC_PREN); + D32(RTC_STAT); + D16(RTC_SWCNT); +#endif + +#ifdef SDH_CFG + parent = debugfs_create_dir("sdh", top); + D32(SDH_ARGUMENT); + D16(SDH_CFG); + D16(SDH_CLK_CTL); + D16(SDH_COMMAND); + D_RO(SDH_DATA_CNT, 16); + D16(SDH_DATA_CTL); + D16(SDH_DATA_LGTH); + D32(SDH_DATA_TIMER); + D16(SDH_E_MASK); + D16(SDH_E_STATUS); + D32(SDH_FIFO); + D_RO(SDH_FIFO_CNT, 16); + D32(SDH_MASK0); + D32(SDH_MASK1); + D_RO(SDH_PID0, 16); + D_RO(SDH_PID1, 16); + D_RO(SDH_PID2, 16); + D_RO(SDH_PID3, 16); + D_RO(SDH_PID4, 16); + D_RO(SDH_PID5, 16); + D_RO(SDH_PID6, 16); + D_RO(SDH_PID7, 16); + D16(SDH_PWR_CTL); + D16(SDH_RD_WAIT_EN); + D_RO(SDH_RESPONSE0, 32); + D_RO(SDH_RESPONSE1, 32); + D_RO(SDH_RESPONSE2, 32); + D_RO(SDH_RESPONSE3, 32); + D_RO(SDH_RESP_CMD, 16); + D_RO(SDH_STATUS, 32); + D_WO(SDH_STATUS_CLR, 16); +#endif + +#ifdef SECURE_CONTROL + parent = debugfs_create_dir("security", top); + D16(SECURE_CONTROL); + D16(SECURE_STATUS); + D32(SECURE_SYSSWT); +#endif + + parent = debugfs_create_dir("sic", top); + D16(SWRST); + D16(SYSCR); + D16(SIC_RVECT); + D32(SIC_IAR0); + D32(SIC_IAR1); + D32(SIC_IAR2); +#ifdef SIC_IAR3 + D32(SIC_IAR3); +#endif +#ifdef SIC_IAR4 + D32(SIC_IAR4); + D32(SIC_IAR5); + D32(SIC_IAR6); +#endif +#ifdef SIC_IAR7 + D32(SIC_IAR7); +#endif +#ifdef SIC_IAR8 + D32(SIC_IAR8); + D32(SIC_IAR9); + D32(SIC_IAR10); + D32(SIC_IAR11); +#endif +#ifdef SIC_IMASK + D32(SIC_IMASK); + D32(SIC_ISR); + D32(SIC_IWR); +#endif +#ifdef SIC_IMASK0 + D32(SIC_IMASK0); + D32(SIC_IMASK1); + D32(SIC_ISR0); + D32(SIC_ISR1); + D32(SIC_IWR0); + D32(SIC_IWR1); +#endif +#ifdef SIC_IMASK2 + D32(SIC_IMASK2); + D32(SIC_ISR2); + D32(SIC_IWR2); +#endif +#ifdef SICB_RVECT + D16(SICB_SWRST); + D16(SICB_SYSCR); + D16(SICB_RVECT); + D32(SICB_IAR0); + D32(SICB_IAR1); + D32(SICB_IAR2); + D32(SICB_IAR3); + D32(SICB_IAR4); + D32(SICB_IAR5); + D32(SICB_IAR6); + D32(SICB_IAR7); + D32(SICB_IMASK0); + D32(SICB_IMASK1); + D32(SICB_ISR0); + D32(SICB_ISR1); + D32(SICB_IWR0); + D32(SICB_IWR1); +#endif + + parent = debugfs_create_dir("spi", top); +#ifdef SPI0_REGBASE + SPI(0); +#endif +#ifdef SPI1_REGBASE + SPI(1); +#endif +#ifdef SPI2_REGBASE + SPI(2); +#endif + + parent = debugfs_create_dir("sport", top); +#ifdef SPORT0_STAT + SPORT(0); +#endif +#ifdef SPORT1_STAT + SPORT(1); +#endif +#ifdef SPORT2_STAT + SPORT(2); +#endif +#ifdef SPORT3_STAT + SPORT(3); +#endif + +#if defined(TWI_CLKDIV) || defined(TWI0_CLKDIV) || defined(TWI1_CLKDIV) + parent = debugfs_create_dir("twi", top); +# ifdef TWI_CLKDIV + bfin_debug_mmrs_twi(parent, TWI_CLKDIV, -1); +# endif +# ifdef TWI0_CLKDIV + TWI(0); +# endif +# ifdef TWI1_CLKDIV + TWI(1); +# endif +#endif + + parent = debugfs_create_dir("uart", top); +#ifdef BFIN_UART_DLL + bfin_debug_mmrs_uart(parent, BFIN_UART_DLL, -1); +#endif +#ifdef UART0_DLL + UART(0); +#endif +#ifdef UART1_DLL + UART(1); +#endif +#ifdef UART2_DLL + UART(2); +#endif +#ifdef UART3_DLL + UART(3); +#endif + +#ifdef USB_FADDR + parent = debugfs_create_dir("usb", top); + D16(USB_FADDR); + D16(USB_POWER); + D16(USB_INTRTX); + D16(USB_INTRRX); + D16(USB_INTRTXE); + D16(USB_INTRRXE); + D16(USB_INTRUSB); + D16(USB_INTRUSBE); + D16(USB_FRAME); + D16(USB_INDEX); + D16(USB_TESTMODE); + D16(USB_GLOBINTR); + D16(USB_GLOBAL_CTL); + D16(USB_TX_MAX_PACKET); + D16(USB_CSR0); + D16(USB_TXCSR); + D16(USB_RX_MAX_PACKET); + D16(USB_RXCSR); + D16(USB_COUNT0); + D16(USB_RXCOUNT); + D16(USB_TXTYPE); + D16(USB_NAKLIMIT0); + D16(USB_TXINTERVAL); + D16(USB_RXTYPE); + D16(USB_RXINTERVAL); + D16(USB_TXCOUNT); + D16(USB_EP0_FIFO); + D16(USB_EP1_FIFO); + D16(USB_EP2_FIFO); + D16(USB_EP3_FIFO); + D16(USB_EP4_FIFO); + D16(USB_EP5_FIFO); + D16(USB_EP6_FIFO); + D16(USB_EP7_FIFO); + D16(USB_OTG_DEV_CTL); + D16(USB_OTG_VBUS_IRQ); + D16(USB_OTG_VBUS_MASK); + D16(USB_LINKINFO); + D16(USB_VPLEN); + D16(USB_HS_EOF1); + D16(USB_FS_EOF1); + D16(USB_LS_EOF1); + D16(USB_APHY_CNTRL); + D16(USB_APHY_CALIB); + D16(USB_APHY_CNTRL2); + D16(USB_PHY_TEST); + D16(USB_PLLOSC_CTRL); + D16(USB_SRP_CLKDIV); + D16(USB_EP_NI0_TXMAXP); + D16(USB_EP_NI0_TXCSR); + D16(USB_EP_NI0_RXMAXP); + D16(USB_EP_NI0_RXCSR); + D16(USB_EP_NI0_RXCOUNT); + D16(USB_EP_NI0_TXTYPE); + D16(USB_EP_NI0_TXINTERVAL); + D16(USB_EP_NI0_RXTYPE); + D16(USB_EP_NI0_RXINTERVAL); + D16(USB_EP_NI0_TXCOUNT); + D16(USB_EP_NI1_TXMAXP); + D16(USB_EP_NI1_TXCSR); + D16(USB_EP_NI1_RXMAXP); + D16(USB_EP_NI1_RXCSR); + D16(USB_EP_NI1_RXCOUNT); + D16(USB_EP_NI1_TXTYPE); + D16(USB_EP_NI1_TXINTERVAL); + D16(USB_EP_NI1_RXTYPE); + D16(USB_EP_NI1_RXINTERVAL); + D16(USB_EP_NI1_TXCOUNT); + D16(USB_EP_NI2_TXMAXP); + D16(USB_EP_NI2_TXCSR); + D16(USB_EP_NI2_RXMAXP); + D16(USB_EP_NI2_RXCSR); + D16(USB_EP_NI2_RXCOUNT); + D16(USB_EP_NI2_TXTYPE); + D16(USB_EP_NI2_TXINTERVAL); + D16(USB_EP_NI2_RXTYPE); + D16(USB_EP_NI2_RXINTERVAL); + D16(USB_EP_NI2_TXCOUNT); + D16(USB_EP_NI3_TXMAXP); + D16(USB_EP_NI3_TXCSR); + D16(USB_EP_NI3_RXMAXP); + D16(USB_EP_NI3_RXCSR); + D16(USB_EP_NI3_RXCOUNT); + D16(USB_EP_NI3_TXTYPE); + D16(USB_EP_NI3_TXINTERVAL); + D16(USB_EP_NI3_RXTYPE); + D16(USB_EP_NI3_RXINTERVAL); + D16(USB_EP_NI3_TXCOUNT); + D16(USB_EP_NI4_TXMAXP); + D16(USB_EP_NI4_TXCSR); + D16(USB_EP_NI4_RXMAXP); + D16(USB_EP_NI4_RXCSR); + D16(USB_EP_NI4_RXCOUNT); + D16(USB_EP_NI4_TXTYPE); + D16(USB_EP_NI4_TXINTERVAL); + D16(USB_EP_NI4_RXTYPE); + D16(USB_EP_NI4_RXINTERVAL); + D16(USB_EP_NI4_TXCOUNT); + D16(USB_EP_NI5_TXMAXP); + D16(USB_EP_NI5_TXCSR); + D16(USB_EP_NI5_RXMAXP); + D16(USB_EP_NI5_RXCSR); + D16(USB_EP_NI5_RXCOUNT); + D16(USB_EP_NI5_TXTYPE); + D16(USB_EP_NI5_TXINTERVAL); + D16(USB_EP_NI5_RXTYPE); + D16(USB_EP_NI5_RXINTERVAL); + D16(USB_EP_NI5_TXCOUNT); + D16(USB_EP_NI6_TXMAXP); + D16(USB_EP_NI6_TXCSR); + D16(USB_EP_NI6_RXMAXP); + D16(USB_EP_NI6_RXCSR); + D16(USB_EP_NI6_RXCOUNT); + D16(USB_EP_NI6_TXTYPE); + D16(USB_EP_NI6_TXINTERVAL); + D16(USB_EP_NI6_RXTYPE); + D16(USB_EP_NI6_RXINTERVAL); + D16(USB_EP_NI6_TXCOUNT); + D16(USB_EP_NI7_TXMAXP); + D16(USB_EP_NI7_TXCSR); + D16(USB_EP_NI7_RXMAXP); + D16(USB_EP_NI7_RXCSR); + D16(USB_EP_NI7_RXCOUNT); + D16(USB_EP_NI7_TXTYPE); + D16(USB_EP_NI7_TXINTERVAL); + D16(USB_EP_NI7_RXTYPE); + D16(USB_EP_NI7_RXINTERVAL); + D16(USB_EP_NI7_TXCOUNT); + D16(USB_DMA_INTERRUPT); + D16(USB_DMA0CONTROL); + D16(USB_DMA0ADDRLOW); + D16(USB_DMA0ADDRHIGH); + D16(USB_DMA0COUNTLOW); + D16(USB_DMA0COUNTHIGH); + D16(USB_DMA1CONTROL); + D16(USB_DMA1ADDRLOW); + D16(USB_DMA1ADDRHIGH); + D16(USB_DMA1COUNTLOW); + D16(USB_DMA1COUNTHIGH); + D16(USB_DMA2CONTROL); + D16(USB_DMA2ADDRLOW); + D16(USB_DMA2ADDRHIGH); + D16(USB_DMA2COUNTLOW); + D16(USB_DMA2COUNTHIGH); + D16(USB_DMA3CONTROL); + D16(USB_DMA3ADDRLOW); + D16(USB_DMA3ADDRHIGH); + D16(USB_DMA3COUNTLOW); + D16(USB_DMA3COUNTHIGH); + D16(USB_DMA4CONTROL); + D16(USB_DMA4ADDRLOW); + D16(USB_DMA4ADDRHIGH); + D16(USB_DMA4COUNTLOW); + D16(USB_DMA4COUNTHIGH); + D16(USB_DMA5CONTROL); + D16(USB_DMA5ADDRLOW); + D16(USB_DMA5ADDRHIGH); + D16(USB_DMA5COUNTLOW); + D16(USB_DMA5COUNTHIGH); + D16(USB_DMA6CONTROL); + D16(USB_DMA6ADDRLOW); + D16(USB_DMA6ADDRHIGH); + D16(USB_DMA6COUNTLOW); + D16(USB_DMA6COUNTHIGH); + D16(USB_DMA7CONTROL); + D16(USB_DMA7ADDRLOW); + D16(USB_DMA7ADDRHIGH); + D16(USB_DMA7COUNTLOW); + D16(USB_DMA7COUNTHIGH); +#endif + +#ifdef WDOG_CNT + parent = debugfs_create_dir("watchdog", top); + D32(WDOG_CNT); + D16(WDOG_CTL); + D32(WDOG_STAT); +#endif +#ifdef WDOGA_CNT + parent = debugfs_create_dir("watchdog", top); + D32(WDOGA_CNT); + D16(WDOGA_CTL); + D32(WDOGA_STAT); + D32(WDOGB_CNT); + D16(WDOGB_CTL); + D32(WDOGB_STAT); +#endif + + /* BF533 glue */ +#ifdef FIO_FLAG_D +#define PORTFIO FIO_FLAG_D +#endif + /* BF561 glue */ +#ifdef FIO0_FLAG_D +#define PORTFIO FIO0_FLAG_D +#endif +#ifdef FIO1_FLAG_D +#define PORTGIO FIO1_FLAG_D +#endif +#ifdef FIO2_FLAG_D +#define PORTHIO FIO2_FLAG_D +#endif + parent = debugfs_create_dir("port", top); +#ifdef PORTFIO + PORT(PORTFIO, 'F'); +#endif +#ifdef PORTGIO + PORT(PORTGIO, 'G'); +#endif +#ifdef PORTHIO + PORT(PORTHIO, 'H'); +#endif + +#ifdef __ADSPBF51x__ + D16(PORTF_FER); + D16(PORTF_DRIVE); + D16(PORTF_HYSTERESIS); + D16(PORTF_MUX); + + D16(PORTG_FER); + D16(PORTG_DRIVE); + D16(PORTG_HYSTERESIS); + D16(PORTG_MUX); + + D16(PORTH_FER); + D16(PORTH_DRIVE); + D16(PORTH_HYSTERESIS); + D16(PORTH_MUX); + + D16(MISCPORT_DRIVE); + D16(MISCPORT_HYSTERESIS); +#endif /* BF51x */ + +#ifdef __ADSPBF52x__ + D16(PORTF_FER); + D16(PORTF_DRIVE); + D16(PORTF_HYSTERESIS); + D16(PORTF_MUX); + D16(PORTF_SLEW); + + D16(PORTG_FER); + D16(PORTG_DRIVE); + D16(PORTG_HYSTERESIS); + D16(PORTG_MUX); + D16(PORTG_SLEW); + + D16(PORTH_FER); + D16(PORTH_DRIVE); + D16(PORTH_HYSTERESIS); + D16(PORTH_MUX); + D16(PORTH_SLEW); + + D16(MISCPORT_DRIVE); + D16(MISCPORT_HYSTERESIS); + D16(MISCPORT_SLEW); +#endif /* BF52x */ + +#ifdef BF537_FAMILY + D16(PORTF_FER); + D16(PORTG_FER); + D16(PORTH_FER); + D16(PORT_MUX); +#endif /* BF534 BF536 BF537 */ + +#ifdef BF538_FAMILY + D16(PORTCIO_FER); + D16(PORTCIO); + D16(PORTCIO_CLEAR); + D16(PORTCIO_SET); + D16(PORTCIO_TOGGLE); + D16(PORTCIO_DIR); + D16(PORTCIO_INEN); + + D16(PORTDIO); + D16(PORTDIO_CLEAR); + D16(PORTDIO_DIR); + D16(PORTDIO_FER); + D16(PORTDIO_INEN); + D16(PORTDIO_SET); + D16(PORTDIO_TOGGLE); + + D16(PORTEIO); + D16(PORTEIO_CLEAR); + D16(PORTEIO_DIR); + D16(PORTEIO_FER); + D16(PORTEIO_INEN); + D16(PORTEIO_SET); + D16(PORTEIO_TOGGLE); +#endif /* BF538 BF539 */ + +#ifdef __ADSPBF54x__ + { + int num; + unsigned long base; + char *_buf, buf[32]; + + base = PORTA_FER; + for (num = 0; num < 10; ++num) { + PORT(base, num); + base += sizeof(struct bfin_gpio_regs); + } + +#define __PINT(uname, lname) __REGS(pint, #uname, lname) + parent = debugfs_create_dir("pint", top); + base = PINT0_MASK_SET; + for (num = 0; num < 4; ++num) { + _buf = REGS_STR_PFX(buf, PINT, num); + __PINT(MASK_SET, mask_set); + __PINT(MASK_CLEAR, mask_clear); + __PINT(IRQ, irq); + __PINT(ASSIGN, assign); + __PINT(EDGE_SET, edge_set); + __PINT(EDGE_CLEAR, edge_clear); + __PINT(INVERT_SET, invert_set); + __PINT(INVERT_CLEAR, invert_clear); + __PINT(PINSTATE, pinstate); + __PINT(LATCH, latch); + base += sizeof(struct bfin_pint_regs); + } + + } +#endif /* BF54x */ + + debug_mmrs_dentry = top; + + return 0; +} +module_init(bfin_debug_mmrs_init); + +static void __exit bfin_debug_mmrs_exit(void) +{ + debugfs_remove_recursive(debug_mmrs_dentry); +} +module_exit(bfin_debug_mmrs_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index f37019c847c..486426f8a0d 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -33,6 +33,7 @@ #include <linux/io.h> #include <asm/system.h> #include <asm/atomic.h> +#include <asm/irq_handler.h> DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs); diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 1696d34f51c..ff3d747154a 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -11,6 +11,7 @@ #include <linux/kallsyms.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <asm/irq_handler.h> #include <asm/trace.h> #include <asm/pda.h> diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c index 401eb1d8e3b..679d0db3525 100644 --- a/arch/blackfin/kernel/nmi.c +++ b/arch/blackfin/kernel/nmi.c @@ -145,16 +145,16 @@ int check_nmi_wdt_touched(void) { unsigned int this_cpu = smp_processor_id(); unsigned int cpu; + cpumask_t mask; - cpumask_t mask = cpu_online_map; - + cpumask_copy(&mask, cpu_online_mask); if (!atomic_read(&nmi_touched[this_cpu])) return 0; atomic_set(&nmi_touched[this_cpu], 0); - cpu_clear(this_cpu, mask); - for_each_cpu_mask(cpu, mask) { + cpumask_clear_cpu(this_cpu, &mask); + for_each_cpu(cpu, &mask) { invalidate_dcache_range((unsigned long)(&nmi_touched[cpu]), (unsigned long)(&nmi_touched[cpu])); if (!atomic_read(&nmi_touched[cpu])) diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c new file mode 100644 index 00000000000..04300f29c0e --- /dev/null +++ b/arch/blackfin/kernel/perf_event.c @@ -0,0 +1,498 @@ +/* + * Blackfin performance counters + * + * Copyright 2011 Analog Devices Inc. + * + * Ripped from SuperH version: + * + * Copyright (C) 2009 Paul Mundt + * + * Heavily based on the x86 and PowerPC implementations. + * + * x86: + * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> + * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar + * Copyright (C) 2009 Jaswinder Singh Rajput + * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter + * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> + * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> + * + * ppc: + * Copyright 2008-2009 Paul Mackerras, IBM Corporation. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/perf_event.h> +#include <asm/bfin_pfmon.h> + +/* + * We have two counters, and each counter can support an event type. + * The 'o' is PFCNTx=1 and 's' is PFCNTx=0 + * + * 0x04 o pc invariant branches + * 0x06 o mispredicted branches + * 0x09 o predicted branches taken + * 0x0B o EXCPT insn + * 0x0C o CSYNC/SSYNC insn + * 0x0D o Insns committed + * 0x0E o Interrupts taken + * 0x0F o Misaligned address exceptions + * 0x80 o Code memory fetches stalled due to DMA + * 0x83 o 64bit insn fetches delivered + * 0x9A o data cache fills (bank a) + * 0x9B o data cache fills (bank b) + * 0x9C o data cache lines evicted (bank a) + * 0x9D o data cache lines evicted (bank b) + * 0x9E o data cache high priority fills + * 0x9F o data cache low priority fills + * 0x00 s loop 0 iterations + * 0x01 s loop 1 iterations + * 0x0A s CSYNC/SSYNC stalls + * 0x10 s DAG read/after write hazards + * 0x13 s RAW data hazards + * 0x81 s code TAG stalls + * 0x82 s code fill stalls + * 0x90 s processor to memory stalls + * 0x91 s data memory stalls not hidden by 0x90 + * 0x92 s data store buffer full stalls + * 0x93 s data memory write buffer full stalls due to high->low priority + * 0x95 s data memory fill buffer stalls + * 0x96 s data TAG collision stalls + * 0x97 s data collision stalls + * 0x98 s data stalls + * 0x99 s data stalls sent to processor + */ + +static const int event_map[] = { + /* use CYCLES cpu register */ + [PERF_COUNT_HW_CPU_CYCLES] = -1, + [PERF_COUNT_HW_INSTRUCTIONS] = 0x0D, + [PERF_COUNT_HW_CACHE_REFERENCES] = -1, + [PERF_COUNT_HW_CACHE_MISSES] = 0x83, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x09, + [PERF_COUNT_HW_BRANCH_MISSES] = 0x06, + [PERF_COUNT_HW_BUS_CYCLES] = -1, +}; + +#define C(x) PERF_COUNT_HW_CACHE_##x + +static const int cache_events[PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [C(L1D)] = { /* Data bank A */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0, + [C(RESULT_MISS) ] = 0x9A, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = 0, + [C(RESULT_MISS) ] = 0, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0, + [C(RESULT_MISS) ] = 0, + }, + }, + + [C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0, + [C(RESULT_MISS) ] = 0x83, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0, + [C(RESULT_MISS) ] = 0, + }, + }, + + [C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + }, + + [C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + }, + + [C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + }, + + [C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS) ] = -1, + }, + }, +}; + +const char *perf_pmu_name(void) +{ + return "bfin"; +} +EXPORT_SYMBOL(perf_pmu_name); + +int perf_num_counters(void) +{ + return ARRAY_SIZE(event_map); +} +EXPORT_SYMBOL(perf_num_counters); + +static u64 bfin_pfmon_read(int idx) +{ + return bfin_read32(PFCNTR0 + (idx * 4)); +} + +static void bfin_pfmon_disable(struct hw_perf_event *hwc, int idx) +{ + bfin_write_PFCTL(bfin_read_PFCTL() & ~PFCEN(idx, PFCEN_MASK)); +} + +static void bfin_pfmon_enable(struct hw_perf_event *hwc, int idx) +{ + u32 val, mask; + + val = PFPWR; + if (idx) { + mask = ~(PFCNT1 | PFMON1 | PFCEN1 | PEMUSW1); + /* The packed config is for event0, so shift it to event1 slots */ + val |= (hwc->config << (PFMON1_P - PFMON0_P)); + val |= (hwc->config & PFCNT0) << (PFCNT1_P - PFCNT0_P); + bfin_write_PFCNTR1(0); + } else { + mask = ~(PFCNT0 | PFMON0 | PFCEN0 | PEMUSW0); + val |= hwc->config; + bfin_write_PFCNTR0(0); + } + + bfin_write_PFCTL((bfin_read_PFCTL() & mask) | val); +} + +static void bfin_pfmon_disable_all(void) +{ + bfin_write_PFCTL(bfin_read_PFCTL() & ~PFPWR); +} + +static void bfin_pfmon_enable_all(void) +{ + bfin_write_PFCTL(bfin_read_PFCTL() | PFPWR); +} + +struct cpu_hw_events { + struct perf_event *events[MAX_HWEVENTS]; + unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; +}; +DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); + +static int hw_perf_cache_event(int config, int *evp) +{ + unsigned long type, op, result; + int ev; + + /* unpack config */ + type = config & 0xff; + op = (config >> 8) & 0xff; + result = (config >> 16) & 0xff; + + if (type >= PERF_COUNT_HW_CACHE_MAX || + op >= PERF_COUNT_HW_CACHE_OP_MAX || + result >= PERF_COUNT_HW_CACHE_RESULT_MAX) + return -EINVAL; + + ev = cache_events[type][op][result]; + if (ev == 0) + return -EOPNOTSUPP; + if (ev == -1) + return -EINVAL; + *evp = ev; + return 0; +} + +static void bfin_perf_event_update(struct perf_event *event, + struct hw_perf_event *hwc, int idx) +{ + u64 prev_raw_count, new_raw_count; + s64 delta; + int shift = 0; + + /* + * Depending on the counter configuration, they may or may not + * be chained, in which case the previous counter value can be + * updated underneath us if the lower-half overflows. + * + * Our tactic to handle this is to first atomically read and + * exchange a new raw count - then add that new-prev delta + * count to the generic counter atomically. + * + * As there is no interrupt associated with the overflow events, + * this is the simplest approach for maintaining consistency. + */ +again: + prev_raw_count = local64_read(&hwc->prev_count); + new_raw_count = bfin_pfmon_read(idx); + + if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, + new_raw_count) != prev_raw_count) + goto again; + + /* + * Now we have the new raw value and have updated the prev + * timestamp already. We can now calculate the elapsed delta + * (counter-)time and add that to the generic counter. + * + * Careful, not all hw sign-extends above the physical width + * of the count. + */ + delta = (new_raw_count << shift) - (prev_raw_count << shift); + delta >>= shift; + + local64_add(delta, &event->count); +} + +static void bfin_pmu_stop(struct perf_event *event, int flags) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + if (!(event->hw.state & PERF_HES_STOPPED)) { + bfin_pfmon_disable(hwc, idx); + cpuc->events[idx] = NULL; + event->hw.state |= PERF_HES_STOPPED; + } + + if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) { + bfin_perf_event_update(event, &event->hw, idx); + event->hw.state |= PERF_HES_UPTODATE; + } +} + +static void bfin_pmu_start(struct perf_event *event, int flags) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + if (WARN_ON_ONCE(idx == -1)) + return; + + if (flags & PERF_EF_RELOAD) + WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); + + cpuc->events[idx] = event; + event->hw.state = 0; + bfin_pfmon_enable(hwc, idx); +} + +static void bfin_pmu_del(struct perf_event *event, int flags) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + bfin_pmu_stop(event, PERF_EF_UPDATE); + __clear_bit(event->hw.idx, cpuc->used_mask); + + perf_event_update_userpage(event); +} + +static int bfin_pmu_add(struct perf_event *event, int flags) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + int ret = -EAGAIN; + + perf_pmu_disable(event->pmu); + + if (__test_and_set_bit(idx, cpuc->used_mask)) { + idx = find_first_zero_bit(cpuc->used_mask, MAX_HWEVENTS); + if (idx == MAX_HWEVENTS) + goto out; + + __set_bit(idx, cpuc->used_mask); + hwc->idx = idx; + } + + bfin_pfmon_disable(hwc, idx); + + event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; + if (flags & PERF_EF_START) + bfin_pmu_start(event, PERF_EF_RELOAD); + + perf_event_update_userpage(event); + ret = 0; +out: + perf_pmu_enable(event->pmu); + return ret; +} + +static void bfin_pmu_read(struct perf_event *event) +{ + bfin_perf_event_update(event, &event->hw, event->hw.idx); +} + +static int bfin_pmu_event_init(struct perf_event *event) +{ + struct perf_event_attr *attr = &event->attr; + struct hw_perf_event *hwc = &event->hw; + int config = -1; + int ret; + + if (attr->exclude_hv || attr->exclude_idle) + return -EPERM; + + /* + * All of the on-chip counters are "limited", in that they have + * no interrupts, and are therefore unable to do sampling without + * further work and timer assistance. + */ + if (hwc->sample_period) + return -EINVAL; + + ret = 0; + switch (attr->type) { + case PERF_TYPE_RAW: + config = PFMON(0, attr->config & PFMON_MASK) | + PFCNT(0, !(attr->config & 0x100)); + break; + case PERF_TYPE_HW_CACHE: + ret = hw_perf_cache_event(attr->config, &config); + break; + case PERF_TYPE_HARDWARE: + if (attr->config >= ARRAY_SIZE(event_map)) + return -EINVAL; + + config = event_map[attr->config]; + break; + } + + if (config == -1) + return -EINVAL; + + if (!attr->exclude_kernel) + config |= PFCEN(0, PFCEN_ENABLE_SUPV); + if (!attr->exclude_user) + config |= PFCEN(0, PFCEN_ENABLE_USER); + + hwc->config |= config; + + return ret; +} + +static void bfin_pmu_enable(struct pmu *pmu) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct perf_event *event; + struct hw_perf_event *hwc; + int i; + + for (i = 0; i < MAX_HWEVENTS; ++i) { + event = cpuc->events[i]; + if (!event) + continue; + hwc = &event->hw; + bfin_pfmon_enable(hwc, hwc->idx); + } + + bfin_pfmon_enable_all(); +} + +static void bfin_pmu_disable(struct pmu *pmu) +{ + bfin_pfmon_disable_all(); +} + +static struct pmu pmu = { + .pmu_enable = bfin_pmu_enable, + .pmu_disable = bfin_pmu_disable, + .event_init = bfin_pmu_event_init, + .add = bfin_pmu_add, + .del = bfin_pmu_del, + .start = bfin_pmu_start, + .stop = bfin_pmu_stop, + .read = bfin_pmu_read, +}; + +static void bfin_pmu_setup(int cpu) +{ + struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); + + memset(cpuhw, 0, sizeof(struct cpu_hw_events)); +} + +static int __cpuinit +bfin_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) +{ + unsigned int cpu = (long)hcpu; + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + bfin_write_PFCTL(0); + bfin_pmu_setup(cpu); + break; + + default: + break; + } + + return NOTIFY_OK; +} + +static int __init bfin_pmu_init(void) +{ + int ret; + + ret = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); + if (!ret) + perf_cpu_notifier(bfin_pmu_notifier); + + return ret; +} +early_initcall(bfin_pmu_init); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index b407bc8ad91..6a660fa921b 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -171,10 +171,8 @@ asmlinkage int bfin_clone(struct pt_regs *regs) unsigned long newsp; #ifdef __ARCH_SYNC_CORE_DCACHE - if (current->rt.nr_cpus_allowed == num_possible_cpus()) { - current->cpus_allowed = cpumask_of_cpu(smp_processor_id()); - current->rt.nr_cpus_allowed = 1; - } + if (current->rt.nr_cpus_allowed == num_possible_cpus()) + set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); #endif /* syscall2 puts clone_flags in r0 and usp in r1 */ diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index 53d08dee853..488bdc51aaa 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -23,6 +23,9 @@ __attribute__ ((__l1_text__, __noreturn__)) static void bfin_reset(void) { + if (!ANOMALY_05000353 && !ANOMALY_05000386) + bfrom_SoftReset((void *)(L1_SCRATCH_START + L1_SCRATCH_LENGTH - 20)); + /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as * much as possible. This code is in L1, so it won't trigger @@ -30,46 +33,40 @@ static void bfin_reset(void) */ __builtin_bfin_ssync(); - /* The bootrom checks to see how it was reset and will - * automatically perform a software reset for us when - * it starts executing after the core reset. - */ - if (ANOMALY_05000353 || ANOMALY_05000386) { - /* Initiate System software reset. */ - bfin_write_SWRST(0x7); + /* Initiate System software reset. */ + bfin_write_SWRST(0x7); - /* Due to the way reset is handled in the hardware, we need - * to delay for 10 SCLKS. The only reliable way to do this is - * to calculate the CCLK/SCLK ratio and multiply 10. For now, - * we'll assume worse case which is a 1:15 ratio. - */ - asm( - "LSETUP (1f, 1f) LC0 = %0\n" - "1: nop;" - : - : "a" (15 * 10) - : "LC0", "LB0", "LT0" - ); + /* Due to the way reset is handled in the hardware, we need + * to delay for 10 SCLKS. The only reliable way to do this is + * to calculate the CCLK/SCLK ratio and multiply 10. For now, + * we'll assume worse case which is a 1:15 ratio. + */ + asm( + "LSETUP (1f, 1f) LC0 = %0\n" + "1: nop;" + : + : "a" (15 * 10) + : "LC0", "LB0", "LT0" + ); - /* Clear System software reset */ - bfin_write_SWRST(0); + /* Clear System software reset */ + bfin_write_SWRST(0); - /* The BF526 ROM will crash during reset */ + /* The BF526 ROM will crash during reset */ #if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) - bfin_read_SWRST(); + bfin_read_SWRST(); #endif - /* Wait for the SWRST write to complete. Cannot rely on SSYNC - * though as the System state is all reset now. - */ - asm( - "LSETUP (1f, 1f) LC1 = %0\n" - "1: nop;" - : - : "a" (15 * 1) - : "LC1", "LB1", "LT1" - ); - } + /* Wait for the SWRST write to complete. Cannot rely on SSYNC + * though as the System state is all reset now. + */ + asm( + "LSETUP (1f, 1f) LC1 = %0\n" + "1: nop;" + : + : "a" (15 * 1) + : "LC1", "LB1", "LT1" + ); while (1) /* Issue core reset */ diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 805c6132c77..536bd9d7e0c 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -29,6 +29,7 @@ #include <asm/cpu.h> #include <asm/fixed_code.h> #include <asm/early_printk.h> +#include <asm/irq_handler.h> u16 _bfin_swrst; EXPORT_SYMBOL(_bfin_swrst); @@ -105,6 +106,8 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) bfin_dcache_init(dcplb_tbl[cpu]); #endif + bfin_setup_cpudata(cpu); + /* * In cache coherence emulation mode, we need to have the * D-cache enabled before running any atomic operation which @@ -163,7 +166,6 @@ void __cpuinit bfin_setup_cpudata(unsigned int cpu) { struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); - cpudata->idle = current; cpudata->imemctl = bfin_read_IMEM_CONTROL(); cpudata->dmemctl = bfin_read_DMEM_CONTROL(); } @@ -851,6 +853,7 @@ void __init native_machine_early_platform_add_devices(void) void __init setup_arch(char **cmdline_p) { + u32 mmr; unsigned long sclk, cclk; native_machine_early_platform_add_devices(); @@ -902,10 +905,10 @@ void __init setup_arch(char **cmdline_p) bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTLVAL); #endif #ifdef CONFIG_BFIN_HYSTERESIS_CONTROL - bfin_write_PORTF_HYSTERISIS(HYST_PORTF_0_15); - bfin_write_PORTG_HYSTERISIS(HYST_PORTG_0_15); - bfin_write_PORTH_HYSTERISIS(HYST_PORTH_0_15); - bfin_write_MISCPORT_HYSTERISIS((bfin_read_MISCPORT_HYSTERISIS() & + bfin_write_PORTF_HYSTERESIS(HYST_PORTF_0_15); + bfin_write_PORTG_HYSTERESIS(HYST_PORTG_0_15); + bfin_write_PORTH_HYSTERESIS(HYST_PORTH_0_15); + bfin_write_MISCPORT_HYSTERESIS((bfin_read_MISCPORT_HYSTERESIS() & ~HYST_NONEGPIO_MASK) | HYST_NONEGPIO); #endif @@ -921,17 +924,14 @@ void __init setup_arch(char **cmdline_p) bfin_read_IMDMA_D1_IRQ_STATUS(); } #endif - printk(KERN_INFO "Hardware Trace "); - if (bfin_read_TBUFCTL() & 0x1) - printk(KERN_CONT "Active "); - else - printk(KERN_CONT "Off "); - if (bfin_read_TBUFCTL() & 0x2) - printk(KERN_CONT "and Enabled\n"); - else - printk(KERN_CONT "and Disabled\n"); - printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF); + mmr = bfin_read_TBUFCTL(); + printk(KERN_INFO "Hardware Trace %s and %sabled\n", + (mmr & 0x1) ? "active" : "off", + (mmr & 0x2) ? "en" : "dis"); + + mmr = bfin_read_SYSCR(); + printk(KERN_INFO "Boot Mode: %i\n", mmr & 0xF); /* Newer parts mirror SWRST bits in SYSCR */ #if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \ @@ -939,7 +939,7 @@ void __init setup_arch(char **cmdline_p) _bfin_swrst = bfin_read_SWRST(); #else /* Clear boot mode field */ - _bfin_swrst = bfin_read_SYSCR() & ~0xf; + _bfin_swrst = mmr & ~0xf; #endif #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT @@ -1036,8 +1036,6 @@ void __init setup_arch(char **cmdline_p) static int __init topology_init(void) { unsigned int cpu; - /* Record CPU-private information for the boot processor. */ - bfin_setup_cpudata(0); for_each_possible_cpu(cpu) { register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu); @@ -1283,12 +1281,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, BFIN_DLINES); #ifdef __ARCH_SYNC_CORE_DCACHE - seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", dcache_invld_count[cpu_num]); + seq_printf(m, "dcache flushes\t: %lu\n", dcache_invld_count[cpu_num]); #endif #ifdef __ARCH_SYNC_CORE_ICACHE - seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", icache_invld_count[cpu_num]); + seq_printf(m, "icache flushes\t: %lu\n", icache_invld_count[cpu_num]); #endif + seq_printf(m, "\n"); + if (cpu_num != num_possible_cpus() - 1) return 0; @@ -1312,13 +1312,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) " in data cache\n"); } seq_printf(m, "board name\t: %s\n", bfin_board_name); - seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", - physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); - seq_printf(m, "kernel memory\t: %d kB (0x%p -> 0x%p)\n", + seq_printf(m, "board memory\t: %ld kB (0x%08lx -> 0x%08lx)\n", + physical_mem_end >> 10, 0ul, physical_mem_end); + seq_printf(m, "kernel memory\t: %d kB (0x%08lx -> 0x%08lx)\n", ((int)memory_end - (int)_rambase) >> 10, - (void *)_rambase, - (void *)memory_end); - seq_printf(m, "\n"); + _rambase, memory_end); return 0; } @@ -1326,7 +1324,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { if (*pos == 0) - *pos = first_cpu(cpu_online_map); + *pos = cpumask_first(cpu_online_mask); if (*pos >= num_online_cpus()) return NULL; @@ -1335,7 +1333,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - *pos = next_cpu(*pos, cpu_online_map); + *pos = cpumask_next(*pos, cpu_online_mask); return c_start(m, pos); } diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 8d85c8c6f85..3ac5b66d14a 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -155,14 +155,8 @@ SECTIONS SECURITY_INITCALL INIT_RAM_FS - . = ALIGN(4); ___per_cpu_load = .; - ___per_cpu_start = .; - *(.data.percpu.first) - *(.data.percpu.page_aligned) - *(.data.percpu) - *(.data.percpu.shared_aligned) - ___per_cpu_end = .; + PERCPU_INPUT(32) EXIT_DATA __einitdata = .; diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h index 24918c5f7ea..d2f076fbbc9 100644 --- a/arch/blackfin/mach-bf518/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h @@ -5,7 +5,7 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ @@ -141,6 +141,7 @@ #define ANOMALY_05000364 (0) #define ANOMALY_05000371 (0) #define ANOMALY_05000380 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000386 (0) #define ANOMALY_05000389 (0) #define ANOMALY_05000400 (0) @@ -155,6 +156,7 @@ #define ANOMALY_05000467 (0) #define ANOMALY_05000474 (0) #define ANOMALY_05000475 (0) +#define ANOMALY_05000480 (0) #define ANOMALY_05000485 (0) #endif diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF512.h b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h index b657d37a340..bb79627f092 100644 --- a/arch/blackfin/mach-bf518/include/mach/cdefBF512.h +++ b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h @@ -990,18 +990,18 @@ #define bfin_write_PORTG_SLEW(val) bfin_write16(PORTG_SLEW, val) #define bfin_read_PORTH_SLEW() bfin_read16(PORTH_SLEW) #define bfin_write_PORTH_SLEW(val) bfin_write16(PORTH_SLEW, val) -#define bfin_read_PORTF_HYSTERISIS() bfin_read16(PORTF_HYSTERISIS) -#define bfin_write_PORTF_HYSTERISIS(val) bfin_write16(PORTF_HYSTERISIS, val) -#define bfin_read_PORTG_HYSTERISIS() bfin_read16(PORTG_HYSTERISIS) -#define bfin_write_PORTG_HYSTERISIS(val) bfin_write16(PORTG_HYSTERISIS, val) -#define bfin_read_PORTH_HYSTERISIS() bfin_read16(PORTH_HYSTERISIS) -#define bfin_write_PORTH_HYSTERISIS(val) bfin_write16(PORTH_HYSTERISIS, val) +#define bfin_read_PORTF_HYSTERESIS() bfin_read16(PORTF_HYSTERESIS) +#define bfin_write_PORTF_HYSTERESIS(val) bfin_write16(PORTF_HYSTERESIS, val) +#define bfin_read_PORTG_HYSTERESIS() bfin_read16(PORTG_HYSTERESIS) +#define bfin_write_PORTG_HYSTERESIS(val) bfin_write16(PORTG_HYSTERESIS, val) +#define bfin_read_PORTH_HYSTERESIS() bfin_read16(PORTH_HYSTERESIS) +#define bfin_write_PORTH_HYSTERESIS(val) bfin_write16(PORTH_HYSTERESIS, val) #define bfin_read_MISCPORT_DRIVE() bfin_read16(MISCPORT_DRIVE) #define bfin_write_MISCPORT_DRIVE(val) bfin_write16(MISCPORT_DRIVE, val) #define bfin_read_MISCPORT_SLEW() bfin_read16(MISCPORT_SLEW) #define bfin_write_MISCPORT_SLEW(val) bfin_write16(MISCPORT_SLEW, val) -#define bfin_read_MISCPORT_HYSTERISIS() bfin_read16(MISCPORT_HYSTERISIS) -#define bfin_write_MISCPORT_HYSTERISIS(val) bfin_write16(MISCPORT_HYSTERISIS, val) +#define bfin_read_MISCPORT_HYSTERESIS() bfin_read16(MISCPORT_HYSTERESIS) +#define bfin_write_MISCPORT_HYSTERESIS(val) bfin_write16(MISCPORT_HYSTERESIS, val) /* HOST Port Registers */ diff --git a/arch/blackfin/mach-bf518/include/mach/defBF512.h b/arch/blackfin/mach-bf518/include/mach/defBF512.h index cb1172f5075..729704078cd 100644 --- a/arch/blackfin/mach-bf518/include/mach/defBF512.h +++ b/arch/blackfin/mach-bf518/include/mach/defBF512.h @@ -561,12 +561,12 @@ #define PORTF_SLEW 0xFFC03230 /* Port F slew control */ #define PORTG_SLEW 0xFFC03234 /* Port G slew control */ #define PORTH_SLEW 0xFFC03238 /* Port H slew control */ -#define PORTF_HYSTERISIS 0xFFC03240 /* Port F Schmitt trigger control */ -#define PORTG_HYSTERISIS 0xFFC03244 /* Port G Schmitt trigger control */ -#define PORTH_HYSTERISIS 0xFFC03248 /* Port H Schmitt trigger control */ +#define PORTF_HYSTERESIS 0xFFC03240 /* Port F Schmitt trigger control */ +#define PORTG_HYSTERESIS 0xFFC03244 /* Port G Schmitt trigger control */ +#define PORTH_HYSTERESIS 0xFFC03248 /* Port H Schmitt trigger control */ #define MISCPORT_DRIVE 0xFFC03280 /* Misc Port drive strength control */ #define MISCPORT_SLEW 0xFFC03284 /* Misc Port slew control */ -#define MISCPORT_HYSTERISIS 0xFFC03288 /* Misc Port Schmitt trigger control */ +#define MISCPORT_HYSTERESIS 0xFFC03288 /* Misc Port Schmitt trigger control */ /*********************************************************************************** diff --git a/arch/blackfin/mach-bf518/include/mach/irq.h b/arch/blackfin/mach-bf518/include/mach/irq.h index 435e76e31aa..edf8efd457d 100644 --- a/arch/blackfin/mach-bf518/include/mach/irq.h +++ b/arch/blackfin/mach-bf518/include/mach/irq.h @@ -7,38 +7,9 @@ #ifndef _BF518_IRQ_H_ #define _BF518_IRQ_H_ -/* - * Interrupt source definitions - Event Source Core Event Name - Core Emulation ** - Events (highest priority) EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - - ..... - - Software Interrupt 1 IVG14 31 - Software Interrupt 2 -- - (lowest priority) IVG15 32 * -*/ - -#define NR_PERI_INTS (2 * 32) - -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /* Emulation */ -#define IRQ_RST 1 /* reset */ -#define IRQ_NMI 2 /* Non Maskable */ -#define IRQ_EVX 3 /* Exception */ -#define IRQ_UNUSED 4 /* - unused interrupt */ -#define IRQ_HWERR 5 /* Hardware Error */ -#define IRQ_CORETMR 6 /* Core timer */ - -#define BFIN_IRQ(x) ((x) + 7) +#include <mach-common/irq.h> + +#define NR_PERI_INTS (2 * 32) #define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ #define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */ @@ -54,23 +25,23 @@ #define IRQ_UART0_ERROR BFIN_IRQ(12) /* UART0 Status */ #define IRQ_UART1_ERROR BFIN_IRQ(13) /* UART1 Status */ #define IRQ_RTC BFIN_IRQ(14) /* RTC */ -#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI) */ +#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI) */ #define IRQ_SPORT0_RX BFIN_IRQ(16) /* DMA 3 Channel (SPORT0 RX) */ #define IRQ_SPORT0_TX BFIN_IRQ(17) /* DMA 4 Channel (SPORT0 TX) */ #define IRQ_RSI BFIN_IRQ(17) /* DMA 4 Channel (RSI) */ #define IRQ_SPORT1_RX BFIN_IRQ(18) /* DMA 5 Channel (SPORT1 RX/SPI) */ #define IRQ_SPI1 BFIN_IRQ(18) /* DMA 5 Channel (SPI1) */ #define IRQ_SPORT1_TX BFIN_IRQ(19) /* DMA 6 Channel (SPORT1 TX) */ -#define IRQ_TWI BFIN_IRQ(20) /* TWI */ -#define IRQ_SPI0 BFIN_IRQ(21) /* DMA 7 Channel (SPI0) */ -#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */ -#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */ -#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */ -#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */ -#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */ -#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */ -#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX) */ -#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */ +#define IRQ_TWI BFIN_IRQ(20) /* TWI */ +#define IRQ_SPI0 BFIN_IRQ(21) /* DMA 7 Channel (SPI0) */ +#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */ +#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */ +#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */ +#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */ +#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */ +#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */ +#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX) */ +#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */ #define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX) */ #define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */ #define IRQ_TIMER0 BFIN_IRQ(32) /* Timer 0 */ @@ -96,101 +67,90 @@ #define IRQ_PWM_SYNC BFIN_IRQ(54) /* PWM Sync Interrupt */ #define IRQ_PTP_STAT BFIN_IRQ(55) /* PTP Stat Interrupt */ -#define SYS_IRQS BFIN_IRQ(63) /* 70 */ - -#define IRQ_PF0 71 -#define IRQ_PF1 72 -#define IRQ_PF2 73 -#define IRQ_PF3 74 -#define IRQ_PF4 75 -#define IRQ_PF5 76 -#define IRQ_PF6 77 -#define IRQ_PF7 78 -#define IRQ_PF8 79 -#define IRQ_PF9 80 -#define IRQ_PF10 81 -#define IRQ_PF11 82 -#define IRQ_PF12 83 -#define IRQ_PF13 84 -#define IRQ_PF14 85 -#define IRQ_PF15 86 - -#define IRQ_PG0 87 -#define IRQ_PG1 88 -#define IRQ_PG2 89 -#define IRQ_PG3 90 -#define IRQ_PG4 91 -#define IRQ_PG5 92 -#define IRQ_PG6 93 -#define IRQ_PG7 94 -#define IRQ_PG8 95 -#define IRQ_PG9 96 -#define IRQ_PG10 97 -#define IRQ_PG11 98 -#define IRQ_PG12 99 -#define IRQ_PG13 100 -#define IRQ_PG14 101 -#define IRQ_PG15 102 - -#define IRQ_PH0 103 -#define IRQ_PH1 104 -#define IRQ_PH2 105 -#define IRQ_PH3 106 -#define IRQ_PH4 107 -#define IRQ_PH5 108 -#define IRQ_PH6 109 -#define IRQ_PH7 110 -#define IRQ_PH8 111 -#define IRQ_PH9 112 -#define IRQ_PH10 113 -#define IRQ_PH11 114 -#define IRQ_PH12 115 -#define IRQ_PH13 116 -#define IRQ_PH14 117 -#define IRQ_PH15 118 - -#define GPIO_IRQ_BASE IRQ_PF0 - -#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */ -#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */ -#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */ -#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */ -#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */ -#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */ -#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */ -#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */ - -#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 +#define SYS_IRQS BFIN_IRQ(63) /* 70 */ + +#define IRQ_PF0 71 +#define IRQ_PF1 72 +#define IRQ_PF2 73 +#define IRQ_PF3 74 +#define IRQ_PF4 75 +#define IRQ_PF5 76 +#define IRQ_PF6 77 +#define IRQ_PF7 78 +#define IRQ_PF8 79 +#define IRQ_PF9 80 +#define IRQ_PF10 81 +#define IRQ_PF11 82 +#define IRQ_PF12 83 +#define IRQ_PF13 84 +#define IRQ_PF14 85 +#define IRQ_PF15 86 + +#define IRQ_PG0 87 +#define IRQ_PG1 88 +#define IRQ_PG2 89 +#define IRQ_PG3 90 +#define IRQ_PG4 91 +#define IRQ_PG5 92 +#define IRQ_PG6 93 +#define IRQ_PG7 94 +#define IRQ_PG8 95 +#define IRQ_PG9 96 +#define IRQ_PG10 97 +#define IRQ_PG11 98 +#define IRQ_PG12 99 +#define IRQ_PG13 100 +#define IRQ_PG14 101 +#define IRQ_PG15 102 + +#define IRQ_PH0 103 +#define IRQ_PH1 104 +#define IRQ_PH2 105 +#define IRQ_PH3 106 +#define IRQ_PH4 107 +#define IRQ_PH5 108 +#define IRQ_PH6 109 +#define IRQ_PH7 110 +#define IRQ_PH8 111 +#define IRQ_PH9 112 +#define IRQ_PH10 113 +#define IRQ_PH11 114 +#define IRQ_PH12 115 +#define IRQ_PH13 116 +#define IRQ_PH14 117 +#define IRQ_PH15 118 + +#define GPIO_IRQ_BASE IRQ_PF0 + +#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */ +#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */ +#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */ +#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */ +#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */ +#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */ +#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */ +#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */ + +#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1) /* IAR0 BIT FIELDS */ #define IRQ_PLL_WAKEUP_POS 0 #define IRQ_DMA0_ERROR_POS 4 -#define IRQ_DMAR0_BLK_POS 8 -#define IRQ_DMAR1_BLK_POS 12 -#define IRQ_DMAR0_OVR_POS 16 -#define IRQ_DMAR1_OVR_POS 20 -#define IRQ_PPI_ERROR_POS 24 -#define IRQ_MAC_ERROR_POS 28 +#define IRQ_DMAR0_BLK_POS 8 +#define IRQ_DMAR1_BLK_POS 12 +#define IRQ_DMAR0_OVR_POS 16 +#define IRQ_DMAR1_OVR_POS 20 +#define IRQ_PPI_ERROR_POS 24 +#define IRQ_MAC_ERROR_POS 28 /* IAR1 BIT FIELDS */ #define IRQ_SPORT0_ERROR_POS 0 #define IRQ_SPORT1_ERROR_POS 4 #define IRQ_PTP_ERROR_POS 8 -#define IRQ_UART0_ERROR_POS 16 -#define IRQ_UART1_ERROR_POS 20 -#define IRQ_RTC_POS 24 -#define IRQ_PPI_POS 28 +#define IRQ_UART0_ERROR_POS 16 +#define IRQ_UART1_ERROR_POS 20 +#define IRQ_RTC_POS 24 +#define IRQ_PPI_POS 28 /* IAR2 BIT FIELDS */ #define IRQ_SPORT0_RX_POS 0 @@ -199,19 +159,19 @@ #define IRQ_SPORT1_RX_POS 8 #define IRQ_SPI1_POS 8 #define IRQ_SPORT1_TX_POS 12 -#define IRQ_TWI_POS 16 -#define IRQ_SPI0_POS 20 -#define IRQ_UART0_RX_POS 24 -#define IRQ_UART0_TX_POS 28 +#define IRQ_TWI_POS 16 +#define IRQ_SPI0_POS 20 +#define IRQ_UART0_RX_POS 24 +#define IRQ_UART0_TX_POS 28 /* IAR3 BIT FIELDS */ -#define IRQ_UART1_RX_POS 0 -#define IRQ_UART1_TX_POS 4 -#define IRQ_OPTSEC_POS 8 -#define IRQ_CNT_POS 12 -#define IRQ_MAC_RX_POS 16 +#define IRQ_UART1_RX_POS 0 +#define IRQ_UART1_TX_POS 4 +#define IRQ_OPTSEC_POS 8 +#define IRQ_CNT_POS 12 +#define IRQ_MAC_RX_POS 16 #define IRQ_PORTH_INTA_POS 20 -#define IRQ_MAC_TX_POS 24 +#define IRQ_MAC_TX_POS 24 #define IRQ_PORTH_INTB_POS 28 /* IAR4 BIT FIELDS */ @@ -227,19 +187,19 @@ /* IAR5 BIT FIELDS */ #define IRQ_PORTG_INTA_POS 0 #define IRQ_PORTG_INTB_POS 4 -#define IRQ_MEM_DMA0_POS 8 -#define IRQ_MEM_DMA1_POS 12 -#define IRQ_WATCH_POS 16 +#define IRQ_MEM_DMA0_POS 8 +#define IRQ_MEM_DMA1_POS 12 +#define IRQ_WATCH_POS 16 #define IRQ_PORTF_INTA_POS 20 #define IRQ_PORTF_INTB_POS 24 -#define IRQ_SPI0_ERROR_POS 28 +#define IRQ_SPI0_ERROR_POS 28 /* IAR6 BIT FIELDS */ -#define IRQ_SPI1_ERROR_POS 0 -#define IRQ_RSI_INT0_POS 12 -#define IRQ_RSI_INT1_POS 16 -#define IRQ_PWM_TRIP_POS 20 -#define IRQ_PWM_SYNC_POS 24 -#define IRQ_PTP_STAT_POS 28 - -#endif /* _BF518_IRQ_H_ */ +#define IRQ_SPI1_ERROR_POS 0 +#define IRQ_RSI_INT0_POS 12 +#define IRQ_RSI_INT1_POS 16 +#define IRQ_PWM_TRIP_POS 20 +#define IRQ_PWM_SYNC_POS 24 +#define IRQ_PTP_STAT_POS 28 + +#endif diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 2cd2ff6f304..e67ac772066 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -26,6 +26,7 @@ #include <asm/portmux.h> #include <asm/dpmc.h> #include <linux/spi/ad7877.h> +#include <asm/bfin_sport.h> /* * Name the Board for the /proc/cpuinfo @@ -526,11 +527,69 @@ static struct bfin5xx_spi_chip spidev_chip_info = { }; #endif +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) + +static const u16 bfin_snd_pin[][7] = { + {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, + P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0, 0}, + {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, + P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_TFS, 0}, +}; + +static struct bfin_snd_platform_data bfin_snd_data[] = { + { + .pin_req = &bfin_snd_pin[0][0], + }, + { + .pin_req = &bfin_snd_pin[1][0], + }, +}; + +#define BFIN_SND_RES(x) \ + [x] = { \ + { \ + .start = SPORT##x##_TCR1, \ + .end = SPORT##x##_TCR1, \ + .flags = IORESOURCE_MEM \ + }, \ + { \ + .start = CH_SPORT##x##_RX, \ + .end = CH_SPORT##x##_RX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = CH_SPORT##x##_TX, \ + .end = CH_SPORT##x##_TX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = IRQ_SPORT##x##_ERROR, \ + .end = IRQ_SPORT##x##_ERROR, \ + .flags = IORESOURCE_IRQ, \ + } \ + } + +static struct resource bfin_snd_resources[][4] = { + BFIN_SND_RES(0), + BFIN_SND_RES(1), +}; + +static struct platform_device bfin_pcm = { + .name = "bfin-pcm-audio", + .id = -1, +}; +#endif + #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) static struct platform_device bfin_i2s = { .name = "bfin-i2s", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif @@ -538,7 +597,11 @@ static struct platform_device bfin_i2s = { static struct platform_device bfin_tdm = { .name = "bfin-tdm", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif @@ -583,7 +646,9 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, .chip_select = 4, + .platform_data = "ad1836", .controller_data = &ad1836_spi_chip_info, + .mode = SPI_MODE_3, }, #endif #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE) @@ -1211,6 +1276,11 @@ static struct platform_device *stamp_devices[] __initdata = { &ezkit_flash_device, #endif +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) + &bfin_pcm, +#endif + #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) &bfin_i2s, #endif diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h index 9358afa05c9..e66a7e89cd3 100644 --- a/arch/blackfin/mach-bf527/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h @@ -5,14 +5,14 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: * - Revision E, 03/15/2010; ADSP-BF526 Blackfin Processor Anomaly List - * - Revision G, 08/25/2009; ADSP-BF527 Blackfin Processor Anomaly List + * - Revision H, 04/29/2010; ADSP-BF527 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -220,6 +220,8 @@ #define ANOMALY_05000483 (1) /* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */ #define ANOMALY_05000485 (_ANOMALY_BF526_BF527(< 2, < 3)) +/* The CODEC Zero-Cross Detect Feature is not Functional */ +#define ANOMALY_05000487 (1) /* IFLUSH sucks at life */ #define ANOMALY_05000491 (1) @@ -268,11 +270,13 @@ #define ANOMALY_05000323 (0) #define ANOMALY_05000362 (1) #define ANOMALY_05000363 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000400 (0) #define ANOMALY_05000402 (0) #define ANOMALY_05000412 (0) #define ANOMALY_05000447 (0) #define ANOMALY_05000448 (0) #define ANOMALY_05000474 (0) +#define ANOMALY_05000480 (0) #endif diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF522.h b/arch/blackfin/mach-bf527/include/mach/cdefBF522.h index 618dfcdfa91..2c12e879aa4 100644 --- a/arch/blackfin/mach-bf527/include/mach/cdefBF522.h +++ b/arch/blackfin/mach-bf527/include/mach/cdefBF522.h @@ -1007,18 +1007,18 @@ #define bfin_write_PORTG_SLEW(val) bfin_write16(PORTG_SLEW, val) #define bfin_read_PORTH_SLEW() bfin_read16(PORTH_SLEW) #define bfin_write_PORTH_SLEW(val) bfin_write16(PORTH_SLEW, val) -#define bfin_read_PORTF_HYSTERISIS() bfin_read16(PORTF_HYSTERISIS) -#define bfin_write_PORTF_HYSTERISIS(val) bfin_write16(PORTF_HYSTERISIS, val) -#define bfin_read_PORTG_HYSTERISIS() bfin_read16(PORTG_HYSTERISIS) -#define bfin_write_PORTG_HYSTERISIS(val) bfin_write16(PORTG_HYSTERISIS, val) -#define bfin_read_PORTH_HYSTERISIS() bfin_read16(PORTH_HYSTERISIS) -#define bfin_write_PORTH_HYSTERISIS(val) bfin_write16(PORTH_HYSTERISIS, val) +#define bfin_read_PORTF_HYSTERESIS() bfin_read16(PORTF_HYSTERESIS) +#define bfin_write_PORTF_HYSTERESIS(val) bfin_write16(PORTF_HYSTERESIS, val) +#define bfin_read_PORTG_HYSTERESIS() bfin_read16(PORTG_HYSTERESIS) +#define bfin_write_PORTG_HYSTERESIS(val) bfin_write16(PORTG_HYSTERESIS, val) +#define bfin_read_PORTH_HYSTERESIS() bfin_read16(PORTH_HYSTERESIS) +#define bfin_write_PORTH_HYSTERESIS(val) bfin_write16(PORTH_HYSTERESIS, val) #define bfin_read_MISCPORT_DRIVE() bfin_read16(MISCPORT_DRIVE) #define bfin_write_MISCPORT_DRIVE(val) bfin_write16(MISCPORT_DRIVE, val) #define bfin_read_MISCPORT_SLEW() bfin_read16(MISCPORT_SLEW) #define bfin_write_MISCPORT_SLEW(val) bfin_write16(MISCPORT_SLEW, val) -#define bfin_read_MISCPORT_HYSTERISIS() bfin_read16(MISCPORT_HYSTERISIS) -#define bfin_write_MISCPORT_HYSTERISIS(val) bfin_write16(MISCPORT_HYSTERISIS, val) +#define bfin_read_MISCPORT_HYSTERESIS() bfin_read16(MISCPORT_HYSTERESIS) +#define bfin_write_MISCPORT_HYSTERESIS(val) bfin_write16(MISCPORT_HYSTERESIS, val) /* HOST Port Registers */ diff --git a/arch/blackfin/mach-bf527/include/mach/defBF522.h b/arch/blackfin/mach-bf527/include/mach/defBF522.h index 84ef11e5264..37d353a1972 100644 --- a/arch/blackfin/mach-bf527/include/mach/defBF522.h +++ b/arch/blackfin/mach-bf527/include/mach/defBF522.h @@ -562,12 +562,12 @@ #define PORTF_SLEW 0xFFC03230 /* Port F slew control */ #define PORTG_SLEW 0xFFC03234 /* Port G slew control */ #define PORTH_SLEW 0xFFC03238 /* Port H slew control */ -#define PORTF_HYSTERISIS 0xFFC03240 /* Port F Schmitt trigger control */ -#define PORTG_HYSTERISIS 0xFFC03244 /* Port G Schmitt trigger control */ -#define PORTH_HYSTERISIS 0xFFC03248 /* Port H Schmitt trigger control */ +#define PORTF_HYSTERESIS 0xFFC03240 /* Port F Schmitt trigger control */ +#define PORTG_HYSTERESIS 0xFFC03244 /* Port G Schmitt trigger control */ +#define PORTH_HYSTERESIS 0xFFC03248 /* Port H Schmitt trigger control */ #define MISCPORT_DRIVE 0xFFC03280 /* Misc Port drive strength control */ #define MISCPORT_SLEW 0xFFC03284 /* Misc Port slew control */ -#define MISCPORT_HYSTERISIS 0xFFC03288 /* Misc Port Schmitt trigger control */ +#define MISCPORT_HYSTERESIS 0xFFC03288 /* Misc Port Schmitt trigger control */ /*********************************************************************************** diff --git a/arch/blackfin/mach-bf527/include/mach/irq.h b/arch/blackfin/mach-bf527/include/mach/irq.h index 704d9253e41..ed7310ff819 100644 --- a/arch/blackfin/mach-bf527/include/mach/irq.h +++ b/arch/blackfin/mach-bf527/include/mach/irq.h @@ -7,38 +7,9 @@ #ifndef _BF527_IRQ_H_ #define _BF527_IRQ_H_ -/* - * Interrupt source definitions - Event Source Core Event Name - Core Emulation ** - Events (highest priority) EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - - ..... - - Software Interrupt 1 IVG14 31 - Software Interrupt 2 -- - (lowest priority) IVG15 32 * -*/ - -#define NR_PERI_INTS (2 * 32) - -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /* Emulation */ -#define IRQ_RST 1 /* reset */ -#define IRQ_NMI 2 /* Non Maskable */ -#define IRQ_EVX 3 /* Exception */ -#define IRQ_UNUSED 4 /* - unused interrupt */ -#define IRQ_HWERR 5 /* Hardware Error */ -#define IRQ_CORETMR 6 /* Core timer */ - -#define BFIN_IRQ(x) ((x) + 7) +#include <mach-common/irq.h> + +#define NR_PERI_INTS (2 * 32) #define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ #define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */ @@ -53,21 +24,21 @@ #define IRQ_UART0_ERROR BFIN_IRQ(12) /* UART0 Status */ #define IRQ_UART1_ERROR BFIN_IRQ(13) /* UART1 Status */ #define IRQ_RTC BFIN_IRQ(14) /* RTC */ -#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI/NAND) */ +#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI/NAND) */ #define IRQ_SPORT0_RX BFIN_IRQ(16) /* DMA 3 Channel (SPORT0 RX) */ #define IRQ_SPORT0_TX BFIN_IRQ(17) /* DMA 4 Channel (SPORT0 TX) */ #define IRQ_SPORT1_RX BFIN_IRQ(18) /* DMA 5 Channel (SPORT1 RX) */ #define IRQ_SPORT1_TX BFIN_IRQ(19) /* DMA 6 Channel (SPORT1 TX) */ -#define IRQ_TWI BFIN_IRQ(20) /* TWI */ -#define IRQ_SPI BFIN_IRQ(21) /* DMA 7 Channel (SPI) */ -#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */ -#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */ -#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */ -#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */ -#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */ -#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */ -#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX/HDMA) */ -#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */ +#define IRQ_TWI BFIN_IRQ(20) /* TWI */ +#define IRQ_SPI BFIN_IRQ(21) /* DMA 7 Channel (SPI) */ +#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */ +#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */ +#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */ +#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */ +#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */ +#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */ +#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX/HDMA) */ +#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */ #define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */ #define IRQ_NFC BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */ #define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */ @@ -96,119 +67,108 @@ #define IRQ_USB_INT2 BFIN_IRQ(54) /* USB_INT2 Interrupt */ #define IRQ_USB_DMA BFIN_IRQ(55) /* USB_DMAINT Interrupt */ -#define SYS_IRQS BFIN_IRQ(63) /* 70 */ - -#define IRQ_PF0 71 -#define IRQ_PF1 72 -#define IRQ_PF2 73 -#define IRQ_PF3 74 -#define IRQ_PF4 75 -#define IRQ_PF5 76 -#define IRQ_PF6 77 -#define IRQ_PF7 78 -#define IRQ_PF8 79 -#define IRQ_PF9 80 -#define IRQ_PF10 81 -#define IRQ_PF11 82 -#define IRQ_PF12 83 -#define IRQ_PF13 84 -#define IRQ_PF14 85 -#define IRQ_PF15 86 - -#define IRQ_PG0 87 -#define IRQ_PG1 88 -#define IRQ_PG2 89 -#define IRQ_PG3 90 -#define IRQ_PG4 91 -#define IRQ_PG5 92 -#define IRQ_PG6 93 -#define IRQ_PG7 94 -#define IRQ_PG8 95 -#define IRQ_PG9 96 -#define IRQ_PG10 97 -#define IRQ_PG11 98 -#define IRQ_PG12 99 -#define IRQ_PG13 100 -#define IRQ_PG14 101 -#define IRQ_PG15 102 - -#define IRQ_PH0 103 -#define IRQ_PH1 104 -#define IRQ_PH2 105 -#define IRQ_PH3 106 -#define IRQ_PH4 107 -#define IRQ_PH5 108 -#define IRQ_PH6 109 -#define IRQ_PH7 110 -#define IRQ_PH8 111 -#define IRQ_PH9 112 -#define IRQ_PH10 113 -#define IRQ_PH11 114 -#define IRQ_PH12 115 -#define IRQ_PH13 116 -#define IRQ_PH14 117 -#define IRQ_PH15 118 - -#define GPIO_IRQ_BASE IRQ_PF0 - -#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */ -#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */ -#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */ -#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */ -#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */ -#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */ -#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */ -#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */ - -#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 +#define SYS_IRQS BFIN_IRQ(63) /* 70 */ + +#define IRQ_PF0 71 +#define IRQ_PF1 72 +#define IRQ_PF2 73 +#define IRQ_PF3 74 +#define IRQ_PF4 75 +#define IRQ_PF5 76 +#define IRQ_PF6 77 +#define IRQ_PF7 78 +#define IRQ_PF8 79 +#define IRQ_PF9 80 +#define IRQ_PF10 81 +#define IRQ_PF11 82 +#define IRQ_PF12 83 +#define IRQ_PF13 84 +#define IRQ_PF14 85 +#define IRQ_PF15 86 + +#define IRQ_PG0 87 +#define IRQ_PG1 88 +#define IRQ_PG2 89 +#define IRQ_PG3 90 +#define IRQ_PG4 91 +#define IRQ_PG5 92 +#define IRQ_PG6 93 +#define IRQ_PG7 94 +#define IRQ_PG8 95 +#define IRQ_PG9 96 +#define IRQ_PG10 97 +#define IRQ_PG11 98 +#define IRQ_PG12 99 +#define IRQ_PG13 100 +#define IRQ_PG14 101 +#define IRQ_PG15 102 + +#define IRQ_PH0 103 +#define IRQ_PH1 104 +#define IRQ_PH2 105 +#define IRQ_PH3 106 +#define IRQ_PH4 107 +#define IRQ_PH5 108 +#define IRQ_PH6 109 +#define IRQ_PH7 110 +#define IRQ_PH8 111 +#define IRQ_PH9 112 +#define IRQ_PH10 113 +#define IRQ_PH11 114 +#define IRQ_PH12 115 +#define IRQ_PH13 116 +#define IRQ_PH14 117 +#define IRQ_PH15 118 + +#define GPIO_IRQ_BASE IRQ_PF0 + +#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */ +#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */ +#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */ +#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */ +#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */ +#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */ +#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */ +#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */ + +#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1) /* IAR0 BIT FIELDS */ #define IRQ_PLL_WAKEUP_POS 0 #define IRQ_DMA0_ERROR_POS 4 -#define IRQ_DMAR0_BLK_POS 8 -#define IRQ_DMAR1_BLK_POS 12 -#define IRQ_DMAR0_OVR_POS 16 -#define IRQ_DMAR1_OVR_POS 20 -#define IRQ_PPI_ERROR_POS 24 -#define IRQ_MAC_ERROR_POS 28 +#define IRQ_DMAR0_BLK_POS 8 +#define IRQ_DMAR1_BLK_POS 12 +#define IRQ_DMAR0_OVR_POS 16 +#define IRQ_DMAR1_OVR_POS 20 +#define IRQ_PPI_ERROR_POS 24 +#define IRQ_MAC_ERROR_POS 28 /* IAR1 BIT FIELDS */ #define IRQ_SPORT0_ERROR_POS 0 #define IRQ_SPORT1_ERROR_POS 4 -#define IRQ_UART0_ERROR_POS 16 -#define IRQ_UART1_ERROR_POS 20 -#define IRQ_RTC_POS 24 -#define IRQ_PPI_POS 28 +#define IRQ_UART0_ERROR_POS 16 +#define IRQ_UART1_ERROR_POS 20 +#define IRQ_RTC_POS 24 +#define IRQ_PPI_POS 28 /* IAR2 BIT FIELDS */ #define IRQ_SPORT0_RX_POS 0 #define IRQ_SPORT0_TX_POS 4 #define IRQ_SPORT1_RX_POS 8 #define IRQ_SPORT1_TX_POS 12 -#define IRQ_TWI_POS 16 -#define IRQ_SPI_POS 20 -#define IRQ_UART0_RX_POS 24 -#define IRQ_UART0_TX_POS 28 +#define IRQ_TWI_POS 16 +#define IRQ_SPI_POS 20 +#define IRQ_UART0_RX_POS 24 +#define IRQ_UART0_TX_POS 28 /* IAR3 BIT FIELDS */ -#define IRQ_UART1_RX_POS 0 -#define IRQ_UART1_TX_POS 4 -#define IRQ_OPTSEC_POS 8 -#define IRQ_CNT_POS 12 -#define IRQ_MAC_RX_POS 16 +#define IRQ_UART1_RX_POS 0 +#define IRQ_UART1_TX_POS 4 +#define IRQ_OPTSEC_POS 8 +#define IRQ_CNT_POS 12 +#define IRQ_MAC_RX_POS 16 #define IRQ_PORTH_INTA_POS 20 -#define IRQ_MAC_TX_POS 24 +#define IRQ_MAC_TX_POS 24 #define IRQ_PORTH_INTB_POS 28 /* IAR4 BIT FIELDS */ @@ -224,21 +184,21 @@ /* IAR5 BIT FIELDS */ #define IRQ_PORTG_INTA_POS 0 #define IRQ_PORTG_INTB_POS 4 -#define IRQ_MEM_DMA0_POS 8 -#define IRQ_MEM_DMA1_POS 12 -#define IRQ_WATCH_POS 16 +#define IRQ_MEM_DMA0_POS 8 +#define IRQ_MEM_DMA1_POS 12 +#define IRQ_WATCH_POS 16 #define IRQ_PORTF_INTA_POS 20 #define IRQ_PORTF_INTB_POS 24 -#define IRQ_SPI_ERROR_POS 28 +#define IRQ_SPI_ERROR_POS 28 /* IAR6 BIT FIELDS */ -#define IRQ_NFC_ERROR_POS 0 -#define IRQ_HDMA_ERROR_POS 4 -#define IRQ_HDMA_POS 8 -#define IRQ_USB_EINT_POS 12 -#define IRQ_USB_INT0_POS 16 -#define IRQ_USB_INT1_POS 20 -#define IRQ_USB_INT2_POS 24 -#define IRQ_USB_DMA_POS 28 - -#endif /* _BF527_IRQ_H_ */ +#define IRQ_NFC_ERROR_POS 0 +#define IRQ_HDMA_ERROR_POS 4 +#define IRQ_HDMA_POS 8 +#define IRQ_USB_EINT_POS 12 +#define IRQ_USB_INT0_POS 16 +#define IRQ_USB_INT1_POS 20 +#define IRQ_USB_INT2_POS 24 +#define IRQ_USB_DMA_POS 28 + +#endif diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h index 78f87218791..72aa59440f8 100644 --- a/arch/blackfin/mach-bf533/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h @@ -5,13 +5,13 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: - * - Revision E, 09/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List + * - Revision F, 05/25/2010; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -206,6 +206,10 @@ #define ANOMALY_05000443 (1) /* False Hardware Error when RETI Points to Invalid Memory */ #define ANOMALY_05000461 (1) +/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */ +#define ANOMALY_05000462 (1) +/* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */ +#define ANOMALY_05000471 (1) /* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */ #define ANOMALY_05000473 (1) /* Possible Lockup Condition whem Modifying PLL from External Memory */ @@ -351,12 +355,14 @@ #define ANOMALY_05000362 (1) #define ANOMALY_05000364 (0) #define ANOMALY_05000380 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000386 (1) #define ANOMALY_05000389 (0) #define ANOMALY_05000412 (0) #define ANOMALY_05000430 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) +#define ANOMALY_05000440 (0) #define ANOMALY_05000447 (0) #define ANOMALY_05000448 (0) #define ANOMALY_05000456 (0) @@ -364,6 +370,7 @@ #define ANOMALY_05000465 (0) #define ANOMALY_05000467 (0) #define ANOMALY_05000474 (0) +#define ANOMALY_05000480 (0) #define ANOMALY_05000485 (0) #endif diff --git a/arch/blackfin/mach-bf533/include/mach/irq.h b/arch/blackfin/mach-bf533/include/mach/irq.h index 1f7e9765d95..70973375414 100644 --- a/arch/blackfin/mach-bf533/include/mach/irq.h +++ b/arch/blackfin/mach-bf533/include/mach/irq.h @@ -7,83 +7,36 @@ #ifndef _BF533_IRQ_H_ #define _BF533_IRQ_H_ -/* - * Interrupt source definitions - Event Source Core Event Name -Core Emulation ** - Events (highest priority) EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - PLL Wakeup Interrupt IVG7 7 - DMA Error (generic) IVG7 8 - PPI Error Interrupt IVG7 9 - SPORT0 Error Interrupt IVG7 10 - SPORT1 Error Interrupt IVG7 11 - SPI Error Interrupt IVG7 12 - UART Error Interrupt IVG7 13 - RTC Interrupt IVG8 14 - DMA0 Interrupt (PPI) IVG8 15 - DMA1 (SPORT0 RX) IVG9 16 - DMA2 (SPORT0 TX) IVG9 17 - DMA3 (SPORT1 RX) IVG9 18 - DMA4 (SPORT1 TX) IVG9 19 - DMA5 (PPI) IVG10 20 - DMA6 (UART RX) IVG10 21 - DMA7 (UART TX) IVG10 22 - Timer0 IVG11 23 - Timer1 IVG11 24 - Timer2 IVG11 25 - PF Interrupt A IVG12 26 - PF Interrupt B IVG12 27 - DMA8/9 Interrupt IVG13 28 - DMA10/11 Interrupt IVG13 29 - Watchdog Timer IVG13 30 +#include <mach-common/irq.h> - Softirq IVG14 31 - System Call -- - (lowest priority) IVG15 32 * - */ -#define SYS_IRQS 31 -#define NR_PERI_INTS 24 +#define NR_PERI_INTS 24 -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /*Emulation */ -#define IRQ_RST 1 /*reset */ -#define IRQ_NMI 2 /*Non Maskable */ -#define IRQ_EVX 3 /*Exception */ -#define IRQ_UNUSED 4 /*- unused interrupt*/ -#define IRQ_HWERR 5 /*Hardware Error */ -#define IRQ_CORETMR 6 /*Core timer */ +#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ +#define IRQ_DMA_ERROR BFIN_IRQ(1) /* DMA Error (general) */ +#define IRQ_PPI_ERROR BFIN_IRQ(2) /* PPI Error Interrupt */ +#define IRQ_SPORT0_ERROR BFIN_IRQ(3) /* SPORT0 Error Interrupt */ +#define IRQ_SPORT1_ERROR BFIN_IRQ(4) /* SPORT1 Error Interrupt */ +#define IRQ_SPI_ERROR BFIN_IRQ(5) /* SPI Error Interrupt */ +#define IRQ_UART0_ERROR BFIN_IRQ(6) /* UART Error Interrupt */ +#define IRQ_RTC BFIN_IRQ(7) /* RTC Interrupt */ +#define IRQ_PPI BFIN_IRQ(8) /* DMA0 Interrupt (PPI) */ +#define IRQ_SPORT0_RX BFIN_IRQ(9) /* DMA1 Interrupt (SPORT0 RX) */ +#define IRQ_SPORT0_TX BFIN_IRQ(10) /* DMA2 Interrupt (SPORT0 TX) */ +#define IRQ_SPORT1_RX BFIN_IRQ(11) /* DMA3 Interrupt (SPORT1 RX) */ +#define IRQ_SPORT1_TX BFIN_IRQ(12) /* DMA4 Interrupt (SPORT1 TX) */ +#define IRQ_SPI BFIN_IRQ(13) /* DMA5 Interrupt (SPI) */ +#define IRQ_UART0_RX BFIN_IRQ(14) /* DMA6 Interrupt (UART RX) */ +#define IRQ_UART0_TX BFIN_IRQ(15) /* DMA7 Interrupt (UART TX) */ +#define IRQ_TIMER0 BFIN_IRQ(16) /* Timer 0 */ +#define IRQ_TIMER1 BFIN_IRQ(17) /* Timer 1 */ +#define IRQ_TIMER2 BFIN_IRQ(18) /* Timer 2 */ +#define IRQ_PROG_INTA BFIN_IRQ(19) /* Programmable Flags A (8) */ +#define IRQ_PROG_INTB BFIN_IRQ(20) /* Programmable Flags B (8) */ +#define IRQ_MEM_DMA0 BFIN_IRQ(21) /* DMA8/9 Interrupt (Memory DMA Stream 0) */ +#define IRQ_MEM_DMA1 BFIN_IRQ(22) /* DMA10/11 Interrupt (Memory DMA Stream 1) */ +#define IRQ_WATCH BFIN_IRQ(23) /* Watch Dog Timer */ -#define IRQ_PLL_WAKEUP 7 /*PLL Wakeup Interrupt */ -#define IRQ_DMA_ERROR 8 /*DMA Error (general) */ -#define IRQ_PPI_ERROR 9 /*PPI Error Interrupt */ -#define IRQ_SPORT0_ERROR 10 /*SPORT0 Error Interrupt */ -#define IRQ_SPORT1_ERROR 11 /*SPORT1 Error Interrupt */ -#define IRQ_SPI_ERROR 12 /*SPI Error Interrupt */ -#define IRQ_UART0_ERROR 13 /*UART Error Interrupt */ -#define IRQ_RTC 14 /*RTC Interrupt */ -#define IRQ_PPI 15 /*DMA0 Interrupt (PPI) */ -#define IRQ_SPORT0_RX 16 /*DMA1 Interrupt (SPORT0 RX) */ -#define IRQ_SPORT0_TX 17 /*DMA2 Interrupt (SPORT0 TX) */ -#define IRQ_SPORT1_RX 18 /*DMA3 Interrupt (SPORT1 RX) */ -#define IRQ_SPORT1_TX 19 /*DMA4 Interrupt (SPORT1 TX) */ -#define IRQ_SPI 20 /*DMA5 Interrupt (SPI) */ -#define IRQ_UART0_RX 21 /*DMA6 Interrupt (UART RX) */ -#define IRQ_UART0_TX 22 /*DMA7 Interrupt (UART TX) */ -#define IRQ_TIMER0 23 /*Timer 0 */ -#define IRQ_TIMER1 24 /*Timer 1 */ -#define IRQ_TIMER2 25 /*Timer 2 */ -#define IRQ_PROG_INTA 26 /*Programmable Flags A (8) */ -#define IRQ_PROG_INTB 27 /*Programmable Flags B (8) */ -#define IRQ_MEM_DMA0 28 /*DMA8/9 Interrupt (Memory DMA Stream 0) */ -#define IRQ_MEM_DMA1 29 /*DMA10/11 Interrupt (Memory DMA Stream 1) */ -#define IRQ_WATCH 30 /*Watch Dog Timer */ +#define SYS_IRQS 31 #define IRQ_PF0 33 #define IRQ_PF1 34 @@ -105,46 +58,35 @@ Core Emulation ** #define GPIO_IRQ_BASE IRQ_PF0 #define NR_MACH_IRQS (IRQ_PF15 + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 -/* IAR0 BIT FIELDS*/ -#define RTC_ERROR_POS 28 -#define UART_ERROR_POS 24 -#define SPORT1_ERROR_POS 20 -#define SPI_ERROR_POS 16 -#define SPORT0_ERROR_POS 12 -#define PPI_ERROR_POS 8 -#define DMA_ERROR_POS 4 -#define PLLWAKE_ERROR_POS 0 +/* IAR0 BIT FIELDS */ +#define RTC_ERROR_POS 28 +#define UART_ERROR_POS 24 +#define SPORT1_ERROR_POS 20 +#define SPI_ERROR_POS 16 +#define SPORT0_ERROR_POS 12 +#define PPI_ERROR_POS 8 +#define DMA_ERROR_POS 4 +#define PLLWAKE_ERROR_POS 0 -/* IAR1 BIT FIELDS*/ -#define DMA7_UARTTX_POS 28 -#define DMA6_UARTRX_POS 24 -#define DMA5_SPI_POS 20 -#define DMA4_SPORT1TX_POS 16 -#define DMA3_SPORT1RX_POS 12 -#define DMA2_SPORT0TX_POS 8 -#define DMA1_SPORT0RX_POS 4 -#define DMA0_PPI_POS 0 +/* IAR1 BIT FIELDS */ +#define DMA7_UARTTX_POS 28 +#define DMA6_UARTRX_POS 24 +#define DMA5_SPI_POS 20 +#define DMA4_SPORT1TX_POS 16 +#define DMA3_SPORT1RX_POS 12 +#define DMA2_SPORT0TX_POS 8 +#define DMA1_SPORT0RX_POS 4 +#define DMA0_PPI_POS 0 -/* IAR2 BIT FIELDS*/ -#define WDTIMER_POS 28 -#define MEMDMA1_POS 24 -#define MEMDMA0_POS 20 -#define PFB_POS 16 -#define PFA_POS 12 -#define TIMER2_POS 8 -#define TIMER1_POS 4 -#define TIMER0_POS 0 +/* IAR2 BIT FIELDS */ +#define WDTIMER_POS 28 +#define MEMDMA1_POS 24 +#define MEMDMA0_POS 20 +#define PFB_POS 16 +#define PFA_POS 12 +#define TIMER2_POS 8 +#define TIMER1_POS 4 +#define TIMER0_POS 0 -#endif /* _BF533_IRQ_H_ */ +#endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 3fa335405b3..e16dc456004 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -35,6 +35,7 @@ #include <asm/reboot.h> #include <asm/portmux.h> #include <asm/dpmc.h> +#include <asm/bfin_sport.h> #ifdef CONFIG_REGULATOR_FIXED_VOLTAGE #include <linux/regulator/fixed.h> #endif @@ -2585,27 +2586,103 @@ static struct platform_device bfin_dpmc = { }, }; -#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ + defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) + +#define SPORT_REQ(x) \ + [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ + P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} + +static const u16 bfin_snd_pin[][7] = { + SPORT_REQ(0), + SPORT_REQ(1), +}; + +static struct bfin_snd_platform_data bfin_snd_data[] = { + { + .pin_req = &bfin_snd_pin[0][0], + }, + { + .pin_req = &bfin_snd_pin[1][0], + }, +}; + +#define BFIN_SND_RES(x) \ + [x] = { \ + { \ + .start = SPORT##x##_TCR1, \ + .end = SPORT##x##_TCR1, \ + .flags = IORESOURCE_MEM \ + }, \ + { \ + .start = CH_SPORT##x##_RX, \ + .end = CH_SPORT##x##_RX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = CH_SPORT##x##_TX, \ + .end = CH_SPORT##x##_TX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = IRQ_SPORT##x##_ERROR, \ + .end = IRQ_SPORT##x##_ERROR, \ + .flags = IORESOURCE_IRQ, \ + } \ + } + +static struct resource bfin_snd_resources[][4] = { + BFIN_SND_RES(0), + BFIN_SND_RES(1), +}; + +static struct platform_device bfin_pcm = { + .name = "bfin-pcm-audio", + .id = -1, +}; +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) +static struct platform_device bfin_ad73311_codec_device = { + .name = "ad73311", + .id = -1, +}; +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE) static struct platform_device bfin_i2s = { .name = "bfin-i2s", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif -#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) static struct platform_device bfin_tdm = { .name = "bfin-tdm", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif -#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) static struct platform_device bfin_ac97 = { .name = "bfin-ac97", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif @@ -2796,17 +2873,28 @@ static struct platform_device *stamp_devices[] __initdata = { &stamp_flash_device, #endif -#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ + defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) + &bfin_pcm, +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) + &bfin_ad73311_codec_device, +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE) &bfin_i2s, #endif -#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) &bfin_tdm, #endif -#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) &bfin_ac97, #endif + #if defined(CONFIG_REGULATOR_AD5398) || defined(CONFIG_REGULATOR_AD5398_MODULE) #if defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER) || \ defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER_MODULE) diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h index 43df6afd22a..7f8e5a9f5db 100644 --- a/arch/blackfin/mach-bf537/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h @@ -5,13 +5,13 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: - * - Revision D, 09/18/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List + * - Revision E, 05/25/2010; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -160,12 +160,16 @@ #define ANOMALY_05000443 (1) /* False Hardware Error when RETI Points to Invalid Memory */ #define ANOMALY_05000461 (1) +/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */ +#define ANOMALY_05000462 (1) /* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */ #define ANOMALY_05000473 (1) /* Possible Lockup Condition whem Modifying PLL from External Memory */ #define ANOMALY_05000475 (1) /* TESTSET Instruction Cannot Be Interrupted */ #define ANOMALY_05000477 (1) +/* Multiple Simultaneous Urgent DMA Requests May Cause DMA System Instability */ +#define ANOMALY_05000480 (__SILICON_REVISION__ < 3) /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */ #define ANOMALY_05000481 (1) /* IFLUSH sucks at life */ @@ -204,6 +208,7 @@ #define ANOMALY_05000363 (0) #define ANOMALY_05000364 (0) #define ANOMALY_05000380 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000386 (1) #define ANOMALY_05000389 (0) #define ANOMALY_05000400 (0) @@ -211,6 +216,7 @@ #define ANOMALY_05000430 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) +#define ANOMALY_05000440 (0) #define ANOMALY_05000447 (0) #define ANOMALY_05000448 (0) #define ANOMALY_05000456 (0) diff --git a/arch/blackfin/mach-bf537/include/mach/irq.h b/arch/blackfin/mach-bf537/include/mach/irq.h index 1a6d617c5fc..b6ed8235bda 100644 --- a/arch/blackfin/mach-bf537/include/mach/irq.h +++ b/arch/blackfin/mach-bf537/include/mach/irq.h @@ -7,193 +7,178 @@ #ifndef _BF537_IRQ_H_ #define _BF537_IRQ_H_ -/* - * Interrupt source definitions - * Event Source Core Event Name - * Core Emulation ** - * Events (highest priority) EMU 0 - * Reset RST 1 - * NMI NMI 2 - * Exception EVX 3 - * Reserved -- 4 - * Hardware Error IVHW 5 - * Core Timer IVTMR 6 - * ..... - * - * Softirq IVG14 - * System Call -- - * (lowest priority) IVG15 - */ - -#define SYS_IRQS 39 -#define NR_PERI_INTS 32 - -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /*Emulation */ -#define IRQ_RST 1 /*reset */ -#define IRQ_NMI 2 /*Non Maskable */ -#define IRQ_EVX 3 /*Exception */ -#define IRQ_UNUSED 4 /*- unused interrupt*/ -#define IRQ_HWERR 5 /*Hardware Error */ -#define IRQ_CORETMR 6 /*Core timer */ - -#define IRQ_PLL_WAKEUP 7 /*PLL Wakeup Interrupt */ -#define IRQ_DMA_ERROR 8 /*DMA Error (general) */ -#define IRQ_GENERIC_ERROR 9 /*GENERIC Error Interrupt */ -#define IRQ_RTC 10 /*RTC Interrupt */ -#define IRQ_PPI 11 /*DMA0 Interrupt (PPI) */ -#define IRQ_SPORT0_RX 12 /*DMA3 Interrupt (SPORT0 RX) */ -#define IRQ_SPORT0_TX 13 /*DMA4 Interrupt (SPORT0 TX) */ -#define IRQ_SPORT1_RX 14 /*DMA5 Interrupt (SPORT1 RX) */ -#define IRQ_SPORT1_TX 15 /*DMA6 Interrupt (SPORT1 TX) */ -#define IRQ_TWI 16 /*TWI Interrupt */ -#define IRQ_SPI 17 /*DMA7 Interrupt (SPI) */ -#define IRQ_UART0_RX 18 /*DMA8 Interrupt (UART0 RX) */ -#define IRQ_UART0_TX 19 /*DMA9 Interrupt (UART0 TX) */ -#define IRQ_UART1_RX 20 /*DMA10 Interrupt (UART1 RX) */ -#define IRQ_UART1_TX 21 /*DMA11 Interrupt (UART1 TX) */ -#define IRQ_CAN_RX 22 /*CAN Receive Interrupt */ -#define IRQ_CAN_TX 23 /*CAN Transmit Interrupt */ -#define IRQ_MAC_RX 24 /*DMA1 (Ethernet RX) Interrupt */ -#define IRQ_MAC_TX 25 /*DMA2 (Ethernet TX) Interrupt */ -#define IRQ_TIMER0 26 /*Timer 0 */ -#define IRQ_TIMER1 27 /*Timer 1 */ -#define IRQ_TIMER2 28 /*Timer 2 */ -#define IRQ_TIMER3 29 /*Timer 3 */ -#define IRQ_TIMER4 30 /*Timer 4 */ -#define IRQ_TIMER5 31 /*Timer 5 */ -#define IRQ_TIMER6 32 /*Timer 6 */ -#define IRQ_TIMER7 33 /*Timer 7 */ -#define IRQ_PROG_INTA 34 /* PF Ports F&G (PF15:0) Interrupt A */ -#define IRQ_PORTG_INTB 35 /* PF Port G (PF15:0) Interrupt B */ -#define IRQ_MEM_DMA0 36 /*(Memory DMA Stream 0) */ -#define IRQ_MEM_DMA1 37 /*(Memory DMA Stream 1) */ -#define IRQ_PROG_INTB 38 /* PF Ports F (PF15:0) Interrupt B */ -#define IRQ_WATCH 38 /*Watch Dog Timer */ - -#define IRQ_PPI_ERROR 42 /*PPI Error Interrupt */ -#define IRQ_CAN_ERROR 43 /*CAN Error Interrupt */ -#define IRQ_MAC_ERROR 44 /*MAC Status/Error Interrupt */ -#define IRQ_SPORT0_ERROR 45 /*SPORT0 Error Interrupt */ -#define IRQ_SPORT1_ERROR 46 /*SPORT1 Error Interrupt */ -#define IRQ_SPI_ERROR 47 /*SPI Error Interrupt */ -#define IRQ_UART0_ERROR 48 /*UART Error Interrupt */ -#define IRQ_UART1_ERROR 49 /*UART Error Interrupt */ - -#define IRQ_PF0 50 -#define IRQ_PF1 51 -#define IRQ_PF2 52 -#define IRQ_PF3 53 -#define IRQ_PF4 54 -#define IRQ_PF5 55 -#define IRQ_PF6 56 -#define IRQ_PF7 57 -#define IRQ_PF8 58 -#define IRQ_PF9 59 -#define IRQ_PF10 60 -#define IRQ_PF11 61 -#define IRQ_PF12 62 -#define IRQ_PF13 63 -#define IRQ_PF14 64 -#define IRQ_PF15 65 - -#define IRQ_PG0 66 -#define IRQ_PG1 67 -#define IRQ_PG2 68 -#define IRQ_PG3 69 -#define IRQ_PG4 70 -#define IRQ_PG5 71 -#define IRQ_PG6 72 -#define IRQ_PG7 73 -#define IRQ_PG8 74 -#define IRQ_PG9 75 -#define IRQ_PG10 76 -#define IRQ_PG11 77 -#define IRQ_PG12 78 -#define IRQ_PG13 79 -#define IRQ_PG14 80 -#define IRQ_PG15 81 - -#define IRQ_PH0 82 -#define IRQ_PH1 83 -#define IRQ_PH2 84 -#define IRQ_PH3 85 -#define IRQ_PH4 86 -#define IRQ_PH5 87 -#define IRQ_PH6 88 -#define IRQ_PH7 89 -#define IRQ_PH8 90 -#define IRQ_PH9 91 -#define IRQ_PH10 92 -#define IRQ_PH11 93 -#define IRQ_PH12 94 -#define IRQ_PH13 95 -#define IRQ_PH14 96 -#define IRQ_PH15 97 - -#define GPIO_IRQ_BASE IRQ_PF0 - -#define IRQ_MAC_PHYINT 98 /* PHY_INT Interrupt */ -#define IRQ_MAC_MMCINT 99 /* MMC Counter Interrupt */ -#define IRQ_MAC_RXFSINT 100 /* RX Frame-Status Interrupt */ -#define IRQ_MAC_TXFSINT 101 /* TX Frame-Status Interrupt */ -#define IRQ_MAC_WAKEDET 102 /* Wake-Up Interrupt */ -#define IRQ_MAC_RXDMAERR 103 /* RX DMA Direction Error Interrupt */ -#define IRQ_MAC_TXDMAERR 104 /* TX DMA Direction Error Interrupt */ -#define IRQ_MAC_STMDONE 105 /* Station Mgt. Transfer Done Interrupt */ - -#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 - -/* IAR0 BIT FIELDS*/ -#define IRQ_PLL_WAKEUP_POS 0 -#define IRQ_DMA_ERROR_POS 4 -#define IRQ_ERROR_POS 8 -#define IRQ_RTC_POS 12 -#define IRQ_PPI_POS 16 -#define IRQ_SPORT0_RX_POS 20 -#define IRQ_SPORT0_TX_POS 24 -#define IRQ_SPORT1_RX_POS 28 - -/* IAR1 BIT FIELDS*/ -#define IRQ_SPORT1_TX_POS 0 -#define IRQ_TWI_POS 4 -#define IRQ_SPI_POS 8 -#define IRQ_UART0_RX_POS 12 -#define IRQ_UART0_TX_POS 16 -#define IRQ_UART1_RX_POS 20 -#define IRQ_UART1_TX_POS 24 -#define IRQ_CAN_RX_POS 28 - -/* IAR2 BIT FIELDS*/ -#define IRQ_CAN_TX_POS 0 -#define IRQ_MAC_RX_POS 4 -#define IRQ_MAC_TX_POS 8 -#define IRQ_TIMER0_POS 12 -#define IRQ_TIMER1_POS 16 -#define IRQ_TIMER2_POS 20 -#define IRQ_TIMER3_POS 24 -#define IRQ_TIMER4_POS 28 - -/* IAR3 BIT FIELDS*/ -#define IRQ_TIMER5_POS 0 -#define IRQ_TIMER6_POS 4 -#define IRQ_TIMER7_POS 8 -#define IRQ_PROG_INTA_POS 12 -#define IRQ_PORTG_INTB_POS 16 -#define IRQ_MEM_DMA0_POS 20 -#define IRQ_MEM_DMA1_POS 24 -#define IRQ_WATCH_POS 28 - -#endif /* _BF537_IRQ_H_ */ +#include <mach-common/irq.h> + +#define NR_PERI_INTS 32 + +#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ +#define IRQ_DMA_ERROR BFIN_IRQ(1) /* DMA Error (general) */ +#define IRQ_GENERIC_ERROR BFIN_IRQ(2) /* GENERIC Error Interrupt */ +#define IRQ_RTC BFIN_IRQ(3) /* RTC Interrupt */ +#define IRQ_PPI BFIN_IRQ(4) /* DMA0 Interrupt (PPI) */ +#define IRQ_SPORT0_RX BFIN_IRQ(5) /* DMA3 Interrupt (SPORT0 RX) */ +#define IRQ_SPORT0_TX BFIN_IRQ(6) /* DMA4 Interrupt (SPORT0 TX) */ +#define IRQ_SPORT1_RX BFIN_IRQ(7) /* DMA5 Interrupt (SPORT1 RX) */ +#define IRQ_SPORT1_TX BFIN_IRQ(8) /* DMA6 Interrupt (SPORT1 TX) */ +#define IRQ_TWI BFIN_IRQ(9) /* TWI Interrupt */ +#define IRQ_SPI BFIN_IRQ(10) /* DMA7 Interrupt (SPI) */ +#define IRQ_UART0_RX BFIN_IRQ(11) /* DMA8 Interrupt (UART0 RX) */ +#define IRQ_UART0_TX BFIN_IRQ(12) /* DMA9 Interrupt (UART0 TX) */ +#define IRQ_UART1_RX BFIN_IRQ(13) /* DMA10 Interrupt (UART1 RX) */ +#define IRQ_UART1_TX BFIN_IRQ(14) /* DMA11 Interrupt (UART1 TX) */ +#define IRQ_CAN_RX BFIN_IRQ(15) /* CAN Receive Interrupt */ +#define IRQ_CAN_TX BFIN_IRQ(16) /* CAN Transmit Interrupt */ +#define IRQ_PH_INTA_MAC_RX BFIN_IRQ(17) /* Port H Interrupt A & DMA1 Interrupt (Ethernet RX) */ +#define IRQ_PH_INTB_MAC_TX BFIN_IRQ(18) /* Port H Interrupt B & DMA2 Interrupt (Ethernet TX) */ +#define IRQ_TIMER0 BFIN_IRQ(19) /* Timer 0 */ +#define IRQ_TIMER1 BFIN_IRQ(20) /* Timer 1 */ +#define IRQ_TIMER2 BFIN_IRQ(21) /* Timer 2 */ +#define IRQ_TIMER3 BFIN_IRQ(22) /* Timer 3 */ +#define IRQ_TIMER4 BFIN_IRQ(23) /* Timer 4 */ +#define IRQ_TIMER5 BFIN_IRQ(24) /* Timer 5 */ +#define IRQ_TIMER6 BFIN_IRQ(25) /* Timer 6 */ +#define IRQ_TIMER7 BFIN_IRQ(26) /* Timer 7 */ +#define IRQ_PF_INTA_PG_INTA BFIN_IRQ(27) /* Ports F&G Interrupt A */ +#define IRQ_PORTG_INTB BFIN_IRQ(28) /* Port G Interrupt B */ +#define IRQ_MEM_DMA0 BFIN_IRQ(29) /* (Memory DMA Stream 0) */ +#define IRQ_MEM_DMA1 BFIN_IRQ(30) /* (Memory DMA Stream 1) */ +#define IRQ_PF_INTB_WATCH BFIN_IRQ(31) /* Watchdog & Port F Interrupt B */ + +#define SYS_IRQS 39 + +#define IRQ_PPI_ERROR 42 /* PPI Error Interrupt */ +#define IRQ_CAN_ERROR 43 /* CAN Error Interrupt */ +#define IRQ_MAC_ERROR 44 /* MAC Status/Error Interrupt */ +#define IRQ_SPORT0_ERROR 45 /* SPORT0 Error Interrupt */ +#define IRQ_SPORT1_ERROR 46 /* SPORT1 Error Interrupt */ +#define IRQ_SPI_ERROR 47 /* SPI Error Interrupt */ +#define IRQ_UART0_ERROR 48 /* UART Error Interrupt */ +#define IRQ_UART1_ERROR 49 /* UART Error Interrupt */ + +#define IRQ_PF0 50 +#define IRQ_PF1 51 +#define IRQ_PF2 52 +#define IRQ_PF3 53 +#define IRQ_PF4 54 +#define IRQ_PF5 55 +#define IRQ_PF6 56 +#define IRQ_PF7 57 +#define IRQ_PF8 58 +#define IRQ_PF9 59 +#define IRQ_PF10 60 +#define IRQ_PF11 61 +#define IRQ_PF12 62 +#define IRQ_PF13 63 +#define IRQ_PF14 64 +#define IRQ_PF15 65 + +#define IRQ_PG0 66 +#define IRQ_PG1 67 +#define IRQ_PG2 68 +#define IRQ_PG3 69 +#define IRQ_PG4 70 +#define IRQ_PG5 71 +#define IRQ_PG6 72 +#define IRQ_PG7 73 +#define IRQ_PG8 74 +#define IRQ_PG9 75 +#define IRQ_PG10 76 +#define IRQ_PG11 77 +#define IRQ_PG12 78 +#define IRQ_PG13 79 +#define IRQ_PG14 80 +#define IRQ_PG15 81 + +#define IRQ_PH0 82 +#define IRQ_PH1 83 +#define IRQ_PH2 84 +#define IRQ_PH3 85 +#define IRQ_PH4 86 +#define IRQ_PH5 87 +#define IRQ_PH6 88 +#define IRQ_PH7 89 +#define IRQ_PH8 90 +#define IRQ_PH9 91 +#define IRQ_PH10 92 +#define IRQ_PH11 93 +#define IRQ_PH12 94 +#define IRQ_PH13 95 +#define IRQ_PH14 96 +#define IRQ_PH15 97 + +#define GPIO_IRQ_BASE IRQ_PF0 + +#define IRQ_MAC_PHYINT 98 /* PHY_INT Interrupt */ +#define IRQ_MAC_MMCINT 99 /* MMC Counter Interrupt */ +#define IRQ_MAC_RXFSINT 100 /* RX Frame-Status Interrupt */ +#define IRQ_MAC_TXFSINT 101 /* TX Frame-Status Interrupt */ +#define IRQ_MAC_WAKEDET 102 /* Wake-Up Interrupt */ +#define IRQ_MAC_RXDMAERR 103 /* RX DMA Direction Error Interrupt */ +#define IRQ_MAC_TXDMAERR 104 /* TX DMA Direction Error Interrupt */ +#define IRQ_MAC_STMDONE 105 /* Station Mgt. Transfer Done Interrupt */ + +#define IRQ_MAC_RX 106 /* DMA1 Interrupt (Ethernet RX) */ +#define IRQ_PORTH_INTA 107 /* Port H Interrupt A */ + +#if 0 /* No Interrupt B support (yet) */ +#define IRQ_MAC_TX 108 /* DMA2 Interrupt (Ethernet TX) */ +#define IRQ_PORTH_INTB 109 /* Port H Interrupt B */ +#else +#define IRQ_MAC_TX IRQ_PH_INTB_MAC_TX +#endif + +#define IRQ_PORTF_INTA 110 /* Port F Interrupt A */ +#define IRQ_PORTG_INTA 111 /* Port G Interrupt A */ + +#if 0 /* No Interrupt B support (yet) */ +#define IRQ_WATCH 112 /* Watchdog Timer */ +#define IRQ_PORTF_INTB 113 /* Port F Interrupt B */ +#else +#define IRQ_WATCH IRQ_PF_INTB_WATCH +#endif + +#define NR_MACH_IRQS (113 + 1) + +/* IAR0 BIT FIELDS */ +#define IRQ_PLL_WAKEUP_POS 0 +#define IRQ_DMA_ERROR_POS 4 +#define IRQ_ERROR_POS 8 +#define IRQ_RTC_POS 12 +#define IRQ_PPI_POS 16 +#define IRQ_SPORT0_RX_POS 20 +#define IRQ_SPORT0_TX_POS 24 +#define IRQ_SPORT1_RX_POS 28 + +/* IAR1 BIT FIELDS */ +#define IRQ_SPORT1_TX_POS 0 +#define IRQ_TWI_POS 4 +#define IRQ_SPI_POS 8 +#define IRQ_UART0_RX_POS 12 +#define IRQ_UART0_TX_POS 16 +#define IRQ_UART1_RX_POS 20 +#define IRQ_UART1_TX_POS 24 +#define IRQ_CAN_RX_POS 28 + +/* IAR2 BIT FIELDS */ +#define IRQ_CAN_TX_POS 0 +#define IRQ_MAC_RX_POS 4 +#define IRQ_MAC_TX_POS 8 +#define IRQ_TIMER0_POS 12 +#define IRQ_TIMER1_POS 16 +#define IRQ_TIMER2_POS 20 +#define IRQ_TIMER3_POS 24 +#define IRQ_TIMER4_POS 28 + +/* IAR3 BIT FIELDS */ +#define IRQ_TIMER5_POS 0 +#define IRQ_TIMER6_POS 4 +#define IRQ_TIMER7_POS 8 +#define IRQ_PROG_INTA_POS 12 +#define IRQ_PORTG_INTB_POS 16 +#define IRQ_MEM_DMA0_POS 20 +#define IRQ_MEM_DMA1_POS 24 +#define IRQ_WATCH_POS 28 + +#define init_mach_irq init_mach_irq + +#endif diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c index f6500622b35..2137a209a22 100644 --- a/arch/blackfin/mach-bf537/ints-priority.c +++ b/arch/blackfin/mach-bf537/ints-priority.c @@ -10,6 +10,13 @@ #include <linux/irq.h> #include <asm/blackfin.h> +#include <asm/irq_handler.h> +#include <asm/bfin5xx_spi.h> +#include <asm/bfin_sport.h> +#include <asm/bfin_can.h> +#include <asm/bfin_dma.h> +#include <asm/dpmc.h> + void __init program_IAR(void) { /* Program the IAR0 Register with the configured priority */ @@ -51,3 +58,159 @@ void __init program_IAR(void) SSYNC(); } + +#define SPI_ERR_MASK (BIT_STAT_TXCOL | BIT_STAT_RBSY | BIT_STAT_MODF | BIT_STAT_TXE) /* SPI_STAT */ +#define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF) /* SPORT_STAT */ +#define PPI_ERR_MASK (0xFFFF & ~FLD) /* PPI_STATUS */ +#define EMAC_ERR_MASK (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE) /* EMAC_SYSTAT */ +#define UART_ERR_MASK (0x6) /* UART_IIR */ +#define CAN_ERR_MASK (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF) /* CAN_GIF */ + +static int error_int_mask; + +static void bf537_generic_error_mask_irq(struct irq_data *d) +{ + error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR)); + if (!error_int_mask) + bfin_internal_mask_irq(IRQ_GENERIC_ERROR); +} + +static void bf537_generic_error_unmask_irq(struct irq_data *d) +{ + bfin_internal_unmask_irq(IRQ_GENERIC_ERROR); + error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR); +} + +static struct irq_chip bf537_generic_error_irqchip = { + .name = "ERROR", + .irq_ack = bfin_ack_noop, + .irq_mask_ack = bf537_generic_error_mask_irq, + .irq_mask = bf537_generic_error_mask_irq, + .irq_unmask = bf537_generic_error_unmask_irq, +}; + +static void bf537_demux_error_irq(unsigned int int_err_irq, + struct irq_desc *inta_desc) +{ + int irq = 0; + +#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) + if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK) + irq = IRQ_MAC_ERROR; + else +#endif + if (bfin_read_SPORT0_STAT() & SPORT_ERR_MASK) + irq = IRQ_SPORT0_ERROR; + else if (bfin_read_SPORT1_STAT() & SPORT_ERR_MASK) + irq = IRQ_SPORT1_ERROR; + else if (bfin_read_PPI_STATUS() & PPI_ERR_MASK) + irq = IRQ_PPI_ERROR; + else if (bfin_read_CAN_GIF() & CAN_ERR_MASK) + irq = IRQ_CAN_ERROR; + else if (bfin_read_SPI_STAT() & SPI_ERR_MASK) + irq = IRQ_SPI_ERROR; + else if ((bfin_read_UART0_IIR() & UART_ERR_MASK) == UART_ERR_MASK) + irq = IRQ_UART0_ERROR; + else if ((bfin_read_UART1_IIR() & UART_ERR_MASK) == UART_ERR_MASK) + irq = IRQ_UART1_ERROR; + + if (irq) { + if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) + bfin_handle_irq(irq); + else { + + switch (irq) { + case IRQ_PPI_ERROR: + bfin_write_PPI_STATUS(PPI_ERR_MASK); + break; +#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) + case IRQ_MAC_ERROR: + bfin_write_EMAC_SYSTAT(EMAC_ERR_MASK); + break; +#endif + case IRQ_SPORT0_ERROR: + bfin_write_SPORT0_STAT(SPORT_ERR_MASK); + break; + + case IRQ_SPORT1_ERROR: + bfin_write_SPORT1_STAT(SPORT_ERR_MASK); + break; + + case IRQ_CAN_ERROR: + bfin_write_CAN_GIS(CAN_ERR_MASK); + break; + + case IRQ_SPI_ERROR: + bfin_write_SPI_STAT(SPI_ERR_MASK); + break; + + default: + break; + } + + pr_debug("IRQ %d:" + " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n", + irq); + } + } else + pr_err("%s: IRQ ?: PERIPHERAL ERROR INTERRUPT ASSERTED BUT NO SOURCE FOUND\n", + __func__); + +} + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static int mac_rx_int_mask; + +static void bf537_mac_rx_mask_irq(struct irq_data *d) +{ + mac_rx_int_mask &= ~(1L << (d->irq - IRQ_MAC_RX)); + if (!mac_rx_int_mask) + bfin_internal_mask_irq(IRQ_PH_INTA_MAC_RX); +} + +static void bf537_mac_rx_unmask_irq(struct irq_data *d) +{ + bfin_internal_unmask_irq(IRQ_PH_INTA_MAC_RX); + mac_rx_int_mask |= 1L << (d->irq - IRQ_MAC_RX); +} + +static struct irq_chip bf537_mac_rx_irqchip = { + .name = "ERROR", + .irq_ack = bfin_ack_noop, + .irq_mask_ack = bf537_mac_rx_mask_irq, + .irq_mask = bf537_mac_rx_mask_irq, + .irq_unmask = bf537_mac_rx_unmask_irq, +}; + +static void bf537_demux_mac_rx_irq(unsigned int int_irq, + struct irq_desc *desc) +{ + if (bfin_read_DMA1_IRQ_STATUS() & (DMA_DONE | DMA_ERR)) + bfin_handle_irq(IRQ_MAC_RX); + else + bfin_demux_gpio_irq(int_irq, desc); +} +#endif + +void __init init_mach_irq(void) +{ + int irq; + +#if defined(CONFIG_BF537) || defined(CONFIG_BF536) + /* Clear EMAC Interrupt Status bits so we can demux it later */ + bfin_write_EMAC_SYSTAT(-1); +#endif + + irq_set_chained_handler(IRQ_GENERIC_ERROR, bf537_demux_error_irq); + for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++) + irq_set_chip_and_handler(irq, &bf537_generic_error_irqchip, + handle_level_irq); + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + irq_set_chained_handler(IRQ_PH_INTA_MAC_RX, bf537_demux_mac_rx_irq); + irq_set_chip_and_handler(IRQ_MAC_RX, &bf537_mac_rx_irqchip, handle_level_irq); + irq_set_chip_and_handler(IRQ_PORTH_INTA, &bf537_mac_rx_irqchip, handle_level_irq); + + irq_set_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq); +#endif +} diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h index 8774b481c78..55e7d0712a9 100644 --- a/arch/blackfin/mach-bf538/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h @@ -5,14 +5,14 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: - * - Revision H, 07/10/2009; ADSP-BF538/BF538F Blackfin Processor Anomaly List - * - Revision M, 07/10/2009; ADSP-BF539/BF539F Blackfin Processor Anomaly List + * - Revision I, 05/25/2010; ADSP-BF538/BF538F Blackfin Processor Anomaly List + * - Revision N, 05/25/2010; ADSP-BF539/BF539F Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -179,6 +179,7 @@ #define ANOMALY_05000363 (0) #define ANOMALY_05000364 (0) #define ANOMALY_05000380 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000386 (1) #define ANOMALY_05000389 (0) #define ANOMALY_05000400 (0) @@ -186,6 +187,7 @@ #define ANOMALY_05000430 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) +#define ANOMALY_05000440 (0) #define ANOMALY_05000447 (0) #define ANOMALY_05000448 (0) #define ANOMALY_05000456 (0) @@ -193,6 +195,7 @@ #define ANOMALY_05000465 (0) #define ANOMALY_05000467 (0) #define ANOMALY_05000474 (0) +#define ANOMALY_05000480 (0) #define ANOMALY_05000485 (0) #endif diff --git a/arch/blackfin/mach-bf538/include/mach/irq.h b/arch/blackfin/mach-bf538/include/mach/irq.h index 7a479d224dc..07ca069d37c 100644 --- a/arch/blackfin/mach-bf538/include/mach/irq.h +++ b/arch/blackfin/mach-bf538/include/mach/irq.h @@ -7,38 +7,9 @@ #ifndef _BF538_IRQ_H_ #define _BF538_IRQ_H_ -/* - * Interrupt source definitions - Event Source Core Event Name - Core Emulation ** - Events (highest priority) EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - - ..... - - Software Interrupt 1 IVG14 31 - Software Interrupt 2 -- - (lowest priority) IVG15 32 * -*/ - -#define NR_PERI_INTS (2 * 32) - -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /* Emulation */ -#define IRQ_RST 1 /* reset */ -#define IRQ_NMI 2 /* Non Maskable */ -#define IRQ_EVX 3 /* Exception */ -#define IRQ_UNUSED 4 /* - unused interrupt */ -#define IRQ_HWERR 5 /* Hardware Error */ -#define IRQ_CORETMR 6 /* Core timer */ - -#define BFIN_IRQ(x) ((x) + 7) +#include <mach-common/irq.h> + +#define NR_PERI_INTS (2 * 32) #define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ #define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */ @@ -91,37 +62,26 @@ #define SYS_IRQS BFIN_IRQ(63) /* 70 */ -#define IRQ_PF0 71 -#define IRQ_PF1 72 -#define IRQ_PF2 73 -#define IRQ_PF3 74 -#define IRQ_PF4 75 -#define IRQ_PF5 76 -#define IRQ_PF6 77 -#define IRQ_PF7 78 -#define IRQ_PF8 79 -#define IRQ_PF9 80 -#define IRQ_PF10 81 -#define IRQ_PF11 82 -#define IRQ_PF12 83 -#define IRQ_PF13 84 -#define IRQ_PF14 85 -#define IRQ_PF15 86 - -#define GPIO_IRQ_BASE IRQ_PF0 - -#define NR_MACH_IRQS (IRQ_PF15 + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 +#define IRQ_PF0 71 +#define IRQ_PF1 72 +#define IRQ_PF2 73 +#define IRQ_PF3 74 +#define IRQ_PF4 75 +#define IRQ_PF5 76 +#define IRQ_PF6 77 +#define IRQ_PF7 78 +#define IRQ_PF8 79 +#define IRQ_PF9 80 +#define IRQ_PF10 81 +#define IRQ_PF11 82 +#define IRQ_PF12 83 +#define IRQ_PF13 84 +#define IRQ_PF14 85 +#define IRQ_PF15 86 + +#define GPIO_IRQ_BASE IRQ_PF0 + +#define NR_MACH_IRQS (IRQ_PF15 + 1) /* IAR0 BIT FIELDS */ #define IRQ_PLL_WAKEUP_POS 0 @@ -184,4 +144,5 @@ #define IRQ_CAN_TX_POS 0 #define IRQ_MEM1_DMA0_POS 4 #define IRQ_MEM1_DMA1_POS 8 -#endif /* _BF538_IRQ_H_ */ + +#endif diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 93e19a54a88..311bf9970fe 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -22,6 +22,7 @@ #include <asm/gpio.h> #include <asm/nand.h> #include <asm/dpmc.h> +#include <asm/bfin_sport.h> #include <asm/portmux.h> #include <asm/bfin_sdh.h> #include <mach/bf54x_keys.h> @@ -956,7 +957,15 @@ static struct mtd_partition ezkit_partitions[] = { .offset = MTDPART_OFS_APPEND, }, { .name = "file system(nor)", - .size = MTDPART_SIZ_FULL, + .size = 0x1000000 - 0x80000 - 0x400000 - 0x8000 * 4, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "config(nor)", + .size = 0x8000 * 3, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "u-boot env(nor)", + .size = 0x8000, .offset = MTDPART_OFS_APPEND, } }; @@ -1312,27 +1321,110 @@ static struct platform_device bfin_dpmc = { }, }; -#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ + defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) + +#define SPORT_REQ(x) \ + [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ + P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} + +static const u16 bfin_snd_pin[][7] = { + SPORT_REQ(0), + SPORT_REQ(1), +}; + +static struct bfin_snd_platform_data bfin_snd_data[] = { + { + .pin_req = &bfin_snd_pin[0][0], + }, + { + .pin_req = &bfin_snd_pin[1][0], + }, +}; + +#define BFIN_SND_RES(x) \ + [x] = { \ + { \ + .start = SPORT##x##_TCR1, \ + .end = SPORT##x##_TCR1, \ + .flags = IORESOURCE_MEM \ + }, \ + { \ + .start = CH_SPORT##x##_RX, \ + .end = CH_SPORT##x##_RX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = CH_SPORT##x##_TX, \ + .end = CH_SPORT##x##_TX, \ + .flags = IORESOURCE_DMA, \ + }, \ + { \ + .start = IRQ_SPORT##x##_ERROR, \ + .end = IRQ_SPORT##x##_ERROR, \ + .flags = IORESOURCE_IRQ, \ + } \ + } + +static struct resource bfin_snd_resources[][4] = { + BFIN_SND_RES(0), + BFIN_SND_RES(1), +}; + +static struct platform_device bfin_pcm = { + .name = "bfin-pcm-audio", + .id = -1, +}; +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) +static struct platform_device bfin_ad73311_codec_device = { + .name = "ad73311", + .id = -1, +}; +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD1980) || defined(CONFIG_SND_BF5XX_SOC_AD1980_MODULE) +static struct platform_device bfin_ad1980_codec_device = { + .name = "ad1980", + .id = -1, +}; +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE) static struct platform_device bfin_i2s = { .name = "bfin-i2s", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif -#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) static struct platform_device bfin_tdm = { .name = "bfin-tdm", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif -#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) +#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) static struct platform_device bfin_ac97 = { .name = "bfin-ac97", .id = CONFIG_SND_BF5XX_SPORT_NUM, - /* TODO: add platform data here */ + .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), + .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], + .dev = { + .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], + }, }; #endif @@ -1450,6 +1542,16 @@ static struct platform_device *ezkit_devices[] __initdata = { &ezkit_flash_device, #endif +#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ + defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ + defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) + &bfin_pcm, +#endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD1980) || defined(CONFIG_SND_BF5XX_SOC_AD1980_MODULE) + &bfin_ad1980_codec_device, +#endif + #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) &bfin_i2s, #endif diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index ffd0537295a..9e70785bdde 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -5,13 +5,13 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: - * - Revision I, 07/23/2009; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List + * - Revision J, 06/03/2010; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -220,6 +220,8 @@ #define ANOMALY_05000481 (1) /* Possible USB Data Corruption When Multiple Endpoints Are Accessed by the Core */ #define ANOMALY_05000483 (1) +/* DDR Trim May Not Be Performed for Certain VLEV Values in OTP Page PBS00L */ +#define ANOMALY_05000484 (__SILICON_REVISION__ < 3) /* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */ #define ANOMALY_05000485 (__SILICON_REVISION__ >= 2) /* IFLUSH sucks at life */ @@ -274,6 +276,8 @@ #define ANOMALY_05000412 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) +#define ANOMALY_05000440 (0) #define ANOMALY_05000475 (0) +#define ANOMALY_05000480 (0) #endif diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h index 7f87787e773..533b8095b54 100644 --- a/arch/blackfin/mach-bf548/include/mach/irq.h +++ b/arch/blackfin/mach-bf548/include/mach/irq.h @@ -7,38 +7,9 @@ #ifndef _BF548_IRQ_H_ #define _BF548_IRQ_H_ -/* - * Interrupt source definitions - Event Source Core Event Name -Core Emulation ** -Events (highest priority) EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - -..... - - Software Interrupt 1 IVG14 31 - Software Interrupt 2 -- - (lowest priority) IVG15 32 * - */ - -#define NR_PERI_INTS (32 * 3) - -/* The ABSTRACT IRQ definitions */ -/** the first seven of the following are fixed, the rest you change if you need to **/ -#define IRQ_EMU 0 /* Emulation */ -#define IRQ_RST 1 /* reset */ -#define IRQ_NMI 2 /* Non Maskable */ -#define IRQ_EVX 3 /* Exception */ -#define IRQ_UNUSED 4 /* - unused interrupt*/ -#define IRQ_HWERR 5 /* Hardware Error */ -#define IRQ_CORETMR 6 /* Core timer */ +#include <mach-common/irq.h> -#define BFIN_IRQ(x) ((x) + 7) +#define NR_PERI_INTS (3 * 32) #define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ #define IRQ_DMAC0_ERROR BFIN_IRQ(1) /* DMAC0 Status Interrupt */ @@ -311,49 +282,37 @@ Events (highest priority) EMU 0 #define IRQ_PJ14 BFIN_PJ_IRQ(14) /* N/A */ #define IRQ_PJ15 BFIN_PJ_IRQ(15) /* N/A */ -#define GPIO_IRQ_BASE IRQ_PA0 +#define GPIO_IRQ_BASE IRQ_PA0 -#define NR_MACH_IRQS (IRQ_PJ15 + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) +#define NR_MACH_IRQS (IRQ_PJ15 + 1) /* For compatibility reasons with existing code */ -#define IRQ_DMAC0_ERR IRQ_DMAC0_ERROR -#define IRQ_EPPI0_ERR IRQ_EPPI0_ERROR +#define IRQ_DMAC0_ERR IRQ_DMAC0_ERROR +#define IRQ_EPPI0_ERR IRQ_EPPI0_ERROR #define IRQ_SPORT0_ERR IRQ_SPORT0_ERROR #define IRQ_SPORT1_ERR IRQ_SPORT1_ERROR -#define IRQ_SPI0_ERR IRQ_SPI0_ERROR -#define IRQ_UART0_ERR IRQ_UART0_ERROR -#define IRQ_DMAC1_ERR IRQ_DMAC1_ERROR +#define IRQ_SPI0_ERR IRQ_SPI0_ERROR +#define IRQ_UART0_ERR IRQ_UART0_ERROR +#define IRQ_DMAC1_ERR IRQ_DMAC1_ERROR #define IRQ_SPORT2_ERR IRQ_SPORT2_ERROR #define IRQ_SPORT3_ERR IRQ_SPORT3_ERROR -#define IRQ_SPI1_ERR IRQ_SPI1_ERROR -#define IRQ_SPI2_ERR IRQ_SPI2_ERROR -#define IRQ_UART1_ERR IRQ_UART1_ERROR -#define IRQ_UART2_ERR IRQ_UART2_ERROR -#define IRQ_CAN0_ERR IRQ_CAN0_ERROR -#define IRQ_MXVR_ERR IRQ_MXVR_ERROR -#define IRQ_EPPI1_ERR IRQ_EPPI1_ERROR -#define IRQ_EPPI2_ERR IRQ_EPPI2_ERROR -#define IRQ_UART3_ERR IRQ_UART3_ERROR -#define IRQ_HOST_ERR IRQ_HOST_ERROR -#define IRQ_PIXC_ERR IRQ_PIXC_ERROR -#define IRQ_NFC_ERR IRQ_NFC_ERROR -#define IRQ_ATAPI_ERR IRQ_ATAPI_ERROR -#define IRQ_CAN1_ERR IRQ_CAN1_ERROR +#define IRQ_SPI1_ERR IRQ_SPI1_ERROR +#define IRQ_SPI2_ERR IRQ_SPI2_ERROR +#define IRQ_UART1_ERR IRQ_UART1_ERROR +#define IRQ_UART2_ERR IRQ_UART2_ERROR +#define IRQ_CAN0_ERR IRQ_CAN0_ERROR +#define IRQ_MXVR_ERR IRQ_MXVR_ERROR +#define IRQ_EPPI1_ERR IRQ_EPPI1_ERROR +#define IRQ_EPPI2_ERR IRQ_EPPI2_ERROR +#define IRQ_UART3_ERR IRQ_UART3_ERROR +#define IRQ_HOST_ERR IRQ_HOST_ERROR +#define IRQ_PIXC_ERR IRQ_PIXC_ERROR +#define IRQ_NFC_ERR IRQ_NFC_ERROR +#define IRQ_ATAPI_ERR IRQ_ATAPI_ERROR +#define IRQ_CAN1_ERR IRQ_CAN1_ERROR #define IRQ_HS_DMA_ERR IRQ_HS_DMA_ERROR - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 - /* IAR0 BIT FIELDS */ #define IRQ_PLL_WAKEUP_POS 0 #define IRQ_DMAC0_ERR_POS 4 @@ -492,4 +451,4 @@ struct bfin_pint_regs { #endif -#endif /* _BF548_IRQ_H_ */ +#endif diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index f667e770419..5067984a62e 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -247,7 +247,15 @@ static struct mtd_partition ezkit_partitions[] = { .offset = MTDPART_OFS_APPEND, }, { .name = "file system(nor)", - .size = MTDPART_SIZ_FULL, + .size = 0x800000 - 0x40000 - 0x1C0000 - 0x2000 * 8, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "config(nor)", + .size = 0x2000 * 7, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "u-boot env(nor)", + .size = 0x2000, .offset = MTDPART_OFS_APPEND, } }; diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h index 6a3499b0209..22b5ab77302 100644 --- a/arch/blackfin/mach-bf561/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h @@ -5,13 +5,13 @@ * and can be replaced with that version at any time * DO NOT EDIT THIS FILE * - * Copyright 2004-2010 Analog Devices Inc. + * Copyright 2004-2011 Analog Devices Inc. * Licensed under the ADI BSD license. * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd */ /* This file should be up to date with: - * - Revision Q, 11/07/2008; ADSP-BF561 Blackfin Processor Anomaly List + * - Revision R, 05/25/2010; ADSP-BF561 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -290,12 +290,18 @@ #define ANOMALY_05000428 (__SILICON_REVISION__ > 3) /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */ #define ANOMALY_05000443 (1) +/* SCKELOW Feature Is Not Functional */ +#define ANOMALY_05000458 (1) /* False Hardware Error when RETI Points to Invalid Memory */ #define ANOMALY_05000461 (1) +/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */ +#define ANOMALY_05000462 (1) +/* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */ +#define ANOMALY_05000471 (1) /* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */ #define ANOMALY_05000473 (1) /* Possible Lockup Condition whem Modifying PLL from External Memory */ -#define ANOMALY_05000475 (__SILICON_REVISION__ < 4) +#define ANOMALY_05000475 (1) /* TESTSET Instruction Cannot Be Interrupted */ #define ANOMALY_05000477 (1) /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */ @@ -314,12 +320,14 @@ #define ANOMALY_05000353 (1) #define ANOMALY_05000364 (0) #define ANOMALY_05000380 (0) +#define ANOMALY_05000383 (0) #define ANOMALY_05000386 (1) #define ANOMALY_05000389 (0) #define ANOMALY_05000400 (0) #define ANOMALY_05000430 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) +#define ANOMALY_05000440 (0) #define ANOMALY_05000447 (0) #define ANOMALY_05000448 (0) #define ANOMALY_05000456 (0) @@ -327,6 +335,7 @@ #define ANOMALY_05000465 (0) #define ANOMALY_05000467 (0) #define ANOMALY_05000474 (0) +#define ANOMALY_05000480 (0) #define ANOMALY_05000485 (0) #endif diff --git a/arch/blackfin/mach-bf561/include/mach/irq.h b/arch/blackfin/mach-bf561/include/mach/irq.h index c95566ade51..d6998520f70 100644 --- a/arch/blackfin/mach-bf561/include/mach/irq.h +++ b/arch/blackfin/mach-bf561/include/mach/irq.h @@ -7,212 +7,98 @@ #ifndef _BF561_IRQ_H_ #define _BF561_IRQ_H_ -/*********************************************************************** - * Interrupt source definitions: - Event Source Core Event Name IRQ No - (highest priority) - Emulation Events EMU 0 - Reset RST 1 - NMI NMI 2 - Exception EVX 3 - Reserved -- 4 - Hardware Error IVHW 5 - Core Timer IVTMR 6 * - - PLL Wakeup Interrupt IVG7 7 - DMA1 Error (generic) IVG7 8 - DMA2 Error (generic) IVG7 9 - IMDMA Error (generic) IVG7 10 - PPI1 Error Interrupt IVG7 11 - PPI2 Error Interrupt IVG7 12 - SPORT0 Error Interrupt IVG7 13 - SPORT1 Error Interrupt IVG7 14 - SPI Error Interrupt IVG7 15 - UART Error Interrupt IVG7 16 - Reserved Interrupt IVG7 17 - - DMA1 0 Interrupt(PPI1) IVG8 18 - DMA1 1 Interrupt(PPI2) IVG8 19 - DMA1 2 Interrupt IVG8 20 - DMA1 3 Interrupt IVG8 21 - DMA1 4 Interrupt IVG8 22 - DMA1 5 Interrupt IVG8 23 - DMA1 6 Interrupt IVG8 24 - DMA1 7 Interrupt IVG8 25 - DMA1 8 Interrupt IVG8 26 - DMA1 9 Interrupt IVG8 27 - DMA1 10 Interrupt IVG8 28 - DMA1 11 Interrupt IVG8 29 - - DMA2 0 (SPORT0 RX) IVG9 30 - DMA2 1 (SPORT0 TX) IVG9 31 - DMA2 2 (SPORT1 RX) IVG9 32 - DMA2 3 (SPORT2 TX) IVG9 33 - DMA2 4 (SPI) IVG9 34 - DMA2 5 (UART RX) IVG9 35 - DMA2 6 (UART TX) IVG9 36 - DMA2 7 Interrupt IVG9 37 - DMA2 8 Interrupt IVG9 38 - DMA2 9 Interrupt IVG9 39 - DMA2 10 Interrupt IVG9 40 - DMA2 11 Interrupt IVG9 41 - - TIMER 0 Interrupt IVG10 42 - TIMER 1 Interrupt IVG10 43 - TIMER 2 Interrupt IVG10 44 - TIMER 3 Interrupt IVG10 45 - TIMER 4 Interrupt IVG10 46 - TIMER 5 Interrupt IVG10 47 - TIMER 6 Interrupt IVG10 48 - TIMER 7 Interrupt IVG10 49 - TIMER 8 Interrupt IVG10 50 - TIMER 9 Interrupt IVG10 51 - TIMER 10 Interrupt IVG10 52 - TIMER 11 Interrupt IVG10 53 - - Programmable Flags0 A (8) IVG11 54 - Programmable Flags0 B (8) IVG11 55 - Programmable Flags1 A (8) IVG11 56 - Programmable Flags1 B (8) IVG11 57 - Programmable Flags2 A (8) IVG11 58 - Programmable Flags2 B (8) IVG11 59 - - MDMA1 0 write/read INT IVG8 60 - MDMA1 1 write/read INT IVG8 61 - - MDMA2 0 write/read INT IVG9 62 - MDMA2 1 write/read INT IVG9 63 - - IMDMA 0 write/read INT IVG12 64 - IMDMA 1 write/read INT IVG12 65 - - Watch Dog Timer IVG13 66 - - Reserved interrupt IVG7 67 - Reserved interrupt IVG7 68 - Supplemental interrupt 0 IVG7 69 - supplemental interrupt 1 IVG7 70 - - Softirq IVG14 - System Call -- - (lowest priority) IVG15 - - **********************************************************************/ - -#define SYS_IRQS 71 -#define NR_PERI_INTS 64 - -/* - * The ABSTRACT IRQ definitions - * the first seven of the following are fixed, - * the rest you change if you need to. - */ -/* IVG 0-6*/ -#define IRQ_EMU 0 /* Emulation */ -#define IRQ_RST 1 /* Reset */ -#define IRQ_NMI 2 /* Non Maskable Interrupt */ -#define IRQ_EVX 3 /* Exception */ -#define IRQ_UNUSED 4 /* Reserved interrupt */ -#define IRQ_HWERR 5 /* Hardware Error */ -#define IRQ_CORETMR 6 /* Core timer */ - -#define IVG_BASE 7 -/* IVG 7 */ -#define IRQ_PLL_WAKEUP (IVG_BASE + 0) /* PLL Wakeup Interrupt */ -#define IRQ_DMA1_ERROR (IVG_BASE + 1) /* DMA1 Error (general) */ -#define IRQ_DMA_ERROR IRQ_DMA1_ERROR /* DMA1 Error (general) */ -#define IRQ_DMA2_ERROR (IVG_BASE + 2) /* DMA2 Error (general) */ -#define IRQ_IMDMA_ERROR (IVG_BASE + 3) /* IMDMA Error Interrupt */ -#define IRQ_PPI1_ERROR (IVG_BASE + 4) /* PPI1 Error Interrupt */ -#define IRQ_PPI_ERROR IRQ_PPI1_ERROR /* PPI1 Error Interrupt */ -#define IRQ_PPI2_ERROR (IVG_BASE + 5) /* PPI2 Error Interrupt */ -#define IRQ_SPORT0_ERROR (IVG_BASE + 6) /* SPORT0 Error Interrupt */ -#define IRQ_SPORT1_ERROR (IVG_BASE + 7) /* SPORT1 Error Interrupt */ -#define IRQ_SPI_ERROR (IVG_BASE + 8) /* SPI Error Interrupt */ -#define IRQ_UART_ERROR (IVG_BASE + 9) /* UART Error Interrupt */ -#define IRQ_RESERVED_ERROR (IVG_BASE + 10) /* Reversed Interrupt */ -/* IVG 8 */ -#define IRQ_DMA1_0 (IVG_BASE + 11) /* DMA1 0 Interrupt(PPI1) */ -#define IRQ_PPI IRQ_DMA1_0 /* DMA1 0 Interrupt(PPI1) */ -#define IRQ_PPI0 IRQ_DMA1_0 /* DMA1 0 Interrupt(PPI1) */ -#define IRQ_DMA1_1 (IVG_BASE + 12) /* DMA1 1 Interrupt(PPI2) */ -#define IRQ_PPI1 IRQ_DMA1_1 /* DMA1 1 Interrupt(PPI2) */ -#define IRQ_DMA1_2 (IVG_BASE + 13) /* DMA1 2 Interrupt */ -#define IRQ_DMA1_3 (IVG_BASE + 14) /* DMA1 3 Interrupt */ -#define IRQ_DMA1_4 (IVG_BASE + 15) /* DMA1 4 Interrupt */ -#define IRQ_DMA1_5 (IVG_BASE + 16) /* DMA1 5 Interrupt */ -#define IRQ_DMA1_6 (IVG_BASE + 17) /* DMA1 6 Interrupt */ -#define IRQ_DMA1_7 (IVG_BASE + 18) /* DMA1 7 Interrupt */ -#define IRQ_DMA1_8 (IVG_BASE + 19) /* DMA1 8 Interrupt */ -#define IRQ_DMA1_9 (IVG_BASE + 20) /* DMA1 9 Interrupt */ -#define IRQ_DMA1_10 (IVG_BASE + 21) /* DMA1 10 Interrupt */ -#define IRQ_DMA1_11 (IVG_BASE + 22) /* DMA1 11 Interrupt */ -/* IVG 9 */ -#define IRQ_DMA2_0 (IVG_BASE + 23) /* DMA2 0 (SPORT0 RX) */ -#define IRQ_SPORT0_RX IRQ_DMA2_0 /* DMA2 0 (SPORT0 RX) */ -#define IRQ_DMA2_1 (IVG_BASE + 24) /* DMA2 1 (SPORT0 TX) */ -#define IRQ_SPORT0_TX IRQ_DMA2_1 /* DMA2 1 (SPORT0 TX) */ -#define IRQ_DMA2_2 (IVG_BASE + 25) /* DMA2 2 (SPORT1 RX) */ -#define IRQ_SPORT1_RX IRQ_DMA2_2 /* DMA2 2 (SPORT1 RX) */ -#define IRQ_DMA2_3 (IVG_BASE + 26) /* DMA2 3 (SPORT2 TX) */ -#define IRQ_SPORT1_TX IRQ_DMA2_3 /* DMA2 3 (SPORT2 TX) */ -#define IRQ_DMA2_4 (IVG_BASE + 27) /* DMA2 4 (SPI) */ -#define IRQ_SPI IRQ_DMA2_4 /* DMA2 4 (SPI) */ -#define IRQ_DMA2_5 (IVG_BASE + 28) /* DMA2 5 (UART RX) */ -#define IRQ_UART_RX IRQ_DMA2_5 /* DMA2 5 (UART RX) */ -#define IRQ_DMA2_6 (IVG_BASE + 29) /* DMA2 6 (UART TX) */ -#define IRQ_UART_TX IRQ_DMA2_6 /* DMA2 6 (UART TX) */ -#define IRQ_DMA2_7 (IVG_BASE + 30) /* DMA2 7 Interrupt */ -#define IRQ_DMA2_8 (IVG_BASE + 31) /* DMA2 8 Interrupt */ -#define IRQ_DMA2_9 (IVG_BASE + 32) /* DMA2 9 Interrupt */ -#define IRQ_DMA2_10 (IVG_BASE + 33) /* DMA2 10 Interrupt */ -#define IRQ_DMA2_11 (IVG_BASE + 34) /* DMA2 11 Interrupt */ -/* IVG 10 */ -#define IRQ_TIMER0 (IVG_BASE + 35) /* TIMER 0 Interrupt */ -#define IRQ_TIMER1 (IVG_BASE + 36) /* TIMER 1 Interrupt */ -#define IRQ_TIMER2 (IVG_BASE + 37) /* TIMER 2 Interrupt */ -#define IRQ_TIMER3 (IVG_BASE + 38) /* TIMER 3 Interrupt */ -#define IRQ_TIMER4 (IVG_BASE + 39) /* TIMER 4 Interrupt */ -#define IRQ_TIMER5 (IVG_BASE + 40) /* TIMER 5 Interrupt */ -#define IRQ_TIMER6 (IVG_BASE + 41) /* TIMER 6 Interrupt */ -#define IRQ_TIMER7 (IVG_BASE + 42) /* TIMER 7 Interrupt */ -#define IRQ_TIMER8 (IVG_BASE + 43) /* TIMER 8 Interrupt */ -#define IRQ_TIMER9 (IVG_BASE + 44) /* TIMER 9 Interrupt */ -#define IRQ_TIMER10 (IVG_BASE + 45) /* TIMER 10 Interrupt */ -#define IRQ_TIMER11 (IVG_BASE + 46) /* TIMER 11 Interrupt */ -/* IVG 11 */ -#define IRQ_PROG0_INTA (IVG_BASE + 47) /* Programmable Flags0 A (8) */ -#define IRQ_PROG_INTA IRQ_PROG0_INTA /* Programmable Flags0 A (8) */ -#define IRQ_PROG0_INTB (IVG_BASE + 48) /* Programmable Flags0 B (8) */ -#define IRQ_PROG_INTB IRQ_PROG0_INTB /* Programmable Flags0 B (8) */ -#define IRQ_PROG1_INTA (IVG_BASE + 49) /* Programmable Flags1 A (8) */ -#define IRQ_PROG1_INTB (IVG_BASE + 50) /* Programmable Flags1 B (8) */ -#define IRQ_PROG2_INTA (IVG_BASE + 51) /* Programmable Flags2 A (8) */ -#define IRQ_PROG2_INTB (IVG_BASE + 52) /* Programmable Flags2 B (8) */ -/* IVG 8 */ -#define IRQ_DMA1_WRRD0 (IVG_BASE + 53) /* MDMA1 0 write/read INT */ -#define IRQ_DMA_WRRD0 IRQ_DMA1_WRRD0 /* MDMA1 0 write/read INT */ +#include <mach-common/irq.h> + +#define NR_PERI_INTS (2 * 32) + +#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ +#define IRQ_DMA1_ERROR BFIN_IRQ(1) /* DMA1 Error (general) */ +#define IRQ_DMA_ERROR IRQ_DMA1_ERROR /* DMA1 Error (general) */ +#define IRQ_DMA2_ERROR BFIN_IRQ(2) /* DMA2 Error (general) */ +#define IRQ_IMDMA_ERROR BFIN_IRQ(3) /* IMDMA Error Interrupt */ +#define IRQ_PPI1_ERROR BFIN_IRQ(4) /* PPI1 Error Interrupt */ +#define IRQ_PPI_ERROR IRQ_PPI1_ERROR /* PPI1 Error Interrupt */ +#define IRQ_PPI2_ERROR BFIN_IRQ(5) /* PPI2 Error Interrupt */ +#define IRQ_SPORT0_ERROR BFIN_IRQ(6) /* SPORT0 Error Interrupt */ +#define IRQ_SPORT1_ERROR BFIN_IRQ(7) /* SPORT1 Error Interrupt */ +#define IRQ_SPI_ERROR BFIN_IRQ(8) /* SPI Error Interrupt */ +#define IRQ_UART_ERROR BFIN_IRQ(9) /* UART Error Interrupt */ +#define IRQ_RESERVED_ERROR BFIN_IRQ(10) /* Reversed */ +#define IRQ_DMA1_0 BFIN_IRQ(11) /* DMA1 0 Interrupt(PPI1) */ +#define IRQ_PPI IRQ_DMA1_0 /* DMA1 0 Interrupt(PPI1) */ +#define IRQ_PPI0 IRQ_DMA1_0 /* DMA1 0 Interrupt(PPI1) */ +#define IRQ_DMA1_1 BFIN_IRQ(12) /* DMA1 1 Interrupt(PPI2) */ +#define IRQ_PPI1 IRQ_DMA1_1 /* DMA1 1 Interrupt(PPI2) */ +#define IRQ_DMA1_2 BFIN_IRQ(13) /* DMA1 2 Interrupt */ +#define IRQ_DMA1_3 BFIN_IRQ(14) /* DMA1 3 Interrupt */ +#define IRQ_DMA1_4 BFIN_IRQ(15) /* DMA1 4 Interrupt */ +#define IRQ_DMA1_5 BFIN_IRQ(16) /* DMA1 5 Interrupt */ +#define IRQ_DMA1_6 BFIN_IRQ(17) /* DMA1 6 Interrupt */ +#define IRQ_DMA1_7 BFIN_IRQ(18) /* DMA1 7 Interrupt */ +#define IRQ_DMA1_8 BFIN_IRQ(19) /* DMA1 8 Interrupt */ +#define IRQ_DMA1_9 BFIN_IRQ(20) /* DMA1 9 Interrupt */ +#define IRQ_DMA1_10 BFIN_IRQ(21) /* DMA1 10 Interrupt */ +#define IRQ_DMA1_11 BFIN_IRQ(22) /* DMA1 11 Interrupt */ +#define IRQ_DMA2_0 BFIN_IRQ(23) /* DMA2 0 (SPORT0 RX) */ +#define IRQ_SPORT0_RX IRQ_DMA2_0 /* DMA2 0 (SPORT0 RX) */ +#define IRQ_DMA2_1 BFIN_IRQ(24) /* DMA2 1 (SPORT0 TX) */ +#define IRQ_SPORT0_TX IRQ_DMA2_1 /* DMA2 1 (SPORT0 TX) */ +#define IRQ_DMA2_2 BFIN_IRQ(25) /* DMA2 2 (SPORT1 RX) */ +#define IRQ_SPORT1_RX IRQ_DMA2_2 /* DMA2 2 (SPORT1 RX) */ +#define IRQ_DMA2_3 BFIN_IRQ(26) /* DMA2 3 (SPORT2 TX) */ +#define IRQ_SPORT1_TX IRQ_DMA2_3 /* DMA2 3 (SPORT2 TX) */ +#define IRQ_DMA2_4 BFIN_IRQ(27) /* DMA2 4 (SPI) */ +#define IRQ_SPI IRQ_DMA2_4 /* DMA2 4 (SPI) */ +#define IRQ_DMA2_5 BFIN_IRQ(28) /* DMA2 5 (UART RX) */ +#define IRQ_UART_RX IRQ_DMA2_5 /* DMA2 5 (UART RX) */ +#define IRQ_DMA2_6 BFIN_IRQ(29) /* DMA2 6 (UART TX) */ +#define IRQ_UART_TX IRQ_DMA2_6 /* DMA2 6 (UART TX) */ +#define IRQ_DMA2_7 BFIN_IRQ(30) /* DMA2 7 Interrupt */ +#define IRQ_DMA2_8 BFIN_IRQ(31) /* DMA2 8 Interrupt */ +#define IRQ_DMA2_9 BFIN_IRQ(32) /* DMA2 9 Interrupt */ +#define IRQ_DMA2_10 BFIN_IRQ(33) /* DMA2 10 Interrupt */ +#define IRQ_DMA2_11 BFIN_IRQ(34) /* DMA2 11 Interrupt */ +#define IRQ_TIMER0 BFIN_IRQ(35) /* TIMER 0 Interrupt */ +#define IRQ_TIMER1 BFIN_IRQ(36) /* TIMER 1 Interrupt */ +#define IRQ_TIMER2 BFIN_IRQ(37) /* TIMER 2 Interrupt */ +#define IRQ_TIMER3 BFIN_IRQ(38) /* TIMER 3 Interrupt */ +#define IRQ_TIMER4 BFIN_IRQ(39) /* TIMER 4 Interrupt */ +#define IRQ_TIMER5 BFIN_IRQ(40) /* TIMER 5 Interrupt */ +#define IRQ_TIMER6 BFIN_IRQ(41) /* TIMER 6 Interrupt */ +#define IRQ_TIMER7 BFIN_IRQ(42) /* TIMER 7 Interrupt */ +#define IRQ_TIMER8 BFIN_IRQ(43) /* TIMER 8 Interrupt */ +#define IRQ_TIMER9 BFIN_IRQ(44) /* TIMER 9 Interrupt */ +#define IRQ_TIMER10 BFIN_IRQ(45) /* TIMER 10 Interrupt */ +#define IRQ_TIMER11 BFIN_IRQ(46) /* TIMER 11 Interrupt */ +#define IRQ_PROG0_INTA BFIN_IRQ(47) /* Programmable Flags0 A (8) */ +#define IRQ_PROG_INTA IRQ_PROG0_INTA /* Programmable Flags0 A (8) */ +#define IRQ_PROG0_INTB BFIN_IRQ(48) /* Programmable Flags0 B (8) */ +#define IRQ_PROG_INTB IRQ_PROG0_INTB /* Programmable Flags0 B (8) */ +#define IRQ_PROG1_INTA BFIN_IRQ(49) /* Programmable Flags1 A (8) */ +#define IRQ_PROG1_INTB BFIN_IRQ(50) /* Programmable Flags1 B (8) */ +#define IRQ_PROG2_INTA BFIN_IRQ(51) /* Programmable Flags2 A (8) */ +#define IRQ_PROG2_INTB BFIN_IRQ(52) /* Programmable Flags2 B (8) */ +#define IRQ_DMA1_WRRD0 BFIN_IRQ(53) /* MDMA1 0 write/read INT */ +#define IRQ_DMA_WRRD0 IRQ_DMA1_WRRD0 /* MDMA1 0 write/read INT */ #define IRQ_MEM_DMA0 IRQ_DMA1_WRRD0 -#define IRQ_DMA1_WRRD1 (IVG_BASE + 54) /* MDMA1 1 write/read INT */ -#define IRQ_DMA_WRRD1 IRQ_DMA1_WRRD1 /* MDMA1 1 write/read INT */ +#define IRQ_DMA1_WRRD1 BFIN_IRQ(54) /* MDMA1 1 write/read INT */ +#define IRQ_DMA_WRRD1 IRQ_DMA1_WRRD1 /* MDMA1 1 write/read INT */ #define IRQ_MEM_DMA1 IRQ_DMA1_WRRD1 -/* IVG 9 */ -#define IRQ_DMA2_WRRD0 (IVG_BASE + 55) /* MDMA2 0 write/read INT */ +#define IRQ_DMA2_WRRD0 BFIN_IRQ(55) /* MDMA2 0 write/read INT */ #define IRQ_MEM_DMA2 IRQ_DMA2_WRRD0 -#define IRQ_DMA2_WRRD1 (IVG_BASE + 56) /* MDMA2 1 write/read INT */ +#define IRQ_DMA2_WRRD1 BFIN_IRQ(56) /* MDMA2 1 write/read INT */ #define IRQ_MEM_DMA3 IRQ_DMA2_WRRD1 -/* IVG 12 */ -#define IRQ_IMDMA_WRRD0 (IVG_BASE + 57) /* IMDMA 0 write/read INT */ +#define IRQ_IMDMA_WRRD0 BFIN_IRQ(57) /* IMDMA 0 write/read INT */ #define IRQ_IMEM_DMA0 IRQ_IMDMA_WRRD0 -#define IRQ_IMDMA_WRRD1 (IVG_BASE + 58) /* IMDMA 1 write/read INT */ +#define IRQ_IMDMA_WRRD1 BFIN_IRQ(58) /* IMDMA 1 write/read INT */ #define IRQ_IMEM_DMA1 IRQ_IMDMA_WRRD1 -/* IVG 13 */ -#define IRQ_WATCH (IVG_BASE + 59) /* Watch Dog Timer */ -/* IVG 7 */ -#define IRQ_RESERVED_1 (IVG_BASE + 60) /* Reserved interrupt */ -#define IRQ_RESERVED_2 (IVG_BASE + 61) /* Reserved interrupt */ -#define IRQ_SUPPLE_0 (IVG_BASE + 62) /* Supplemental interrupt 0 */ -#define IRQ_SUPPLE_1 (IVG_BASE + 63) /* supplemental interrupt 1 */ +#define IRQ_WATCH BFIN_IRQ(59) /* Watch Dog Timer */ +#define IRQ_RESERVED_1 BFIN_IRQ(60) /* Reserved interrupt */ +#define IRQ_RESERVED_2 BFIN_IRQ(61) /* Reserved interrupt */ +#define IRQ_SUPPLE_0 BFIN_IRQ(62) /* Supplemental interrupt 0 */ +#define IRQ_SUPPLE_1 BFIN_IRQ(63) /* supplemental interrupt 1 */ + +#define SYS_IRQS 71 #define IRQ_PF0 73 #define IRQ_PF1 74 @@ -266,158 +152,85 @@ #define GPIO_IRQ_BASE IRQ_PF0 #define NR_MACH_IRQS (IRQ_PF47 + 1) -#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS) - -#define IVG7 7 -#define IVG8 8 -#define IVG9 9 -#define IVG10 10 -#define IVG11 11 -#define IVG12 12 -#define IVG13 13 -#define IVG14 14 -#define IVG15 15 - -/* - * DEFAULT PRIORITIES: - */ - -#define CONFIG_DEF_PLL_WAKEUP 7 -#define CONFIG_DEF_DMA1_ERROR 7 -#define CONFIG_DEF_DMA2_ERROR 7 -#define CONFIG_DEF_IMDMA_ERROR 7 -#define CONFIG_DEF_PPI1_ERROR 7 -#define CONFIG_DEF_PPI2_ERROR 7 -#define CONFIG_DEF_SPORT0_ERROR 7 -#define CONFIG_DEF_SPORT1_ERROR 7 -#define CONFIG_DEF_SPI_ERROR 7 -#define CONFIG_DEF_UART_ERROR 7 -#define CONFIG_DEF_RESERVED_ERROR 7 -#define CONFIG_DEF_DMA1_0 8 -#define CONFIG_DEF_DMA1_1 8 -#define CONFIG_DEF_DMA1_2 8 -#define CONFIG_DEF_DMA1_3 8 -#define CONFIG_DEF_DMA1_4 8 -#define CONFIG_DEF_DMA1_5 8 -#define CONFIG_DEF_DMA1_6 8 -#define CONFIG_DEF_DMA1_7 8 -#define CONFIG_DEF_DMA1_8 8 -#define CONFIG_DEF_DMA1_9 8 -#define CONFIG_DEF_DMA1_10 8 -#define CONFIG_DEF_DMA1_11 8 -#define CONFIG_DEF_DMA2_0 9 -#define CONFIG_DEF_DMA2_1 9 -#define CONFIG_DEF_DMA2_2 9 -#define CONFIG_DEF_DMA2_3 9 -#define CONFIG_DEF_DMA2_4 9 -#define CONFIG_DEF_DMA2_5 9 -#define CONFIG_DEF_DMA2_6 9 -#define CONFIG_DEF_DMA2_7 9 -#define CONFIG_DEF_DMA2_8 9 -#define CONFIG_DEF_DMA2_9 9 -#define CONFIG_DEF_DMA2_10 9 -#define CONFIG_DEF_DMA2_11 9 -#define CONFIG_DEF_TIMER0 10 -#define CONFIG_DEF_TIMER1 10 -#define CONFIG_DEF_TIMER2 10 -#define CONFIG_DEF_TIMER3 10 -#define CONFIG_DEF_TIMER4 10 -#define CONFIG_DEF_TIMER5 10 -#define CONFIG_DEF_TIMER6 10 -#define CONFIG_DEF_TIMER7 10 -#define CONFIG_DEF_TIMER8 10 -#define CONFIG_DEF_TIMER9 10 -#define CONFIG_DEF_TIMER10 10 -#define CONFIG_DEF_TIMER11 10 -#define CONFIG_DEF_PROG0_INTA 11 -#define CONFIG_DEF_PROG0_INTB 11 -#define CONFIG_DEF_PROG1_INTA 11 -#define CONFIG_DEF_PROG1_INTB 11 -#define CONFIG_DEF_PROG2_INTA 11 -#define CONFIG_DEF_PROG2_INTB 11 -#define CONFIG_DEF_DMA1_WRRD0 8 -#define CONFIG_DEF_DMA1_WRRD1 8 -#define CONFIG_DEF_DMA2_WRRD0 9 -#define CONFIG_DEF_DMA2_WRRD1 9 -#define CONFIG_DEF_IMDMA_WRRD0 12 -#define CONFIG_DEF_IMDMA_WRRD1 12 -#define CONFIG_DEF_WATCH 13 -#define CONFIG_DEF_RESERVED_1 7 -#define CONFIG_DEF_RESERVED_2 7 -#define CONFIG_DEF_SUPPLE_0 7 -#define CONFIG_DEF_SUPPLE_1 7 /* IAR0 BIT FIELDS */ -#define IRQ_PLL_WAKEUP_POS 0 -#define IRQ_DMA1_ERROR_POS 4 -#define IRQ_DMA2_ERROR_POS 8 -#define IRQ_IMDMA_ERROR_POS 12 -#define IRQ_PPI0_ERROR_POS 16 -#define IRQ_PPI1_ERROR_POS 20 -#define IRQ_SPORT0_ERROR_POS 24 -#define IRQ_SPORT1_ERROR_POS 28 +#define IRQ_PLL_WAKEUP_POS 0 +#define IRQ_DMA1_ERROR_POS 4 +#define IRQ_DMA2_ERROR_POS 8 +#define IRQ_IMDMA_ERROR_POS 12 +#define IRQ_PPI0_ERROR_POS 16 +#define IRQ_PPI1_ERROR_POS 20 +#define IRQ_SPORT0_ERROR_POS 24 +#define IRQ_SPORT1_ERROR_POS 28 + /* IAR1 BIT FIELDS */ -#define IRQ_SPI_ERROR_POS 0 -#define IRQ_UART_ERROR_POS 4 -#define IRQ_RESERVED_ERROR_POS 8 -#define IRQ_DMA1_0_POS 12 -#define IRQ_DMA1_1_POS 16 -#define IRQ_DMA1_2_POS 20 -#define IRQ_DMA1_3_POS 24 -#define IRQ_DMA1_4_POS 28 +#define IRQ_SPI_ERROR_POS 0 +#define IRQ_UART_ERROR_POS 4 +#define IRQ_RESERVED_ERROR_POS 8 +#define IRQ_DMA1_0_POS 12 +#define IRQ_DMA1_1_POS 16 +#define IRQ_DMA1_2_POS 20 +#define IRQ_DMA1_3_POS 24 +#define IRQ_DMA1_4_POS 28 + /* IAR2 BIT FIELDS */ -#define IRQ_DMA1_5_POS 0 -#define IRQ_DMA1_6_POS 4 -#define IRQ_DMA1_7_POS 8 -#define IRQ_DMA1_8_POS 12 -#define IRQ_DMA1_9_POS 16 -#define IRQ_DMA1_10_POS 20 -#define IRQ_DMA1_11_POS 24 -#define IRQ_DMA2_0_POS 28 +#define IRQ_DMA1_5_POS 0 +#define IRQ_DMA1_6_POS 4 +#define IRQ_DMA1_7_POS 8 +#define IRQ_DMA1_8_POS 12 +#define IRQ_DMA1_9_POS 16 +#define IRQ_DMA1_10_POS 20 +#define IRQ_DMA1_11_POS 24 +#define IRQ_DMA2_0_POS 28 + /* IAR3 BIT FIELDS */ -#define IRQ_DMA2_1_POS 0 -#define IRQ_DMA2_2_POS 4 -#define IRQ_DMA2_3_POS 8 -#define IRQ_DMA2_4_POS 12 -#define IRQ_DMA2_5_POS 16 -#define IRQ_DMA2_6_POS 20 -#define IRQ_DMA2_7_POS 24 -#define IRQ_DMA2_8_POS 28 +#define IRQ_DMA2_1_POS 0 +#define IRQ_DMA2_2_POS 4 +#define IRQ_DMA2_3_POS 8 +#define IRQ_DMA2_4_POS 12 +#define IRQ_DMA2_5_POS 16 +#define IRQ_DMA2_6_POS 20 +#define IRQ_DMA2_7_POS 24 +#define IRQ_DMA2_8_POS 28 + /* IAR4 BIT FIELDS */ -#define IRQ_DMA2_9_POS 0 -#define IRQ_DMA2_10_POS 4 -#define IRQ_DMA2_11_POS 8 -#define IRQ_TIMER0_POS 12 -#define IRQ_TIMER1_POS 16 -#define IRQ_TIMER2_POS 20 -#define IRQ_TIMER3_POS 24 -#define IRQ_TIMER4_POS 28 +#define IRQ_DMA2_9_POS 0 +#define IRQ_DMA2_10_POS 4 +#define IRQ_DMA2_11_POS 8 +#define IRQ_TIMER0_POS 12 +#define IRQ_TIMER1_POS 16 +#define IRQ_TIMER2_POS 20 +#define IRQ_TIMER3_POS 24 +#define IRQ_TIMER4_POS 28 + /* IAR5 BIT FIELDS */ -#define IRQ_TIMER5_POS 0 -#define IRQ_TIMER6_POS 4 -#define IRQ_TIMER7_POS 8 -#define IRQ_TIMER8_POS 12 -#define IRQ_TIMER9_POS 16 -#define IRQ_TIMER10_POS 20 -#define IRQ_TIMER11_POS 24 -#define IRQ_PROG0_INTA_POS 28 +#define IRQ_TIMER5_POS 0 +#define IRQ_TIMER6_POS 4 +#define IRQ_TIMER7_POS 8 +#define IRQ_TIMER8_POS 12 +#define IRQ_TIMER9_POS 16 +#define IRQ_TIMER10_POS 20 +#define IRQ_TIMER11_POS 24 +#define IRQ_PROG0_INTA_POS 28 + /* IAR6 BIT FIELDS */ -#define IRQ_PROG0_INTB_POS 0 -#define IRQ_PROG1_INTA_POS 4 -#define IRQ_PROG1_INTB_POS 8 -#define IRQ_PROG2_INTA_POS 12 -#define IRQ_PROG2_INTB_POS 16 -#define IRQ_DMA1_WRRD0_POS 20 -#define IRQ_DMA1_WRRD1_POS 24 -#define IRQ_DMA2_WRRD0_POS 28 -/* IAR7 BIT FIELDS */ -#define IRQ_DMA2_WRRD1_POS 0 -#define IRQ_IMDMA_WRRD0_POS 4 -#define IRQ_IMDMA_WRRD1_POS 8 -#define IRQ_WDTIMER_POS 12 -#define IRQ_RESERVED_1_POS 16 -#define IRQ_RESERVED_2_POS 20 -#define IRQ_SUPPLE_0_POS 24 -#define IRQ_SUPPLE_1_POS 28 +#define IRQ_PROG0_INTB_POS 0 +#define IRQ_PROG1_INTA_POS 4 +#define IRQ_PROG1_INTB_POS 8 +#define IRQ_PROG2_INTA_POS 12 +#define IRQ_PROG2_INTB_POS 16 +#define IRQ_DMA1_WRRD0_POS 20 +#define IRQ_DMA1_WRRD1_POS 24 +#define IRQ_DMA2_WRRD0_POS 28 -#endif /* _BF561_IRQ_H_ */ +/* IAR7 BIT FIELDS */ +#define IRQ_DMA2_WRRD1_POS 0 +#define IRQ_IMDMA_WRRD0_POS 4 +#define IRQ_IMDMA_WRRD1_POS 8 +#define IRQ_WDTIMER_POS 12 +#define IRQ_RESERVED_1_POS 16 +#define IRQ_RESERVED_2_POS 20 +#define IRQ_SUPPLE_0_POS 24 +#define IRQ_SUPPLE_1_POS 28 + +#endif diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 7b07740cf68..85abd8be134 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -24,17 +24,23 @@ static DEFINE_SPINLOCK(boot_lock); void __init platform_init_cpus(void) { - cpu_set(0, cpu_possible_map); /* CoreA */ - cpu_set(1, cpu_possible_map); /* CoreB */ + struct cpumask mask; + + cpumask_set_cpu(0, &mask); /* CoreA */ + cpumask_set_cpu(1, &mask); /* CoreB */ + init_cpu_possible(&mask); } void __init platform_prepare_cpus(unsigned int max_cpus) { + struct cpumask mask; + bfin_relocate_coreb_l1_mem(); /* Both cores ought to be present on a bf561! */ - cpu_set(0, cpu_present_map); /* CoreA */ - cpu_set(1, cpu_present_map); /* CoreB */ + cpumask_set_cpu(0, &mask); /* CoreA */ + cpumask_set_cpu(1, &mask); /* CoreB */ + init_cpu_present(&mask); } int __init setup_profiling_timer(unsigned int multiplier) /* not supported */ @@ -62,9 +68,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu) bfin_write_SICB_IWR1(IWR_DISABLE_ALL); SSYNC(); - /* Store CPU-private information to the cpu_data array. */ - bfin_setup_cpudata(cpu); - /* We are done with local CPU inits, unblock the boot CPU. */ set_cpu_online(cpu, true); spin_lock(&boot_lock); diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c index 5e4112e518a..f5685a496c5 100644 --- a/arch/blackfin/mach-common/dpmc.c +++ b/arch/blackfin/mach-common/dpmc.c @@ -85,10 +85,11 @@ static void bfin_wakeup_cpu(void) { unsigned int cpu; unsigned int this_cpu = smp_processor_id(); - cpumask_t mask = cpu_online_map; + cpumask_t mask; - cpu_clear(this_cpu, mask); - for_each_cpu_mask(cpu, mask) + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(this_cpu, &mask); + for_each_cpu(cpu, &mask) platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0); } diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 43d9fb195c1..1177369f992 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -19,32 +19,14 @@ #ifdef CONFIG_IPIPE #include <linux/ipipe.h> #endif -#ifdef CONFIG_KGDB -#include <linux/kgdb.h> -#endif #include <asm/traps.h> #include <asm/blackfin.h> #include <asm/gpio.h> #include <asm/irq_handler.h> #include <asm/dpmc.h> -#include <asm/bfin5xx_spi.h> -#include <asm/bfin_sport.h> -#include <asm/bfin_can.h> #define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) -#ifdef BF537_FAMILY -# define BF537_GENERIC_ERROR_INT_DEMUX -# define SPI_ERR_MASK (BIT_STAT_TXCOL | BIT_STAT_RBSY | BIT_STAT_MODF | BIT_STAT_TXE) /* SPI_STAT */ -# define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF) /* SPORT_STAT */ -# define PPI_ERR_MASK (0xFFFF & ~FLD) /* PPI_STATUS */ -# define EMAC_ERR_MASK (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE) /* EMAC_SYSTAT */ -# define UART_ERR_MASK (0x6) /* UART_IIR */ -# define CAN_ERR_MASK (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF) /* CAN_GIF */ -#else -# undef BF537_GENERIC_ERROR_INT_DEMUX -#endif - /* * NOTES: * - we have separated the physical Hardware interrupt from the @@ -63,22 +45,19 @@ unsigned long bfin_irq_flags = 0x1f; EXPORT_SYMBOL(bfin_irq_flags); #endif -/* The number of spurious interrupts */ -atomic_t num_spurious; - #ifdef CONFIG_PM unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */ unsigned vr_wakeup; #endif -struct ivgx { +static struct ivgx { /* irq number for request_irq, available in mach-bf5xx/irq.h */ unsigned int irqno; /* corresponding bit in the SIC_ISR register */ unsigned int isrflag; } ivg_table[NR_PERI_INTS]; -struct ivg_slice { +static struct ivg_slice { /* position of first irq in ivg_table for given ivg */ struct ivgx *ifirst; struct ivgx *istop; @@ -125,7 +104,7 @@ static void __init search_IAR(void) * This is for core internal IRQs */ -static void bfin_ack_noop(struct irq_data *d) +void bfin_ack_noop(struct irq_data *d) { /* Dummy function. */ } @@ -154,26 +133,24 @@ static void bfin_core_unmask_irq(struct irq_data *d) return; } -static void bfin_internal_mask_irq(unsigned int irq) +void bfin_internal_mask_irq(unsigned int irq) { - unsigned long flags; + unsigned long flags = hard_local_irq_save(); -#ifdef CONFIG_BF53x - flags = hard_local_irq_save(); - bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & - ~(1 << SIC_SYSIRQ(irq))); -#else - unsigned mask_bank, mask_bit; - flags = hard_local_irq_save(); - mask_bank = SIC_SYSIRQ(irq) / 32; - mask_bit = SIC_SYSIRQ(irq) % 32; +#ifdef SIC_IMASK0 + unsigned mask_bank = SIC_SYSIRQ(irq) / 32; + unsigned mask_bit = SIC_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & ~(1 << mask_bit)); -#ifdef CONFIG_SMP +# ifdef CONFIG_SMP bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) & ~(1 << mask_bit)); +# endif +#else + bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & + ~(1 << SIC_SYSIRQ(irq))); #endif -#endif + hard_local_irq_restore(flags); } @@ -186,33 +163,31 @@ static void bfin_internal_mask_irq_chip(struct irq_data *d) static void bfin_internal_unmask_irq_affinity(unsigned int irq, const struct cpumask *affinity) #else -static void bfin_internal_unmask_irq(unsigned int irq) +void bfin_internal_unmask_irq(unsigned int irq) #endif { - unsigned long flags; + unsigned long flags = hard_local_irq_save(); -#ifdef CONFIG_BF53x - flags = hard_local_irq_save(); - bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | - (1 << SIC_SYSIRQ(irq))); -#else - unsigned mask_bank, mask_bit; - flags = hard_local_irq_save(); - mask_bank = SIC_SYSIRQ(irq) / 32; - mask_bit = SIC_SYSIRQ(irq) % 32; -#ifdef CONFIG_SMP +#ifdef SIC_IMASK0 + unsigned mask_bank = SIC_SYSIRQ(irq) / 32; + unsigned mask_bit = SIC_SYSIRQ(irq) % 32; +# ifdef CONFIG_SMP if (cpumask_test_cpu(0, affinity)) -#endif +# endif bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | (1 << mask_bit)); -#ifdef CONFIG_SMP +# ifdef CONFIG_SMP if (cpumask_test_cpu(1, affinity)) bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) | (1 << mask_bit)); +# endif +#else + bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | + (1 << SIC_SYSIRQ(irq))); #endif -#endif + hard_local_irq_restore(flags); } @@ -295,6 +270,8 @@ static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state) { return bfin_internal_set_wake(d->irq, state); } +#else +# define bfin_internal_set_wake_chip NULL #endif static struct irq_chip bfin_core_irqchip = { @@ -315,12 +292,10 @@ static struct irq_chip bfin_internal_irqchip = { #ifdef CONFIG_SMP .irq_set_affinity = bfin_internal_set_affinity, #endif -#ifdef CONFIG_PM .irq_set_wake = bfin_internal_set_wake_chip, -#endif }; -static void bfin_handle_irq(unsigned irq) +void bfin_handle_irq(unsigned irq) { #ifdef CONFIG_IPIPE struct pt_regs regs; /* Contents not used. */ @@ -332,102 +307,6 @@ static void bfin_handle_irq(unsigned irq) #endif /* !CONFIG_IPIPE */ } -#ifdef BF537_GENERIC_ERROR_INT_DEMUX -static int error_int_mask; - -static void bfin_generic_error_mask_irq(struct irq_data *d) -{ - error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR)); - if (!error_int_mask) - bfin_internal_mask_irq(IRQ_GENERIC_ERROR); -} - -static void bfin_generic_error_unmask_irq(struct irq_data *d) -{ - bfin_internal_unmask_irq(IRQ_GENERIC_ERROR); - error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR); -} - -static struct irq_chip bfin_generic_error_irqchip = { - .name = "ERROR", - .irq_ack = bfin_ack_noop, - .irq_mask_ack = bfin_generic_error_mask_irq, - .irq_mask = bfin_generic_error_mask_irq, - .irq_unmask = bfin_generic_error_unmask_irq, -}; - -static void bfin_demux_error_irq(unsigned int int_err_irq, - struct irq_desc *inta_desc) -{ - int irq = 0; - -#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) - if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK) - irq = IRQ_MAC_ERROR; - else -#endif - if (bfin_read_SPORT0_STAT() & SPORT_ERR_MASK) - irq = IRQ_SPORT0_ERROR; - else if (bfin_read_SPORT1_STAT() & SPORT_ERR_MASK) - irq = IRQ_SPORT1_ERROR; - else if (bfin_read_PPI_STATUS() & PPI_ERR_MASK) - irq = IRQ_PPI_ERROR; - else if (bfin_read_CAN_GIF() & CAN_ERR_MASK) - irq = IRQ_CAN_ERROR; - else if (bfin_read_SPI_STAT() & SPI_ERR_MASK) - irq = IRQ_SPI_ERROR; - else if ((bfin_read_UART0_IIR() & UART_ERR_MASK) == UART_ERR_MASK) - irq = IRQ_UART0_ERROR; - else if ((bfin_read_UART1_IIR() & UART_ERR_MASK) == UART_ERR_MASK) - irq = IRQ_UART1_ERROR; - - if (irq) { - if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) - bfin_handle_irq(irq); - else { - - switch (irq) { - case IRQ_PPI_ERROR: - bfin_write_PPI_STATUS(PPI_ERR_MASK); - break; -#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) - case IRQ_MAC_ERROR: - bfin_write_EMAC_SYSTAT(EMAC_ERR_MASK); - break; -#endif - case IRQ_SPORT0_ERROR: - bfin_write_SPORT0_STAT(SPORT_ERR_MASK); - break; - - case IRQ_SPORT1_ERROR: - bfin_write_SPORT1_STAT(SPORT_ERR_MASK); - break; - - case IRQ_CAN_ERROR: - bfin_write_CAN_GIS(CAN_ERR_MASK); - break; - - case IRQ_SPI_ERROR: - bfin_write_SPI_STAT(SPI_ERR_MASK); - break; - - default: - break; - } - - pr_debug("IRQ %d:" - " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n", - irq); - } - } else - printk(KERN_ERR - "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR" - " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n", - __func__, __FILE__, __LINE__); - -} -#endif /* BF537_GENERIC_ERROR_INT_DEMUX */ - #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) static int mac_stat_int_mask; @@ -468,7 +347,7 @@ static void bfin_mac_status_mask_irq(struct irq_data *d) unsigned int irq = d->irq; mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT)); -#ifdef BF537_GENERIC_ERROR_INT_DEMUX +#ifdef BF537_FAMILY switch (irq) { case IRQ_MAC_PHYINT: bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() & ~PHYIE); @@ -487,7 +366,7 @@ static void bfin_mac_status_unmask_irq(struct irq_data *d) { unsigned int irq = d->irq; -#ifdef BF537_GENERIC_ERROR_INT_DEMUX +#ifdef BF537_FAMILY switch (irq) { case IRQ_MAC_PHYINT: bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() | PHYIE); @@ -505,12 +384,14 @@ static void bfin_mac_status_unmask_irq(struct irq_data *d) #ifdef CONFIG_PM int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state) { -#ifdef BF537_GENERIC_ERROR_INT_DEMUX +#ifdef BF537_FAMILY return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state); #else return bfin_internal_set_wake(IRQ_MAC_ERROR, state); #endif } +#else +# define bfin_mac_status_set_wake NULL #endif static struct irq_chip bfin_mac_status_irqchip = { @@ -519,13 +400,11 @@ static struct irq_chip bfin_mac_status_irqchip = { .irq_mask_ack = bfin_mac_status_mask_irq, .irq_mask = bfin_mac_status_mask_irq, .irq_unmask = bfin_mac_status_unmask_irq, -#ifdef CONFIG_PM .irq_set_wake = bfin_mac_status_set_wake, -#endif }; -static void bfin_demux_mac_status_irq(unsigned int int_err_irq, - struct irq_desc *inta_desc) +void bfin_demux_mac_status_irq(unsigned int int_err_irq, + struct irq_desc *inta_desc) { int i, irq = 0; u32 status = bfin_read_EMAC_SYSTAT(); @@ -680,29 +559,48 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) } #ifdef CONFIG_PM -int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) +static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); } +#else +# define bfin_gpio_set_wake NULL #endif -static void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) +static void bfin_demux_gpio_block(unsigned int irq) { - unsigned int i, gpio, mask, irq, search = 0; + unsigned int gpio, mask; + + gpio = irq_to_gpio(irq); + mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio); + + while (mask) { + if (mask & 1) + bfin_handle_irq(irq); + irq++; + mask >>= 1; + } +} + +void bfin_demux_gpio_irq(unsigned int inta_irq, + struct irq_desc *desc) +{ + unsigned int irq; switch (inta_irq) { -#if defined(CONFIG_BF53x) - case IRQ_PROG_INTA: - irq = IRQ_PF0; - search = 1; +#if defined(BF537_FAMILY) + case IRQ_PF_INTA_PG_INTA: + bfin_demux_gpio_block(IRQ_PF0); + irq = IRQ_PG0; break; -# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) - case IRQ_MAC_RX: + case IRQ_PH_INTA_MAC_RX: irq = IRQ_PH0; break; -# endif -#elif defined(CONFIG_BF538) || defined(CONFIG_BF539) +#elif defined(BF533_FAMILY) + case IRQ_PROG_INTA: + irq = IRQ_PF0; + break; +#elif defined(BF538_FAMILY) case IRQ_PORTF_INTA: irq = IRQ_PF0; break; @@ -732,31 +630,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, return; } - if (search) { - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - irq += i; - - mask = get_gpiop_data(i) & get_gpiop_maska(i); - - while (mask) { - if (mask & 1) - bfin_handle_irq(irq); - irq++; - mask >>= 1; - } - } - } else { - gpio = irq_to_gpio(irq); - mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio); - - do { - if (mask & 1) - bfin_handle_irq(irq); - irq++; - mask >>= 1; - } while (mask); - } - + bfin_demux_gpio_block(irq); } #else /* CONFIG_BF54x */ @@ -974,15 +848,11 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) } #ifdef CONFIG_PM -u32 pint_saved_masks[NR_PINT_SYS_IRQS]; -u32 pint_wakeup_masks[NR_PINT_SYS_IRQS]; - -int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) +static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { u32 pint_irq; u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 bank = PINT_2_BANK(pint_val); - u32 pintbit = PINT_BIT(pint_val); switch (bank) { case 0: @@ -1003,46 +873,14 @@ int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) bfin_internal_set_wake(pint_irq, state); - if (state) - pint_wakeup_masks[bank] |= pintbit; - else - pint_wakeup_masks[bank] &= ~pintbit; - return 0; } - -u32 bfin_pm_setup(void) -{ - u32 val, i; - - for (i = 0; i < NR_PINT_SYS_IRQS; i++) { - val = pint[i]->mask_clear; - pint_saved_masks[i] = val; - if (val ^ pint_wakeup_masks[i]) { - pint[i]->mask_clear = val; - pint[i]->mask_set = pint_wakeup_masks[i]; - } - } - - return 0; -} - -void bfin_pm_restore(void) -{ - u32 i, val; - - for (i = 0; i < NR_PINT_SYS_IRQS; i++) { - val = pint_saved_masks[i]; - if (val ^ pint_wakeup_masks[i]) { - pint[i]->mask_clear = pint[i]->mask_clear; - pint[i]->mask_set = val; - } - } -} +#else +# define bfin_gpio_set_wake NULL #endif -static void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) +void bfin_demux_gpio_irq(unsigned int inta_irq, + struct irq_desc *desc) { u32 bank, pint_val; u32 request, irq; @@ -1091,9 +929,7 @@ static struct irq_chip bfin_gpio_irqchip = { .irq_set_type = bfin_gpio_irq_type, .irq_startup = bfin_gpio_irq_startup, .irq_shutdown = bfin_gpio_irq_shutdown, -#ifdef CONFIG_PM .irq_set_wake = bfin_gpio_set_wake, -#endif }; void __cpuinit init_exception_vectors(void) @@ -1127,12 +963,12 @@ int __init init_arch_irq(void) { int irq; unsigned long ilat = 0; + /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ - || defined(BF538_FAMILY) || defined(CONFIG_BF51x) +#ifdef SIC_IMASK0 bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); -# ifdef CONFIG_BF54x +# ifdef SIC_IMASK2 bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); # endif # ifdef CONFIG_SMP @@ -1145,11 +981,6 @@ int __init init_arch_irq(void) local_irq_disable(); -#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) - /* Clear EMAC Interrupt Status bits so we can demux it later */ - bfin_write_EMAC_SYSTAT(-1); -#endif - #ifdef CONFIG_BF54x # ifdef CONFIG_PINTx_REASSIGN pint[0]->assign = CONFIG_PINT0_ASSIGN; @@ -1168,11 +999,11 @@ int __init init_arch_irq(void) irq_set_chip(irq, &bfin_internal_irqchip); switch (irq) { -#if defined(CONFIG_BF53x) +#if defined(BF537_FAMILY) + case IRQ_PH_INTA_MAC_RX: + case IRQ_PF_INTA_PG_INTA: +#elif defined(BF533_FAMILY) case IRQ_PROG_INTA: -# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) - case IRQ_MAC_RX: -# endif #elif defined(CONFIG_BF54x) case IRQ_PINT0: case IRQ_PINT1: @@ -1186,16 +1017,11 @@ int __init init_arch_irq(void) case IRQ_PROG0_INTA: case IRQ_PROG1_INTA: case IRQ_PROG2_INTA: -#elif defined(CONFIG_BF538) || defined(CONFIG_BF539) +#elif defined(BF538_FAMILY) case IRQ_PORTF_INTA: #endif irq_set_chained_handler(irq, bfin_demux_gpio_irq); break; -#ifdef BF537_GENERIC_ERROR_INT_DEMUX - case IRQ_GENERIC_ERROR: - irq_set_chained_handler(irq, bfin_demux_error_irq); - break; -#endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) case IRQ_MAC_ERROR: irq_set_chained_handler(irq, @@ -1213,11 +1039,10 @@ int __init init_arch_irq(void) case IRQ_CORETMR: # ifdef CONFIG_SMP irq_set_handler(irq, handle_percpu_irq); - break; # else irq_set_handler(irq, handle_simple_irq); - break; # endif + break; #endif #ifdef CONFIG_TICKSOURCE_GPTMR0 @@ -1226,26 +1051,17 @@ int __init init_arch_irq(void) break; #endif -#ifdef CONFIG_IPIPE default: +#ifdef CONFIG_IPIPE irq_set_handler(irq, handle_level_irq); - break; -#else /* !CONFIG_IPIPE */ - default: +#else irq_set_handler(irq, handle_simple_irq); +#endif break; -#endif /* !CONFIG_IPIPE */ } } -#ifdef BF537_GENERIC_ERROR_INT_DEMUX - for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++) - irq_set_chip_and_handler(irq, &bfin_generic_error_irqchip, - handle_level_irq); -#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) - irq_set_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq); -#endif -#endif + init_mach_irq(); #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++) @@ -1307,53 +1123,54 @@ int __init init_arch_irq(void) #ifdef CONFIG_DO_IRQ_L1 __attribute__((l1_text)) #endif -void do_irq(int vec, struct pt_regs *fp) +static int vec_to_irq(int vec) { - if (vec == EVT_IVTMR_P) { - vec = IRQ_CORETMR; - } else { - struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; - struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; -#if defined(SIC_ISR0) - unsigned long sic_status[3]; + struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; + struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; + unsigned long sic_status[3]; + + if (likely(vec == EVT_IVTMR_P)) + return IRQ_CORETMR; - if (smp_processor_id()) { +#ifdef SIC_ISR + sic_status[0] = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); +#else + if (smp_processor_id()) { # ifdef SICB_ISR0 - /* This will be optimized out in UP mode. */ - sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0(); - sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1(); -# endif - } else { - sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); - sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); - } -# ifdef SIC_ISR2 - sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); + /* This will be optimized out in UP mode. */ + sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0(); + sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1(); # endif - for (;; ivg++) { - if (ivg >= ivg_stop) { - atomic_inc(&num_spurious); - return; - } - if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) - break; - } -#else - unsigned long sic_status; - - sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); + } else { + sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); + sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); + } +#endif +#ifdef SIC_ISR2 + sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); +#endif - for (;; ivg++) { - if (ivg >= ivg_stop) { - atomic_inc(&num_spurious); - return; - } else if (sic_status & ivg->isrflag) - break; - } + for (;; ivg++) { + if (ivg >= ivg_stop) + return -1; +#ifdef SIC_ISR + if (sic_status[0] & ivg->isrflag) +#else + if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) #endif - vec = ivg->irqno; + return ivg->irqno; } - asm_do_IRQ(vec, fp); +} + +#ifdef CONFIG_DO_IRQ_L1 +__attribute__((l1_text)) +#endif +void do_irq(int vec, struct pt_regs *fp) +{ + int irq = vec_to_irq(vec); + if (irq == -1) + return; + asm_do_IRQ(irq, fp); } #ifdef CONFIG_IPIPE @@ -1391,40 +1208,9 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; int irq, s = 0; - if (likely(vec == EVT_IVTMR_P)) - irq = IRQ_CORETMR; - else { -#if defined(SIC_ISR0) - unsigned long sic_status[3]; - - sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); - sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); -# ifdef SIC_ISR2 - sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); -# endif - for (;; ivg++) { - if (ivg >= ivg_stop) { - atomic_inc(&num_spurious); - return 0; - } - if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) - break; - } -#else - unsigned long sic_status; - - sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); - - for (;; ivg++) { - if (ivg >= ivg_stop) { - atomic_inc(&num_spurious); - return 0; - } else if (sic_status & ivg->isrflag) - break; - } -#endif - irq = ivg->irqno; - } + irq = vec_to_irq(vec); + if (irq == -1) + return 0; if (irq == IRQ_SYSTMR) { #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_TICKSOURCE_GPTMR0) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 1fbd94c4445..35e7e1eb018 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -25,6 +25,7 @@ #include <linux/slab.h> #include <asm/atomic.h> #include <asm/cacheflush.h> +#include <asm/irq_handler.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> @@ -96,7 +97,7 @@ static void ipi_cpu_stop(unsigned int cpu) dump_stack(); spin_unlock(&stop_lock); - cpu_clear(cpu, cpu_online_map); + set_cpu_online(cpu, false); local_irq_disable(); @@ -146,7 +147,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) */ resync_core_dcache(); #endif - cpu_clear(cpu, *msg->call_struct.waitmask); + cpumask_clear_cpu(cpu, msg->call_struct.waitmask); } } @@ -222,9 +223,10 @@ static inline void smp_send_message(cpumask_t callmap, unsigned long type, struct ipi_message_queue *msg_queue; struct ipi_message *msg; unsigned long flags, next_msg; - cpumask_t waitmask = callmap; /* waitmask is shared by all cpus */ + cpumask_t waitmask; /* waitmask is shared by all cpus */ - for_each_cpu_mask(cpu, callmap) { + cpumask_copy(&waitmask, &callmap); + for_each_cpu(cpu, &callmap) { msg_queue = &per_cpu(ipi_msg_queue, cpu); spin_lock_irqsave(&msg_queue->lock, flags); if (msg_queue->count < BFIN_IPI_MSGQ_LEN) { @@ -246,7 +248,7 @@ static inline void smp_send_message(cpumask_t callmap, unsigned long type, } if (wait) { - while (!cpus_empty(waitmask)) + while (!cpumask_empty(&waitmask)) blackfin_dcache_invalidate_range( (unsigned long)(&waitmask), (unsigned long)(&waitmask)); @@ -265,9 +267,9 @@ int smp_call_function(void (*func)(void *info), void *info, int wait) cpumask_t callmap; preempt_disable(); - callmap = cpu_online_map; - cpu_clear(smp_processor_id(), callmap); - if (!cpus_empty(callmap)) + cpumask_copy(&callmap, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &callmap); + if (!cpumask_empty(&callmap)) smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); preempt_enable(); @@ -284,8 +286,8 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, if (cpu_is_offline(cpu)) return 0; - cpus_clear(callmap); - cpu_set(cpu, callmap); + cpumask_clear(&callmap); + cpumask_set_cpu(cpu, &callmap); smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); @@ -308,9 +310,9 @@ void smp_send_stop(void) cpumask_t callmap; preempt_disable(); - callmap = cpu_online_map; - cpu_clear(smp_processor_id(), callmap); - if (!cpus_empty(callmap)) + cpumask_copy(&callmap, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &callmap); + if (!cpumask_empty(&callmap)) smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); preempt_enable(); diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c index dfd304a4a3e..29d98faa1ef 100644 --- a/arch/blackfin/mm/sram-alloc.c +++ b/arch/blackfin/mm/sram-alloc.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/rtc.h> #include <linux/slab.h> @@ -764,7 +765,7 @@ EXPORT_SYMBOL(sram_alloc_with_lsl); /* Need to keep line of output the same. Currently, that is 44 bytes * (including newline). */ -static int _sram_proc_read(char *buf, int *len, int count, const char *desc, +static int _sram_proc_show(struct seq_file *m, const char *desc, struct sram_piece *pfree_head, struct sram_piece *pused_head) { @@ -773,13 +774,13 @@ static int _sram_proc_read(char *buf, int *len, int count, const char *desc, if (!pfree_head || !pused_head) return -1; - *len += sprintf(&buf[*len], "--- SRAM %-14s Size PID State \n", desc); + seq_printf(m, "--- SRAM %-14s Size PID State \n", desc); /* search the relevant memory slot */ pslot = pused_head->next; while (pslot != NULL) { - *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", + seq_printf(m, "%p-%p %10i %5i %-10s\n", pslot->paddr, pslot->paddr + pslot->size, pslot->size, pslot->pid, "ALLOCATED"); @@ -789,7 +790,7 @@ static int _sram_proc_read(char *buf, int *len, int count, const char *desc, pslot = pfree_head->next; while (pslot != NULL) { - *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", + seq_printf(m, "%p-%p %10i %5i %-10s\n", pslot->paddr, pslot->paddr + pslot->size, pslot->size, pslot->pid, "FREE"); @@ -798,54 +799,62 @@ static int _sram_proc_read(char *buf, int *len, int count, const char *desc, return 0; } -static int sram_proc_read(char *buf, char **start, off_t offset, int count, - int *eof, void *data) +static int sram_proc_show(struct seq_file *m, void *v) { - int len = 0; unsigned int cpu; for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { - if (_sram_proc_read(buf, &len, count, "Scratchpad", + if (_sram_proc_show(m, "Scratchpad", &per_cpu(free_l1_ssram_head, cpu), &per_cpu(used_l1_ssram_head, cpu))) goto not_done; #if L1_DATA_A_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Data A", + if (_sram_proc_show(m, "L1 Data A", &per_cpu(free_l1_data_A_sram_head, cpu), &per_cpu(used_l1_data_A_sram_head, cpu))) goto not_done; #endif #if L1_DATA_B_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Data B", + if (_sram_proc_show(m, "L1 Data B", &per_cpu(free_l1_data_B_sram_head, cpu), &per_cpu(used_l1_data_B_sram_head, cpu))) goto not_done; #endif #if L1_CODE_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L1 Instruction", + if (_sram_proc_show(m, "L1 Instruction", &per_cpu(free_l1_inst_sram_head, cpu), &per_cpu(used_l1_inst_sram_head, cpu))) goto not_done; #endif } #if L2_LENGTH != 0 - if (_sram_proc_read(buf, &len, count, "L2", &free_l2_sram_head, - &used_l2_sram_head)) + if (_sram_proc_show(m, "L2", &free_l2_sram_head, &used_l2_sram_head)) goto not_done; #endif - *eof = 1; not_done: - return len; + return 0; +} + +static int sram_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, sram_proc_show, NULL); } +static const struct file_operations sram_proc_ops = { + .open = sram_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int __init sram_proc_init(void) { struct proc_dir_entry *ptr; - ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL); + + ptr = proc_create("sram", S_IRUGO, NULL, &sram_proc_ops); if (!ptr) { printk(KERN_WARNING "unable to create /proc/sram\n"); return -1; } - ptr->read_proc = sram_proc_read; return 0; } late_initcall(sram_proc_init); diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index e32b0c23c4c..635e1bfb1c5 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -339,6 +339,14 @@ config NO_IOPORT source "drivers/pci/Kconfig" +config HOTPLUG + bool "Support for hot-pluggable devices" + ---help--- + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + One well-known example of this is USB. + source "drivers/pci/hotplug/Kconfig" endmenu diff --git a/arch/tile/configs/tile_defconfig b/arch/tile/configs/tile_defconfig deleted file mode 100644 index 0fe54445fda..00000000000 --- a/arch/tile/configs/tile_defconfig +++ /dev/null @@ -1,71 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="usr/contents.txt" -CONFIG_EXPERT=y -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_HZ_100=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -CONFIG_IPV6=y -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_NETDEVICES=y -CONFIG_TUN=y -# CONFIG_NETDEV_10000 is not set -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -# CONFIG_HID_SUPPORT is not set -CONFIG_RTC_CLASS=y -# CONFIG_RTC_INTF_SYSFS is not set -# CONFIG_RTC_INTF_PROC is not set -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=m -CONFIG_TMPFS=y -CONFIG_HUGETLBFS=y -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_FRAME_WARN=2048 -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_VM=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_EXTRA_FLAGS="-femit-struct-debug-baseonly" diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig new file mode 100644 index 00000000000..09f1c7fad8b --- /dev/null +++ b/arch/tile/configs/tilegx_defconfig @@ -0,0 +1,1833 @@ +# +# Automatically generated make config: don't edit +# Linux/tilegx 2.6.39-rc5 Kernel Configuration +# Wed May 4 11:08:04 2011 +# +CONFIG_TILE=y +CONFIG_MMU=y +CONFIG_GENERIC_CSUM=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_HAVE_ARCH_ALLOC_REMAP=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_DEFAULT_MIGRATION_COST=10000000 +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_STRICT_DEVMEM=y +CONFIG_SMP=y +# CONFIG_DEBUG_COPY_FROM_USER is not set +CONFIG_HVC_TILE=y +CONFIG_TILEGX=y +CONFIG_64BIT=y +CONFIG_ARCH_DEFCONFIG="arch/tile/configs/tilegx_defconfig" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=64 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=19 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_NS=y +# CONFIG_CGROUP_FREEZER is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="usr/contents.txt" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_USE_GENERIC_SMP_HELPERS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_BLK_DEV_THROTTLING is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PADATA=y +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y + +# +# Tilera-specific configuration +# +CONFIG_NR_CPUS=100 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +# CONFIG_HIGHMEM is not set +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=2 +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_DISCONTIGMEM_MANUAL=y +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CMDLINE_BOOL is not set +CONFIG_VMALLOC_RESERVE=0x1000000 +CONFIG_HARDWALL=y +CONFIG_KERNEL_PL=1 + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_NO_IOMEM is not set +# CONFIG_NO_IOPORT is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_DEBUG=y +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IPV6_MROUTE=y +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETLABEL=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +# CONFIG_NF_CONNTRACK_SNMP is not set +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +# CONFIG_NF_CT_NETLINK is not set +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +CONFIG_NETFILTER_XT_MATCH_DCCP=m +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +# CONFIG_IP_SET is not set +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +# CONFIG_IP_VS_DH is not set +# CONFIG_IP_VS_SH is not set +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +# CONFIG_IP_VS_NFCT is not set +# CONFIG_IP_VS_PE_SIP is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +# CONFIG_NF_NAT is not set +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_MV88E6131=y +CONFIG_NET_DSA_MV88E6123_61_65=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +CONFIG_PHONET=m +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +# CONFIG_NET_SCH_SFB is not set +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +# CONFIG_NET_ACT_CSUM is not set +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_ATA_OVER_ETH=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=m +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=m +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_SCSI_BNX2X_FCOE is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +CONFIG_SATA_SIL24=m +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARASAN_CF is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CS5536 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MULTICORE_RAID456=y +# CONFIG_MD_MULTIPATH is not set +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +# CONFIG_DM_RAID is not set +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y +CONFIG_VETH=m +# CONFIG_ARCNET is not set +# CONFIG_MII is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_NET_ETHERNET is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +CONFIG_E1000E=m +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set +# CONFIG_STMMAC_ETH is not set +# CONFIG_PCH_GBE is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_TILE_NET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MFD_HSU is not set +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_HVC_DRIVER=y +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_INTEL_MID is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_TILE=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_FS_XIP=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +CONFIG_JBD2_DEBUG=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +# CONFIG_OCFS2_FS is not set +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +CONFIG_GENERIC_ACL=y + +# +# Caches +# +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=m +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_XATTR is not set +# CONFIG_SQUASHFS_LZO is not set +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_PNFS_FILE_LAYOUT=m +CONFIG_NFS_FSCACHE=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFS_USE_NEW_IDMAPPER is not set +CONFIG_NFSD=m +CONFIG_NFSD_DEPRECATED=y +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +# CONFIG_CIFS_STATS2 is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_FSCACHE=y +# CONFIG_CIFS_ACL is not set +CONFIG_CIFS_EXPERIMENTAL=y +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +CONFIG_HEADERS_CHECK=y +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_LIST=y +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BUILD_DOCSRC is not set +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_ATOMIC64_SELFTEST is not set +CONFIG_ASYNC_RAID6_TEST=m +# CONFIG_SAMPLES is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_EXTRA_FLAGS="" + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=65536 +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_IMA is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYPTO_LZO=m + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=m +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_VIRTUALIZATION is not set diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig new file mode 100644 index 00000000000..f58dc362b94 --- /dev/null +++ b/arch/tile/configs/tilepro_defconfig @@ -0,0 +1,1163 @@ +# +# Automatically generated make config: don't edit +# Linux/tile 2.6.39-rc5 Kernel Configuration +# Tue May 3 09:15:02 2011 +# +CONFIG_TILE=y +CONFIG_MMU=y +CONFIG_GENERIC_CSUM=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_HAVE_ARCH_ALLOC_REMAP=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_DEFAULT_MIGRATION_COST=10000000 +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_STRICT_DEVMEM=y +CONFIG_SMP=y +# CONFIG_DEBUG_COPY_FROM_USER is not set +CONFIG_HVC_TILE=y +# CONFIG_TILEGX is not set +CONFIG_ARCH_DEFCONFIG="arch/tile/configs/tile_defconfig" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_FHANDLE=y +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="usr/contents.txt" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_USE_GENERIC_SMP_HELPERS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y + +# +# Tilera-specific configuration +# +CONFIG_NR_CPUS=64 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +CONFIG_HIGHMEM=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=2 +# CONFIG_VMSPLIT_3_75G is not set +# CONFIG_VMSPLIT_3_5G is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2_75G is not set +# CONFIG_VMSPLIT_2_5G is not set +# CONFIG_VMSPLIT_2_25G is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_DISCONTIGMEM_MANUAL=y +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CMDLINE_BOOL is not set +CONFIG_VMALLOC_RESERVE=0x1000000 +CONFIG_HARDWALL=y +CONFIG_KERNEL_PL=1 + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_NO_IOMEM is not set +# CONFIG_NO_IOPORT is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_SCSI_BNX2X_FCOE is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_MII is not set +# CONFIG_PHYLIB is not set +# CONFIG_NET_ETHERNET is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set +# CONFIG_STMMAC_ETH is not set +# CONFIG_PCH_GBE is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +CONFIG_TILE_NET=y +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MFD_HSU is not set +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_HVC_DRIVER=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=y +CONFIG_EDAC_TILE=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +# CONFIG_RTC_INTF_SYSFS is not set +# CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_TILE=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_EXTRA_FLAGS="-femit-struct-debug-baseonly" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +CONFIG_HAVE_KVM=y +# CONFIG_VIRTUALIZATION is not set diff --git a/arch/tile/include/arch/chip_tilegx.h b/arch/tile/include/arch/chip_tilegx.h new file mode 100644 index 00000000000..ea8e4f2c948 --- /dev/null +++ b/arch/tile/include/arch/chip_tilegx.h @@ -0,0 +1,258 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* + * @file + * Global header file. + * This header file specifies defines for TILE-Gx. + */ + +#ifndef __ARCH_CHIP_H__ +#define __ARCH_CHIP_H__ + +/** Specify chip version. + * When possible, prefer the CHIP_xxx symbols below for future-proofing. + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip__ symbol. + */ +#define TILE_CHIP 10 + +/** Specify chip revision. + * This provides for the case of a respin of a particular chip type; + * the normal value for this symbol is "0". + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip_rev__ symbol. + */ +#define TILE_CHIP_REV 0 + +/** The name of this architecture. */ +#define CHIP_ARCH_NAME "tilegx" + +/** The ELF e_machine type for binaries for this chip. */ +#define CHIP_ELF_TYPE() EM_TILEGX + +/** The alternate ELF e_machine type for binaries for this chip. */ +#define CHIP_COMPAT_ELF_TYPE() 0x2597 + +/** What is the native word size of the machine? */ +#define CHIP_WORD_SIZE() 64 + +/** How many bits of a virtual address are used. Extra bits must be + * the sign extension of the low bits. + */ +#define CHIP_VA_WIDTH() 42 + +/** How many bits are in a physical address? */ +#define CHIP_PA_WIDTH() 40 + +/** Size of the L2 cache, in bytes. */ +#define CHIP_L2_CACHE_SIZE() 262144 + +/** Log size of an L2 cache line in bytes. */ +#define CHIP_L2_LOG_LINE_SIZE() 6 + +/** Size of an L2 cache line, in bytes. */ +#define CHIP_L2_LINE_SIZE() (1 << CHIP_L2_LOG_LINE_SIZE()) + +/** Associativity of the L2 cache. */ +#define CHIP_L2_ASSOC() 8 + +/** Size of the L1 data cache, in bytes. */ +#define CHIP_L1D_CACHE_SIZE() 32768 + +/** Log size of an L1 data cache line in bytes. */ +#define CHIP_L1D_LOG_LINE_SIZE() 6 + +/** Size of an L1 data cache line, in bytes. */ +#define CHIP_L1D_LINE_SIZE() (1 << CHIP_L1D_LOG_LINE_SIZE()) + +/** Associativity of the L1 data cache. */ +#define CHIP_L1D_ASSOC() 2 + +/** Size of the L1 instruction cache, in bytes. */ +#define CHIP_L1I_CACHE_SIZE() 32768 + +/** Log size of an L1 instruction cache line in bytes. */ +#define CHIP_L1I_LOG_LINE_SIZE() 6 + +/** Size of an L1 instruction cache line, in bytes. */ +#define CHIP_L1I_LINE_SIZE() (1 << CHIP_L1I_LOG_LINE_SIZE()) + +/** Associativity of the L1 instruction cache. */ +#define CHIP_L1I_ASSOC() 2 + +/** Stride with which flush instructions must be issued. */ +#define CHIP_FLUSH_STRIDE() CHIP_L2_LINE_SIZE() + +/** Stride with which inv instructions must be issued. */ +#define CHIP_INV_STRIDE() CHIP_L2_LINE_SIZE() + +/** Stride with which finv instructions must be issued. */ +#define CHIP_FINV_STRIDE() CHIP_L2_LINE_SIZE() + +/** Can the local cache coherently cache data that is homed elsewhere? */ +#define CHIP_HAS_COHERENT_LOCAL_CACHE() 1 + +/** How many simultaneous outstanding victims can the L2 cache have? */ +#define CHIP_MAX_OUTSTANDING_VICTIMS() 128 + +/** Does the TLB support the NC and NOALLOC bits? */ +#define CHIP_HAS_NC_AND_NOALLOC_BITS() 1 + +/** Does the chip support hash-for-home caching? */ +#define CHIP_HAS_CBOX_HOME_MAP() 1 + +/** Number of entries in the chip's home map tables. */ +#define CHIP_CBOX_HOME_MAP_SIZE() 128 + +/** Do uncacheable requests miss in the cache regardless of whether + * there is matching data? */ +#define CHIP_HAS_ENFORCED_UNCACHEABLE_REQUESTS() 1 + +/** Does the mf instruction wait for victims? */ +#define CHIP_HAS_MF_WAITS_FOR_VICTIMS() 0 + +/** Does the chip have an "inv" instruction that doesn't also flush? */ +#define CHIP_HAS_INV() 1 + +/** Does the chip have a "wh64" instruction? */ +#define CHIP_HAS_WH64() 1 + +/** Does this chip have a 'dword_align' instruction? */ +#define CHIP_HAS_DWORD_ALIGN() 0 + +/** Number of performance counters. */ +#define CHIP_PERFORMANCE_COUNTERS() 4 + +/** Does this chip have auxiliary performance counters? */ +#define CHIP_HAS_AUX_PERF_COUNTERS() 1 + +/** Is the CBOX_MSR1 SPR supported? */ +#define CHIP_HAS_CBOX_MSR1() 0 + +/** Is the TILE_RTF_HWM SPR supported? */ +#define CHIP_HAS_TILE_RTF_HWM() 1 + +/** Is the TILE_WRITE_PENDING SPR supported? */ +#define CHIP_HAS_TILE_WRITE_PENDING() 0 + +/** Is the PROC_STATUS SPR supported? */ +#define CHIP_HAS_PROC_STATUS_SPR() 1 + +/** Is the DSTREAM_PF SPR supported? */ +#define CHIP_HAS_DSTREAM_PF() 1 + +/** Log of the number of mshims we have. */ +#define CHIP_LOG_NUM_MSHIMS() 2 + +/** Are the bases of the interrupt vector areas fixed? */ +#define CHIP_HAS_FIXED_INTVEC_BASE() 0 + +/** Are the interrupt masks split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_INTR_MASK() 0 + +/** Is the cycle count split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_CYCLE() 0 + +/** Does the chip have a static network? */ +#define CHIP_HAS_SN() 0 + +/** Does the chip have a static network processor? */ +#define CHIP_HAS_SN_PROC() 0 + +/** Size of the L1 static network processor instruction cache, in bytes. */ +/* #define CHIP_L1SNI_CACHE_SIZE() -- does not apply to chip 10 */ + +/** Does the chip have DMA support in each tile? */ +#define CHIP_HAS_TILE_DMA() 0 + +/** Does the chip have the second revision of the directly accessible + * dynamic networks? This encapsulates a number of characteristics, + * including the absence of the catch-all, the absence of inline message + * tags, the absence of support for network context-switching, and so on. + */ +#define CHIP_HAS_REV1_XDN() 1 + +/** Does the chip have cmpexch and similar (fetchadd, exch, etc.)? */ +#define CHIP_HAS_CMPEXCH() 1 + +/** Does the chip have memory-mapped I/O support? */ +#define CHIP_HAS_MMIO() 1 + +/** Does the chip have post-completion interrupts? */ +#define CHIP_HAS_POST_COMPLETION_INTERRUPTS() 1 + +/** Does the chip have native single step support? */ +#define CHIP_HAS_SINGLE_STEP() 1 + +#ifndef __OPEN_SOURCE__ /* features only relevant to hypervisor-level code */ + +/** How many entries are present in the instruction TLB? */ +#define CHIP_ITLB_ENTRIES() 16 + +/** How many entries are present in the data TLB? */ +#define CHIP_DTLB_ENTRIES() 32 + +/** How many MAF entries does the XAUI shim have? */ +#define CHIP_XAUI_MAF_ENTRIES() 32 + +/** Does the memory shim have a source-id table? */ +#define CHIP_HAS_MSHIM_SRCID_TABLE() 0 + +/** Does the L1 instruction cache clear on reset? */ +#define CHIP_HAS_L1I_CLEAR_ON_RESET() 1 + +/** Does the chip come out of reset with valid coordinates on all tiles? + * Note that if defined, this also implies that the upper left is 1,1. + */ +#define CHIP_HAS_VALID_TILE_COORD_RESET() 1 + +/** Does the chip have unified packet formats? */ +#define CHIP_HAS_UNIFIED_PACKET_FORMATS() 1 + +/** Does the chip support write reordering? */ +#define CHIP_HAS_WRITE_REORDERING() 1 + +/** Does the chip support Y-X routing as well as X-Y? */ +#define CHIP_HAS_Y_X_ROUTING() 1 + +/** Is INTCTRL_3 managed with the correct MPL? */ +#define CHIP_HAS_INTCTRL_3_STATUS_FIX() 1 + +/** Is it possible to configure the chip to be big-endian? */ +#define CHIP_HAS_BIG_ENDIAN_CONFIG() 1 + +/** Is the CACHE_RED_WAY_OVERRIDDEN SPR supported? */ +#define CHIP_HAS_CACHE_RED_WAY_OVERRIDDEN() 0 + +/** Is the DIAG_TRACE_WAY SPR supported? */ +#define CHIP_HAS_DIAG_TRACE_WAY() 0 + +/** Is the MEM_STRIPE_CONFIG SPR supported? */ +#define CHIP_HAS_MEM_STRIPE_CONFIG() 1 + +/** Are the TLB_PERF SPRs supported? */ +#define CHIP_HAS_TLB_PERF() 1 + +/** Is the VDN_SNOOP_SHIM_CTL SPR supported? */ +#define CHIP_HAS_VDN_SNOOP_SHIM_CTL() 0 + +/** Does the chip support rev1 DMA packets? */ +#define CHIP_HAS_REV1_DMA_PACKETS() 1 + +/** Does the chip have an IPI shim? */ +#define CHIP_HAS_IPI() 1 + +#endif /* !__OPEN_SOURCE__ */ +#endif /* __ARCH_CHIP_H__ */ diff --git a/arch/tile/include/arch/icache.h b/arch/tile/include/arch/icache.h index 5c87c901633..762eafa8a11 100644 --- a/arch/tile/include/arch/icache.h +++ b/arch/tile/include/arch/icache.h @@ -16,7 +16,7 @@ /** * @file * - * Support for invalidating bytes in the instruction + * Support for invalidating bytes in the instruction cache. */ #ifndef __ARCH_ICACHE_H__ @@ -30,11 +30,10 @@ * * @param addr The start of memory to be invalidated. * @param size The number of bytes to be invalidated. - * @param page_size The system's page size, typically the PAGE_SIZE constant - * in sys/page.h. This value must be a power of two no larger - * than the page containing the code to be invalidated. If the value - * is smaller than the actual page size, this function will still - * work, but may run slower than necessary. + * @param page_size The system's page size, e.g. getpagesize() in userspace. + * This value must be a power of two no larger than the page containing + * the code to be invalidated. If the value is smaller than the actual page + * size, this function will still work, but may run slower than necessary. */ static __inline void invalidate_icache(const void* addr, unsigned long size, diff --git a/arch/tile/include/arch/interrupts_64.h b/arch/tile/include/arch/interrupts_64.h new file mode 100644 index 00000000000..5bb58b2e4e6 --- /dev/null +++ b/arch/tile/include/arch/interrupts_64.h @@ -0,0 +1,276 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef __ARCH_INTERRUPTS_H__ +#define __ARCH_INTERRUPTS_H__ + +/** Mask for an interrupt. */ +#ifdef __ASSEMBLER__ +/* Note: must handle breaking interrupts into high and low words manually. */ +#define INT_MASK(intno) (1 << (intno)) +#else +#define INT_MASK(intno) (1ULL << (intno)) +#endif + + +/** Where a given interrupt executes */ +#define INTERRUPT_VECTOR(i, pl) (0xFC000000 + ((pl) << 24) + ((i) << 8)) + +/** Where to store a vector for a given interrupt. */ +#define USER_INTERRUPT_VECTOR(i) INTERRUPT_VECTOR(i, 0) + +/** The base address of user-level interrupts. */ +#define USER_INTERRUPT_VECTOR_BASE INTERRUPT_VECTOR(0, 0) + + +/** Additional synthetic interrupt. */ +#define INT_BREAKPOINT (63) + +#define INT_MEM_ERROR 0 +#define INT_SINGLE_STEP_3 1 +#define INT_SINGLE_STEP_2 2 +#define INT_SINGLE_STEP_1 3 +#define INT_SINGLE_STEP_0 4 +#define INT_IDN_COMPLETE 5 +#define INT_UDN_COMPLETE 6 +#define INT_ITLB_MISS 7 +#define INT_ILL 8 +#define INT_GPV 9 +#define INT_IDN_ACCESS 10 +#define INT_UDN_ACCESS 11 +#define INT_SWINT_3 12 +#define INT_SWINT_2 13 +#define INT_SWINT_1 14 +#define INT_SWINT_0 15 +#define INT_ILL_TRANS 16 +#define INT_UNALIGN_DATA 17 +#define INT_DTLB_MISS 18 +#define INT_DTLB_ACCESS 19 +#define INT_IDN_FIREWALL 20 +#define INT_UDN_FIREWALL 21 +#define INT_TILE_TIMER 22 +#define INT_AUX_TILE_TIMER 23 +#define INT_IDN_TIMER 24 +#define INT_UDN_TIMER 25 +#define INT_IDN_AVAIL 26 +#define INT_UDN_AVAIL 27 +#define INT_IPI_3 28 +#define INT_IPI_2 29 +#define INT_IPI_1 30 +#define INT_IPI_0 31 +#define INT_PERF_COUNT 32 +#define INT_AUX_PERF_COUNT 33 +#define INT_INTCTRL_3 34 +#define INT_INTCTRL_2 35 +#define INT_INTCTRL_1 36 +#define INT_INTCTRL_0 37 +#define INT_BOOT_ACCESS 38 +#define INT_WORLD_ACCESS 39 +#define INT_I_ASID 40 +#define INT_D_ASID 41 +#define INT_DOUBLE_FAULT 42 + +#define NUM_INTERRUPTS 43 + +#ifndef __ASSEMBLER__ +#define QUEUED_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_AUX_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_IPI_3) | \ + INT_MASK(INT_IPI_2) | \ + INT_MASK(INT_IPI_1) | \ + INT_MASK(INT_IPI_0) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + 0) +#define NONQUEUED_INTERRUPTS ( \ + INT_MASK(INT_SINGLE_STEP_3) | \ + INT_MASK(INT_SINGLE_STEP_2) | \ + INT_MASK(INT_SINGLE_STEP_1) | \ + INT_MASK(INT_SINGLE_STEP_0) | \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_ILL_TRANS) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + 0) +#define CRITICAL_MASKED_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_SINGLE_STEP_3) | \ + INT_MASK(INT_SINGLE_STEP_2) | \ + INT_MASK(INT_SINGLE_STEP_1) | \ + INT_MASK(INT_SINGLE_STEP_0) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_AUX_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_IPI_3) | \ + INT_MASK(INT_IPI_2) | \ + INT_MASK(INT_IPI_1) | \ + INT_MASK(INT_IPI_0) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + 0) +#define CRITICAL_UNMASKED_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_ILL_TRANS) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + 0) +#define MASKABLE_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_SINGLE_STEP_3) | \ + INT_MASK(INT_SINGLE_STEP_2) | \ + INT_MASK(INT_SINGLE_STEP_1) | \ + INT_MASK(INT_SINGLE_STEP_0) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_AUX_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_IPI_3) | \ + INT_MASK(INT_IPI_2) | \ + INT_MASK(INT_IPI_1) | \ + INT_MASK(INT_IPI_0) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + 0) +#define UNMASKABLE_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_ILL_TRANS) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + 0) +#define SYNC_INTERRUPTS ( \ + INT_MASK(INT_SINGLE_STEP_3) | \ + INT_MASK(INT_SINGLE_STEP_2) | \ + INT_MASK(INT_SINGLE_STEP_1) | \ + INT_MASK(INT_SINGLE_STEP_0) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_ILL_TRANS) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + 0) +#define NON_SYNC_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_AUX_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_IPI_3) | \ + INT_MASK(INT_IPI_2) | \ + INT_MASK(INT_IPI_1) | \ + INT_MASK(INT_IPI_0) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + 0) +#endif /* !__ASSEMBLER__ */ +#endif /* !__ARCH_INTERRUPTS_H__ */ diff --git a/arch/tile/include/arch/spr_def.h b/arch/tile/include/arch/spr_def.h index 442fcba0d12..f548efeb2de 100644 --- a/arch/tile/include/arch/spr_def.h +++ b/arch/tile/include/arch/spr_def.h @@ -12,6 +12,15 @@ * more details. */ +/* Include the proper base SPR definition file. */ +#ifdef __tilegx__ +#include <arch/spr_def_64.h> +#else +#include <arch/spr_def_32.h> +#endif + +#ifdef __KERNEL__ + /* * In addition to including the proper base SPR definition file, depending * on machine architecture, this file defines several macros which allow @@ -29,7 +38,6 @@ #define _concat4(a, b, c, d) __concat4(a, b, c, d) #ifdef __tilegx__ -#include <arch/spr_def_64.h> /* TILE-Gx dependent, protection-level dependent SPRs. */ @@ -65,7 +73,6 @@ _concat4(INT_SINGLE_STEP_, CONFIG_KERNEL_PL,,) #else -#include <arch/spr_def_32.h> /* TILEPro dependent, protection-level dependent SPRs. */ @@ -102,3 +109,5 @@ _concat4(SPR_INTCTRL_, CONFIG_KERNEL_PL, _STATUS,) #define INT_INTCTRL_K \ _concat4(INT_INTCTRL_, CONFIG_KERNEL_PL,,) + +#endif /* __KERNEL__ */ diff --git a/arch/tile/include/arch/spr_def_64.h b/arch/tile/include/arch/spr_def_64.h new file mode 100644 index 00000000000..cd3e5f95d5f --- /dev/null +++ b/arch/tile/include/arch/spr_def_64.h @@ -0,0 +1,173 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef __DOXYGEN__ + +#ifndef __ARCH_SPR_DEF_H__ +#define __ARCH_SPR_DEF_H__ + +#define SPR_AUX_PERF_COUNT_0 0x2105 +#define SPR_AUX_PERF_COUNT_1 0x2106 +#define SPR_AUX_PERF_COUNT_CTL 0x2107 +#define SPR_AUX_PERF_COUNT_STS 0x2108 +#define SPR_CMPEXCH_VALUE 0x2780 +#define SPR_CYCLE 0x2781 +#define SPR_DONE 0x2705 +#define SPR_DSTREAM_PF 0x2706 +#define SPR_EVENT_BEGIN 0x2782 +#define SPR_EVENT_END 0x2783 +#define SPR_EX_CONTEXT_0_0 0x2580 +#define SPR_EX_CONTEXT_0_1 0x2581 +#define SPR_EX_CONTEXT_0_1__PL_SHIFT 0 +#define SPR_EX_CONTEXT_0_1__PL_RMASK 0x3 +#define SPR_EX_CONTEXT_0_1__PL_MASK 0x3 +#define SPR_EX_CONTEXT_0_1__ICS_SHIFT 2 +#define SPR_EX_CONTEXT_0_1__ICS_RMASK 0x1 +#define SPR_EX_CONTEXT_0_1__ICS_MASK 0x4 +#define SPR_EX_CONTEXT_1_0 0x2480 +#define SPR_EX_CONTEXT_1_1 0x2481 +#define SPR_EX_CONTEXT_1_1__PL_SHIFT 0 +#define SPR_EX_CONTEXT_1_1__PL_RMASK 0x3 +#define SPR_EX_CONTEXT_1_1__PL_MASK 0x3 +#define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2 +#define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1 +#define SPR_EX_CONTEXT_1_1__ICS_MASK 0x4 +#define SPR_EX_CONTEXT_2_0 0x2380 +#define SPR_EX_CONTEXT_2_1 0x2381 +#define SPR_EX_CONTEXT_2_1__PL_SHIFT 0 +#define SPR_EX_CONTEXT_2_1__PL_RMASK 0x3 +#define SPR_EX_CONTEXT_2_1__PL_MASK 0x3 +#define SPR_EX_CONTEXT_2_1__ICS_SHIFT 2 +#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1 +#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4 +#define SPR_FAIL 0x2707 +#define SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK 0x1 +#define SPR_INTCTRL_0_STATUS 0x2505 +#define SPR_INTCTRL_1_STATUS 0x2405 +#define SPR_INTCTRL_2_STATUS 0x2305 +#define SPR_INTERRUPT_CRITICAL_SECTION 0x2708 +#define SPR_INTERRUPT_MASK_0 0x2506 +#define SPR_INTERRUPT_MASK_1 0x2406 +#define SPR_INTERRUPT_MASK_2 0x2306 +#define SPR_INTERRUPT_MASK_RESET_0 0x2507 +#define SPR_INTERRUPT_MASK_RESET_1 0x2407 +#define SPR_INTERRUPT_MASK_RESET_2 0x2307 +#define SPR_INTERRUPT_MASK_SET_0 0x2508 +#define SPR_INTERRUPT_MASK_SET_1 0x2408 +#define SPR_INTERRUPT_MASK_SET_2 0x2308 +#define SPR_INTERRUPT_VECTOR_BASE_0 0x2509 +#define SPR_INTERRUPT_VECTOR_BASE_1 0x2409 +#define SPR_INTERRUPT_VECTOR_BASE_2 0x2309 +#define SPR_INTERRUPT_VECTOR_BASE_3 0x2209 +#define SPR_IPI_EVENT_0 0x1f05 +#define SPR_IPI_EVENT_1 0x1e05 +#define SPR_IPI_EVENT_2 0x1d05 +#define SPR_IPI_EVENT_RESET_0 0x1f06 +#define SPR_IPI_EVENT_RESET_1 0x1e06 +#define SPR_IPI_EVENT_RESET_2 0x1d06 +#define SPR_IPI_EVENT_SET_0 0x1f07 +#define SPR_IPI_EVENT_SET_1 0x1e07 +#define SPR_IPI_EVENT_SET_2 0x1d07 +#define SPR_IPI_MASK_0 0x1f08 +#define SPR_IPI_MASK_1 0x1e08 +#define SPR_IPI_MASK_2 0x1d08 +#define SPR_IPI_MASK_RESET_0 0x1f09 +#define SPR_IPI_MASK_RESET_1 0x1e09 +#define SPR_IPI_MASK_RESET_2 0x1d09 +#define SPR_IPI_MASK_SET_0 0x1f0a +#define SPR_IPI_MASK_SET_1 0x1e0a +#define SPR_IPI_MASK_SET_2 0x1d0a +#define SPR_MPL_AUX_TILE_TIMER_SET_0 0x1700 +#define SPR_MPL_AUX_TILE_TIMER_SET_1 0x1701 +#define SPR_MPL_AUX_TILE_TIMER_SET_2 0x1702 +#define SPR_MPL_INTCTRL_0_SET_0 0x2500 +#define SPR_MPL_INTCTRL_0_SET_1 0x2501 +#define SPR_MPL_INTCTRL_0_SET_2 0x2502 +#define SPR_MPL_INTCTRL_1_SET_0 0x2400 +#define SPR_MPL_INTCTRL_1_SET_1 0x2401 +#define SPR_MPL_INTCTRL_1_SET_2 0x2402 +#define SPR_MPL_INTCTRL_2_SET_0 0x2300 +#define SPR_MPL_INTCTRL_2_SET_1 0x2301 +#define SPR_MPL_INTCTRL_2_SET_2 0x2302 +#define SPR_MPL_UDN_ACCESS_SET_0 0x0b00 +#define SPR_MPL_UDN_ACCESS_SET_1 0x0b01 +#define SPR_MPL_UDN_ACCESS_SET_2 0x0b02 +#define SPR_MPL_UDN_AVAIL_SET_0 0x1b00 +#define SPR_MPL_UDN_AVAIL_SET_1 0x1b01 +#define SPR_MPL_UDN_AVAIL_SET_2 0x1b02 +#define SPR_MPL_UDN_COMPLETE_SET_0 0x0600 +#define SPR_MPL_UDN_COMPLETE_SET_1 0x0601 +#define SPR_MPL_UDN_COMPLETE_SET_2 0x0602 +#define SPR_MPL_UDN_FIREWALL_SET_0 0x1500 +#define SPR_MPL_UDN_FIREWALL_SET_1 0x1501 +#define SPR_MPL_UDN_FIREWALL_SET_2 0x1502 +#define SPR_MPL_UDN_TIMER_SET_0 0x1900 +#define SPR_MPL_UDN_TIMER_SET_1 0x1901 +#define SPR_MPL_UDN_TIMER_SET_2 0x1902 +#define SPR_MPL_WORLD_ACCESS_SET_0 0x2700 +#define SPR_MPL_WORLD_ACCESS_SET_1 0x2701 +#define SPR_MPL_WORLD_ACCESS_SET_2 0x2702 +#define SPR_PASS 0x2709 +#define SPR_PERF_COUNT_0 0x2005 +#define SPR_PERF_COUNT_1 0x2006 +#define SPR_PERF_COUNT_CTL 0x2007 +#define SPR_PERF_COUNT_DN_CTL 0x2008 +#define SPR_PERF_COUNT_STS 0x2009 +#define SPR_PROC_STATUS 0x2784 +#define SPR_SIM_CONTROL 0x2785 +#define SPR_SINGLE_STEP_CONTROL_0 0x0405 +#define SPR_SINGLE_STEP_CONTROL_0__CANCELED_MASK 0x1 +#define SPR_SINGLE_STEP_CONTROL_0__INHIBIT_MASK 0x2 +#define SPR_SINGLE_STEP_CONTROL_1 0x0305 +#define SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK 0x1 +#define SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK 0x2 +#define SPR_SINGLE_STEP_CONTROL_2 0x0205 +#define SPR_SINGLE_STEP_CONTROL_2__CANCELED_MASK 0x1 +#define SPR_SINGLE_STEP_CONTROL_2__INHIBIT_MASK 0x2 +#define SPR_SINGLE_STEP_EN_0_0 0x250a +#define SPR_SINGLE_STEP_EN_0_1 0x240a +#define SPR_SINGLE_STEP_EN_0_2 0x230a +#define SPR_SINGLE_STEP_EN_1_0 0x250b +#define SPR_SINGLE_STEP_EN_1_1 0x240b +#define SPR_SINGLE_STEP_EN_1_2 0x230b +#define SPR_SINGLE_STEP_EN_2_0 0x250c +#define SPR_SINGLE_STEP_EN_2_1 0x240c +#define SPR_SINGLE_STEP_EN_2_2 0x230c +#define SPR_SYSTEM_SAVE_0_0 0x2582 +#define SPR_SYSTEM_SAVE_0_1 0x2583 +#define SPR_SYSTEM_SAVE_0_2 0x2584 +#define SPR_SYSTEM_SAVE_0_3 0x2585 +#define SPR_SYSTEM_SAVE_1_0 0x2482 +#define SPR_SYSTEM_SAVE_1_1 0x2483 +#define SPR_SYSTEM_SAVE_1_2 0x2484 +#define SPR_SYSTEM_SAVE_1_3 0x2485 +#define SPR_SYSTEM_SAVE_2_0 0x2382 +#define SPR_SYSTEM_SAVE_2_1 0x2383 +#define SPR_SYSTEM_SAVE_2_2 0x2384 +#define SPR_SYSTEM_SAVE_2_3 0x2385 +#define SPR_TILE_COORD 0x270b +#define SPR_TILE_RTF_HWM 0x270c +#define SPR_TILE_TIMER_CONTROL 0x1605 +#define SPR_UDN_AVAIL_EN 0x1b05 +#define SPR_UDN_DATA_AVAIL 0x0b80 +#define SPR_UDN_DEADLOCK_TIMEOUT 0x1906 +#define SPR_UDN_DEMUX_COUNT_0 0x0b05 +#define SPR_UDN_DEMUX_COUNT_1 0x0b06 +#define SPR_UDN_DEMUX_COUNT_2 0x0b07 +#define SPR_UDN_DEMUX_COUNT_3 0x0b08 +#define SPR_UDN_DIRECTION_PROTECT 0x1505 + +#endif /* !defined(__ARCH_SPR_DEF_H__) */ + +#endif /* !defined(__DOXYGEN__) */ diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h index 75a16028a95..739cfe0499d 100644 --- a/arch/tile/include/asm/atomic.h +++ b/arch/tile/include/asm/atomic.h @@ -130,17 +130,52 @@ static inline int atomic_read(const atomic_t *v) */ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) - -/* - * We define xchg() and cmpxchg() in the included headers. - * Note that we do not define __HAVE_ARCH_CMPXCHG, since that would imply - * that cmpxchg() is an efficient operation, which is not particularly true. - */ - /* Nonexistent functions intended to cause link errors. */ extern unsigned long __xchg_called_with_bad_pointer(void); extern unsigned long __cmpxchg_called_with_bad_pointer(void); +#define xchg(ptr, x) \ + ({ \ + typeof(*(ptr)) __x; \ + switch (sizeof(*(ptr))) { \ + case 4: \ + __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \ + (atomic_t *)(ptr), \ + (u32)(typeof((x)-(x)))(x)); \ + break; \ + case 8: \ + __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \ + (atomic64_t *)(ptr), \ + (u64)(typeof((x)-(x)))(x)); \ + break; \ + default: \ + __xchg_called_with_bad_pointer(); \ + } \ + __x; \ + }) + +#define cmpxchg(ptr, o, n) \ + ({ \ + typeof(*(ptr)) __x; \ + switch (sizeof(*(ptr))) { \ + case 4: \ + __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \ + (atomic_t *)(ptr), \ + (u32)(typeof((o)-(o)))(o), \ + (u32)(typeof((n)-(n)))(n)); \ + break; \ + case 8: \ + __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \ + (atomic64_t *)(ptr), \ + (u64)(typeof((o)-(o)))(o), \ + (u64)(typeof((n)-(n)))(n)); \ + break; \ + default: \ + __cmpxchg_called_with_bad_pointer(); \ + } \ + __x; \ + }) + #define tas(ptr) (xchg((ptr), 1)) #endif /* __ASSEMBLY__ */ diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h index ed359aee883..92a8bee3231 100644 --- a/arch/tile/include/asm/atomic_32.h +++ b/arch/tile/include/asm/atomic_32.h @@ -110,16 +110,6 @@ static inline void atomic_set(atomic_t *v, int n) _atomic_xchg(v, n); } -#define xchg(ptr, x) ((typeof(*(ptr))) \ - ((sizeof(*(ptr)) == sizeof(atomic_t)) ? \ - atomic_xchg((atomic_t *)(ptr), (long)(x)) : \ - __xchg_called_with_bad_pointer())) - -#define cmpxchg(ptr, o, n) ((typeof(*(ptr))) \ - ((sizeof(*(ptr)) == sizeof(atomic_t)) ? \ - atomic_cmpxchg((atomic_t *)(ptr), (long)(o), (long)(n)) : \ - __cmpxchg_called_with_bad_pointer())) - /* A 64bit atomic type */ typedef struct { diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h new file mode 100644 index 00000000000..1c1e60d8ccb --- /dev/null +++ b/arch/tile/include/asm/atomic_64.h @@ -0,0 +1,156 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Do not include directly; use <asm/atomic.h>. + */ + +#ifndef _ASM_TILE_ATOMIC_64_H +#define _ASM_TILE_ATOMIC_64_H + +#ifndef __ASSEMBLY__ + +#include <arch/spr_def.h> + +/* First, the 32-bit atomic ops that are "real" on our 64-bit platform. */ + +#define atomic_set(v, i) ((v)->counter = (i)) + +/* + * The smp_mb() operations throughout are to support the fact that + * Linux requires memory barriers before and after the operation, + * on any routine which updates memory and returns a value. + */ + +static inline int atomic_cmpxchg(atomic_t *v, int o, int n) +{ + int val; + __insn_mtspr(SPR_CMPEXCH_VALUE, o); + smp_mb(); /* barrier for proper semantics */ + val = __insn_cmpexch4((void *)&v->counter, n); + smp_mb(); /* barrier for proper semantics */ + return val; +} + +static inline int atomic_xchg(atomic_t *v, int n) +{ + int val; + smp_mb(); /* barrier for proper semantics */ + val = __insn_exch4((void *)&v->counter, n); + smp_mb(); /* barrier for proper semantics */ + return val; +} + +static inline void atomic_add(int i, atomic_t *v) +{ + __insn_fetchadd4((void *)&v->counter, i); +} + +static inline int atomic_add_return(int i, atomic_t *v) +{ + int val; + smp_mb(); /* barrier for proper semantics */ + val = __insn_fetchadd4((void *)&v->counter, i) + i; + barrier(); /* the "+ i" above will wait on memory */ + return val; +} + +static inline int atomic_add_unless(atomic_t *v, int a, int u) +{ + int guess, oldval = v->counter; + do { + if (oldval == u) + break; + guess = oldval; + oldval = atomic_cmpxchg(v, guess, guess + a); + } while (guess != oldval); + return oldval != u; +} + +/* Now the true 64-bit operations. */ + +#define ATOMIC64_INIT(i) { (i) } + +#define atomic64_read(v) ((v)->counter) +#define atomic64_set(v, i) ((v)->counter = (i)) + +static inline long atomic64_cmpxchg(atomic64_t *v, long o, long n) +{ + long val; + smp_mb(); /* barrier for proper semantics */ + __insn_mtspr(SPR_CMPEXCH_VALUE, o); + val = __insn_cmpexch((void *)&v->counter, n); + smp_mb(); /* barrier for proper semantics */ + return val; +} + +static inline long atomic64_xchg(atomic64_t *v, long n) +{ + long val; + smp_mb(); /* barrier for proper semantics */ + val = __insn_exch((void *)&v->counter, n); + smp_mb(); /* barrier for proper semantics */ + return val; +} + +static inline void atomic64_add(long i, atomic64_t *v) +{ + __insn_fetchadd((void *)&v->counter, i); +} + +static inline long atomic64_add_return(long i, atomic64_t *v) +{ + int val; + smp_mb(); /* barrier for proper semantics */ + val = __insn_fetchadd((void *)&v->counter, i) + i; + barrier(); /* the "+ i" above will wait on memory */ + return val; +} + +static inline long atomic64_add_unless(atomic64_t *v, long a, long u) +{ + long guess, oldval = v->counter; + do { + if (oldval == u) + break; + guess = oldval; + oldval = atomic64_cmpxchg(v, guess, guess + a); + } while (guess != oldval); + return oldval != u; +} + +#define atomic64_sub_return(i, v) atomic64_add_return(-(i), (v)) +#define atomic64_sub(i, v) atomic64_add(-(i), (v)) +#define atomic64_inc_return(v) atomic64_add_return(1, (v)) +#define atomic64_dec_return(v) atomic64_sub_return(1, (v)) +#define atomic64_inc(v) atomic64_add(1, (v)) +#define atomic64_dec(v) atomic64_sub(1, (v)) + +#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) +#define atomic64_dec_and_test(v) (atomic64_dec_return(v) == 0) +#define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0) +#define atomic64_add_negative(i, v) (atomic64_add_return((i), (v)) < 0) + +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) + +/* Atomic dec and inc don't implement barrier, so provide them if needed. */ +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +/* Define this to indicate that cmpxchg is an efficient operation. */ +#define __HAVE_ARCH_CMPXCHG + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_ATOMIC_64_H */ diff --git a/arch/tile/include/asm/backtrace.h b/arch/tile/include/asm/backtrace.h index f18887d8239..bd5399a69ed 100644 --- a/arch/tile/include/asm/backtrace.h +++ b/arch/tile/include/asm/backtrace.h @@ -12,80 +12,41 @@ * more details. */ -#ifndef _TILE_BACKTRACE_H -#define _TILE_BACKTRACE_H - - +#ifndef _ASM_TILE_BACKTRACE_H +#define _ASM_TILE_BACKTRACE_H #include <linux/types.h> -#include <arch/chip.h> - -#if defined(__tile__) -typedef unsigned long VirtualAddress; -#elif CHIP_VA_WIDTH() > 32 -typedef unsigned long long VirtualAddress; -#else -typedef unsigned int VirtualAddress; -#endif - - -/** Reads 'size' bytes from 'address' and writes the data to 'result'. +/* Reads 'size' bytes from 'address' and writes the data to 'result'. * Returns true if successful, else false (e.g. memory not readable). */ typedef bool (*BacktraceMemoryReader)(void *result, - VirtualAddress address, + unsigned long address, unsigned int size, void *extra); typedef struct { - /** Current PC. */ - VirtualAddress pc; + /* Current PC. */ + unsigned long pc; - /** Current stack pointer value. */ - VirtualAddress sp; + /* Current stack pointer value. */ + unsigned long sp; - /** Current frame pointer value (i.e. caller's stack pointer) */ - VirtualAddress fp; + /* Current frame pointer value (i.e. caller's stack pointer) */ + unsigned long fp; - /** Internal use only: caller's PC for first frame. */ - VirtualAddress initial_frame_caller_pc; + /* Internal use only: caller's PC for first frame. */ + unsigned long initial_frame_caller_pc; - /** Internal use only: callback to read memory. */ + /* Internal use only: callback to read memory. */ BacktraceMemoryReader read_memory_func; - /** Internal use only: arbitrary argument to read_memory_func. */ + /* Internal use only: arbitrary argument to read_memory_func. */ void *read_memory_func_extra; } BacktraceIterator; -/** Initializes a backtracer to start from the given location. - * - * If the frame pointer cannot be determined it is set to -1. - * - * @param state The state to be filled in. - * @param read_memory_func A callback that reads memory. If NULL, a default - * value is provided. - * @param read_memory_func_extra An arbitrary argument to read_memory_func. - * @param pc The current PC. - * @param lr The current value of the 'lr' register. - * @param sp The current value of the 'sp' register. - * @param r52 The current value of the 'r52' register. - */ -extern void backtrace_init(BacktraceIterator *state, - BacktraceMemoryReader read_memory_func, - void *read_memory_func_extra, - VirtualAddress pc, VirtualAddress lr, - VirtualAddress sp, VirtualAddress r52); - - -/** Advances the backtracing state to the calling frame, returning - * true iff successful. - */ -extern bool backtrace_next(BacktraceIterator *state); - - typedef enum { /* We have no idea what the caller's pc is. */ @@ -138,7 +99,7 @@ enum { }; -/** Internal constants used to define 'info' operands. */ +/* Internal constants used to define 'info' operands. */ enum { /* 0 and 1 are reserved, as are all negative numbers. */ @@ -147,13 +108,10 @@ enum { CALLER_SP_IN_R52_BASE = 4, CALLER_SP_OFFSET_BASE = 8, - - /* Marks the entry point of certain functions. */ - ENTRY_POINT_INFO_OP = 16 }; -/** Current backtracer state describing where it thinks the caller is. */ +/* Current backtracer state describing where it thinks the caller is. */ typedef struct { /* * Public fields @@ -192,7 +150,13 @@ typedef struct { } CallerLocation; +extern void backtrace_init(BacktraceIterator *state, + BacktraceMemoryReader read_memory_func, + void *read_memory_func_extra, + unsigned long pc, unsigned long lr, + unsigned long sp, unsigned long r52); +extern bool backtrace_next(BacktraceIterator *state); -#endif /* _TILE_BACKTRACE_H */ +#endif /* _ASM_TILE_BACKTRACE_H */ diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h index 132e6bbd07e..16f1fa51fea 100644 --- a/arch/tile/include/asm/bitops.h +++ b/arch/tile/include/asm/bitops.h @@ -122,6 +122,7 @@ static inline unsigned long __arch_hweight64(__u64 w) #include <asm-generic/bitops/lock.h> #include <asm-generic/bitops/find.h> #include <asm-generic/bitops/sched.h> +#include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/le.h> #endif /* _ASM_TILE_BITOPS_H */ diff --git a/arch/tile/include/asm/bitops_32.h b/arch/tile/include/asm/bitops_32.h index 2638be51a16..d31ab905cfa 100644 --- a/arch/tile/include/asm/bitops_32.h +++ b/arch/tile/include/asm/bitops_32.h @@ -126,7 +126,6 @@ static inline int test_and_change_bit(unsigned nr, #define smp_mb__before_clear_bit() smp_mb() #define smp_mb__after_clear_bit() do {} while (0) -#include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/ext2-atomic.h> #endif /* _ASM_TILE_BITOPS_32_H */ diff --git a/arch/tile/include/asm/bitops_64.h b/arch/tile/include/asm/bitops_64.h new file mode 100644 index 00000000000..99615e8d2d8 --- /dev/null +++ b/arch/tile/include/asm/bitops_64.h @@ -0,0 +1,105 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_BITOPS_64_H +#define _ASM_TILE_BITOPS_64_H + +#include <linux/compiler.h> +#include <asm/atomic.h> +#include <asm/system.h> + +/* See <asm/bitops.h> for API comments. */ + +static inline void set_bit(unsigned nr, volatile unsigned long *addr) +{ + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + __insn_fetchor((void *)(addr + nr / BITS_PER_LONG), mask); +} + +static inline void clear_bit(unsigned nr, volatile unsigned long *addr) +{ + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + __insn_fetchand((void *)(addr + nr / BITS_PER_LONG), ~mask); +} + +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() + + +static inline void change_bit(unsigned nr, volatile unsigned long *addr) +{ + unsigned long old, mask = (1UL << (nr % BITS_PER_LONG)); + long guess, oldval; + addr += nr / BITS_PER_LONG; + old = *addr; + do { + guess = oldval; + oldval = atomic64_cmpxchg((atomic64_t *)addr, + guess, guess ^ mask); + } while (guess != oldval); +} + + +/* + * The test_and_xxx_bit() routines require a memory fence before we + * start the operation, and after the operation completes. We use + * smp_mb() before, and rely on the "!= 0" comparison, plus a compiler + * barrier(), to block until the atomic op is complete. + */ + +static inline int test_and_set_bit(unsigned nr, volatile unsigned long *addr) +{ + int val; + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + smp_mb(); /* barrier for proper semantics */ + val = (__insn_fetchor((void *)(addr + nr / BITS_PER_LONG), mask) + & mask) != 0; + barrier(); + return val; +} + + +static inline int test_and_clear_bit(unsigned nr, volatile unsigned long *addr) +{ + int val; + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + smp_mb(); /* barrier for proper semantics */ + val = (__insn_fetchand((void *)(addr + nr / BITS_PER_LONG), ~mask) + & mask) != 0; + barrier(); + return val; +} + + +static inline int test_and_change_bit(unsigned nr, + volatile unsigned long *addr) +{ + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + long guess, oldval = *addr; + addr += nr / BITS_PER_LONG; + oldval = *addr; + do { + guess = oldval; + oldval = atomic64_cmpxchg((atomic64_t *)addr, + guess, guess ^ mask); + } while (guess != oldval); + return (oldval & mask) != 0; +} + +#define ext2_set_bit_atomic(lock, nr, addr) \ + test_and_set_bit((nr), (unsigned long *)(addr)) +#define ext2_clear_bit_atomic(lock, nr, addr) \ + test_and_clear_bit((nr), (unsigned long *)(addr)) + +#endif /* _ASM_TILE_BITOPS_64_H */ diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h index 12fb0fb330e..e925f4bb498 100644 --- a/arch/tile/include/asm/cacheflush.h +++ b/arch/tile/include/asm/cacheflush.h @@ -116,22 +116,28 @@ static inline void __finv_buffer(void *buffer, size_t size) } -/* Invalidate a VA range, then memory fence. */ +/* Invalidate a VA range and wait for it to be complete. */ static inline void inv_buffer(void *buffer, size_t size) { __inv_buffer(buffer, size); - mb_incoherent(); + mb(); } -/* Flush a VA range, then memory fence. */ -static inline void flush_buffer(void *buffer, size_t size) +/* + * Flush a locally-homecached VA range and wait for the evicted + * cachelines to hit memory. + */ +static inline void flush_buffer_local(void *buffer, size_t size) { __flush_buffer(buffer, size); mb_incoherent(); } -/* Flush & invalidate a VA range, then memory fence. */ -static inline void finv_buffer(void *buffer, size_t size) +/* + * Flush and invalidate a locally-homecached VA range and wait for the + * evicted cachelines to hit memory. + */ +static inline void finv_buffer_local(void *buffer, size_t size) { __finv_buffer(buffer, size); mb_incoherent(); diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index c3ae570c0a5..bf95f55b82b 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -215,8 +215,8 @@ struct compat_sigaction; struct compat_siginfo; struct compat_sigaltstack; long compat_sys_execve(const char __user *path, - const compat_uptr_t __user *argv, - const compat_uptr_t __user *envp, struct pt_regs *); + compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs *); long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize); diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h index 15e1dceecc6..eaa06d175b3 100644 --- a/arch/tile/include/asm/dma-mapping.h +++ b/arch/tile/include/asm/dma-mapping.h @@ -65,7 +65,8 @@ extern void dma_sync_single_range_for_cpu(struct device *, dma_addr_t, extern void dma_sync_single_range_for_device(struct device *, dma_addr_t, unsigned long offset, size_t, enum dma_data_direction); -extern void dma_cache_sync(void *vaddr, size_t, enum dma_data_direction); +extern void dma_cache_sync(struct device *dev, void *vaddr, size_t, + enum dma_data_direction); static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/tile/include/asm/fb.h b/arch/tile/include/asm/fb.h new file mode 100644 index 00000000000..3a4988e8df4 --- /dev/null +++ b/arch/tile/include/asm/fb.h @@ -0,0 +1 @@ +#include <asm-generic/fb.h> diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index d3cbb9b14cb..c9ea1652af0 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h @@ -52,6 +52,7 @@ extern void iounmap(volatile void __iomem *addr); #endif #define ioremap_nocache(physaddr, size) ioremap(physaddr, size) +#define ioremap_wc(physaddr, size) ioremap(physaddr, size) #define ioremap_writethrough(physaddr, size) ioremap(physaddr, size) #define ioremap_fullcache(physaddr, size) ioremap(physaddr, size) @@ -161,6 +162,15 @@ static inline void _tile_writeq(u64 val, unsigned long addr) #define iowrite32 writel #define iowrite64 writeq +static inline void memset_io(void *dst, int val, size_t len) +{ + int x; + BUG_ON((unsigned long)dst & 0x3); + val = (val & 0xff) * 0x01010101; + for (x = 0; x < len; x += 4) + writel(val, dst + x); +} + static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t len) { @@ -269,6 +279,11 @@ static inline void outsl(unsigned long addr, const void *buffer, int count) ioport_panic(); } +#define ioread16be(addr) be16_to_cpu(ioread16(addr)) +#define ioread32be(addr) be32_to_cpu(ioread32(addr)) +#define iowrite16be(v, addr) iowrite16(be16_to_cpu(v), (addr)) +#define iowrite32be(v, addr) iowrite32(be32_to_cpu(v), (addr)) + #define ioread8_rep(p, dst, count) \ insb((unsigned long) (p), (dst), (count)) #define ioread16_rep(p, dst, count) \ @@ -283,4 +298,7 @@ static inline void outsl(unsigned long addr, const void *buffer, int count) #define iowrite32_rep(p, src, count) \ outsl((unsigned long) (p), (src), (count)) +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt + #endif /* _ASM_TILE_IO_H */ diff --git a/arch/tile/include/asm/irq.h b/arch/tile/include/asm/irq.h index 572fd3ef1d7..94e9a511de8 100644 --- a/arch/tile/include/asm/irq.h +++ b/arch/tile/include/asm/irq.h @@ -23,6 +23,8 @@ /* IRQ numbers used for linux IPIs. */ #define IRQ_RESCHEDULE 1 +#define irq_canonicalize(irq) (irq) + void ack_bad_irq(unsigned int irq); /* diff --git a/arch/tile/include/asm/mmu_context.h b/arch/tile/include/asm/mmu_context.h index 9bc0d0725c2..15fb2464112 100644 --- a/arch/tile/include/asm/mmu_context.h +++ b/arch/tile/include/asm/mmu_context.h @@ -100,8 +100,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, __get_cpu_var(current_asid) = asid; /* Clear cpu from the old mm, and set it in the new one. */ - cpumask_clear_cpu(cpu, &prev->cpu_vm_mask); - cpumask_set_cpu(cpu, &next->cpu_vm_mask); + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + cpumask_set_cpu(cpu, mm_cpumask(next)); /* Re-load page tables */ install_page_table(next->pgd, asid); diff --git a/arch/tile/include/asm/opcode-tile_32.h b/arch/tile/include/asm/opcode-tile_32.h index eda60ecbae3..03df7b1e77b 100644 --- a/arch/tile/include/asm/opcode-tile_32.h +++ b/arch/tile/include/asm/opcode-tile_32.h @@ -1502,5 +1502,12 @@ extern int parse_insn_tile(tile_bundle_bits bits, decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]); +/* Given a set of bundle bits and a specific pipe, returns which + * instruction the bundle contains in that pipe. + */ +extern const struct tile_opcode * +find_opcode(tile_bundle_bits bits, tile_pipeline pipe); + + #endif /* opcode_tile_h */ diff --git a/arch/tile/include/asm/opcode-tile_64.h b/arch/tile/include/asm/opcode-tile_64.h index eda60ecbae3..c0633466cd5 100644 --- a/arch/tile/include/asm/opcode-tile_64.h +++ b/arch/tile/include/asm/opcode-tile_64.h @@ -5,863 +5,711 @@ #ifndef opcode_tile_h #define opcode_tile_h -typedef unsigned long long tile_bundle_bits; +typedef unsigned long long tilegx_bundle_bits; enum { - TILE_MAX_OPERANDS = 5 /* mm */ + TILEGX_MAX_OPERANDS = 4 /* bfexts */ }; typedef enum { - TILE_OPC_BPT, - TILE_OPC_INFO, - TILE_OPC_INFOL, - TILE_OPC_J, - TILE_OPC_JAL, - TILE_OPC_MOVE, - TILE_OPC_MOVE_SN, - TILE_OPC_MOVEI, - TILE_OPC_MOVEI_SN, - TILE_OPC_MOVELI, - TILE_OPC_MOVELI_SN, - TILE_OPC_MOVELIS, - TILE_OPC_PREFETCH, - TILE_OPC_RAISE, - TILE_OPC_ADD, - TILE_OPC_ADD_SN, - TILE_OPC_ADDB, - TILE_OPC_ADDB_SN, - TILE_OPC_ADDBS_U, - TILE_OPC_ADDBS_U_SN, - TILE_OPC_ADDH, - TILE_OPC_ADDH_SN, - TILE_OPC_ADDHS, - TILE_OPC_ADDHS_SN, - TILE_OPC_ADDI, - TILE_OPC_ADDI_SN, - TILE_OPC_ADDIB, - TILE_OPC_ADDIB_SN, - TILE_OPC_ADDIH, - TILE_OPC_ADDIH_SN, - TILE_OPC_ADDLI, - TILE_OPC_ADDLI_SN, - TILE_OPC_ADDLIS, - TILE_OPC_ADDS, - TILE_OPC_ADDS_SN, - TILE_OPC_ADIFFB_U, - TILE_OPC_ADIFFB_U_SN, - TILE_OPC_ADIFFH, - TILE_OPC_ADIFFH_SN, - TILE_OPC_AND, - TILE_OPC_AND_SN, - TILE_OPC_ANDI, - TILE_OPC_ANDI_SN, - TILE_OPC_AULI, - TILE_OPC_AVGB_U, - TILE_OPC_AVGB_U_SN, - TILE_OPC_AVGH, - TILE_OPC_AVGH_SN, - TILE_OPC_BBNS, - TILE_OPC_BBNS_SN, - TILE_OPC_BBNST, - TILE_OPC_BBNST_SN, - TILE_OPC_BBS, - TILE_OPC_BBS_SN, - TILE_OPC_BBST, - TILE_OPC_BBST_SN, - TILE_OPC_BGEZ, - TILE_OPC_BGEZ_SN, - TILE_OPC_BGEZT, - TILE_OPC_BGEZT_SN, - TILE_OPC_BGZ, - TILE_OPC_BGZ_SN, - TILE_OPC_BGZT, - TILE_OPC_BGZT_SN, - TILE_OPC_BITX, - TILE_OPC_BITX_SN, - TILE_OPC_BLEZ, - TILE_OPC_BLEZ_SN, - TILE_OPC_BLEZT, - TILE_OPC_BLEZT_SN, - TILE_OPC_BLZ, - TILE_OPC_BLZ_SN, - TILE_OPC_BLZT, - TILE_OPC_BLZT_SN, - TILE_OPC_BNZ, - TILE_OPC_BNZ_SN, - TILE_OPC_BNZT, - TILE_OPC_BNZT_SN, - TILE_OPC_BYTEX, - TILE_OPC_BYTEX_SN, - TILE_OPC_BZ, - TILE_OPC_BZ_SN, - TILE_OPC_BZT, - TILE_OPC_BZT_SN, - TILE_OPC_CLZ, - TILE_OPC_CLZ_SN, - TILE_OPC_CRC32_32, - TILE_OPC_CRC32_32_SN, - TILE_OPC_CRC32_8, - TILE_OPC_CRC32_8_SN, - TILE_OPC_CTZ, - TILE_OPC_CTZ_SN, - TILE_OPC_DRAIN, - TILE_OPC_DTLBPR, - TILE_OPC_DWORD_ALIGN, - TILE_OPC_DWORD_ALIGN_SN, - TILE_OPC_FINV, - TILE_OPC_FLUSH, - TILE_OPC_FNOP, - TILE_OPC_ICOH, - TILE_OPC_ILL, - TILE_OPC_INTHB, - TILE_OPC_INTHB_SN, - TILE_OPC_INTHH, - TILE_OPC_INTHH_SN, - TILE_OPC_INTLB, - TILE_OPC_INTLB_SN, - TILE_OPC_INTLH, - TILE_OPC_INTLH_SN, - TILE_OPC_INV, - TILE_OPC_IRET, - TILE_OPC_JALB, - TILE_OPC_JALF, - TILE_OPC_JALR, - TILE_OPC_JALRP, - TILE_OPC_JB, - TILE_OPC_JF, - TILE_OPC_JR, - TILE_OPC_JRP, - TILE_OPC_LB, - TILE_OPC_LB_SN, - TILE_OPC_LB_U, - TILE_OPC_LB_U_SN, - TILE_OPC_LBADD, - TILE_OPC_LBADD_SN, - TILE_OPC_LBADD_U, - TILE_OPC_LBADD_U_SN, - TILE_OPC_LH, - TILE_OPC_LH_SN, - TILE_OPC_LH_U, - TILE_OPC_LH_U_SN, - TILE_OPC_LHADD, - TILE_OPC_LHADD_SN, - TILE_OPC_LHADD_U, - TILE_OPC_LHADD_U_SN, - TILE_OPC_LNK, - TILE_OPC_LNK_SN, - TILE_OPC_LW, - TILE_OPC_LW_SN, - TILE_OPC_LW_NA, - TILE_OPC_LW_NA_SN, - TILE_OPC_LWADD, - TILE_OPC_LWADD_SN, - TILE_OPC_LWADD_NA, - TILE_OPC_LWADD_NA_SN, - TILE_OPC_MAXB_U, - TILE_OPC_MAXB_U_SN, - TILE_OPC_MAXH, - TILE_OPC_MAXH_SN, - TILE_OPC_MAXIB_U, - TILE_OPC_MAXIB_U_SN, - TILE_OPC_MAXIH, - TILE_OPC_MAXIH_SN, - TILE_OPC_MF, - TILE_OPC_MFSPR, - TILE_OPC_MINB_U, - TILE_OPC_MINB_U_SN, - TILE_OPC_MINH, - TILE_OPC_MINH_SN, - TILE_OPC_MINIB_U, - TILE_OPC_MINIB_U_SN, - TILE_OPC_MINIH, - TILE_OPC_MINIH_SN, - TILE_OPC_MM, - TILE_OPC_MNZ, - TILE_OPC_MNZ_SN, - TILE_OPC_MNZB, - TILE_OPC_MNZB_SN, - TILE_OPC_MNZH, - TILE_OPC_MNZH_SN, - TILE_OPC_MTSPR, - TILE_OPC_MULHH_SS, - TILE_OPC_MULHH_SS_SN, - TILE_OPC_MULHH_SU, - TILE_OPC_MULHH_SU_SN, - TILE_OPC_MULHH_UU, - TILE_OPC_MULHH_UU_SN, - TILE_OPC_MULHHA_SS, - TILE_OPC_MULHHA_SS_SN, - TILE_OPC_MULHHA_SU, - TILE_OPC_MULHHA_SU_SN, - TILE_OPC_MULHHA_UU, - TILE_OPC_MULHHA_UU_SN, - TILE_OPC_MULHHSA_UU, - TILE_OPC_MULHHSA_UU_SN, - TILE_OPC_MULHL_SS, - TILE_OPC_MULHL_SS_SN, - TILE_OPC_MULHL_SU, - TILE_OPC_MULHL_SU_SN, - TILE_OPC_MULHL_US, - TILE_OPC_MULHL_US_SN, - TILE_OPC_MULHL_UU, - TILE_OPC_MULHL_UU_SN, - TILE_OPC_MULHLA_SS, - TILE_OPC_MULHLA_SS_SN, - TILE_OPC_MULHLA_SU, - TILE_OPC_MULHLA_SU_SN, - TILE_OPC_MULHLA_US, - TILE_OPC_MULHLA_US_SN, - TILE_OPC_MULHLA_UU, - TILE_OPC_MULHLA_UU_SN, - TILE_OPC_MULHLSA_UU, - TILE_OPC_MULHLSA_UU_SN, - TILE_OPC_MULLL_SS, - TILE_OPC_MULLL_SS_SN, - TILE_OPC_MULLL_SU, - TILE_OPC_MULLL_SU_SN, - TILE_OPC_MULLL_UU, - TILE_OPC_MULLL_UU_SN, - TILE_OPC_MULLLA_SS, - TILE_OPC_MULLLA_SS_SN, - TILE_OPC_MULLLA_SU, - TILE_OPC_MULLLA_SU_SN, - TILE_OPC_MULLLA_UU, - TILE_OPC_MULLLA_UU_SN, - TILE_OPC_MULLLSA_UU, - TILE_OPC_MULLLSA_UU_SN, - TILE_OPC_MVNZ, - TILE_OPC_MVNZ_SN, - TILE_OPC_MVZ, - TILE_OPC_MVZ_SN, - TILE_OPC_MZ, - TILE_OPC_MZ_SN, - TILE_OPC_MZB, - TILE_OPC_MZB_SN, - TILE_OPC_MZH, - TILE_OPC_MZH_SN, - TILE_OPC_NAP, - TILE_OPC_NOP, - TILE_OPC_NOR, - TILE_OPC_NOR_SN, - TILE_OPC_OR, - TILE_OPC_OR_SN, - TILE_OPC_ORI, - TILE_OPC_ORI_SN, - TILE_OPC_PACKBS_U, - TILE_OPC_PACKBS_U_SN, - TILE_OPC_PACKHB, - TILE_OPC_PACKHB_SN, - TILE_OPC_PACKHS, - TILE_OPC_PACKHS_SN, - TILE_OPC_PACKLB, - TILE_OPC_PACKLB_SN, - TILE_OPC_PCNT, - TILE_OPC_PCNT_SN, - TILE_OPC_RL, - TILE_OPC_RL_SN, - TILE_OPC_RLI, - TILE_OPC_RLI_SN, - TILE_OPC_S1A, - TILE_OPC_S1A_SN, - TILE_OPC_S2A, - TILE_OPC_S2A_SN, - TILE_OPC_S3A, - TILE_OPC_S3A_SN, - TILE_OPC_SADAB_U, - TILE_OPC_SADAB_U_SN, - TILE_OPC_SADAH, - TILE_OPC_SADAH_SN, - TILE_OPC_SADAH_U, - TILE_OPC_SADAH_U_SN, - TILE_OPC_SADB_U, - TILE_OPC_SADB_U_SN, - TILE_OPC_SADH, - TILE_OPC_SADH_SN, - TILE_OPC_SADH_U, - TILE_OPC_SADH_U_SN, - TILE_OPC_SB, - TILE_OPC_SBADD, - TILE_OPC_SEQ, - TILE_OPC_SEQ_SN, - TILE_OPC_SEQB, - TILE_OPC_SEQB_SN, - TILE_OPC_SEQH, - TILE_OPC_SEQH_SN, - TILE_OPC_SEQI, - TILE_OPC_SEQI_SN, - TILE_OPC_SEQIB, - TILE_OPC_SEQIB_SN, - TILE_OPC_SEQIH, - TILE_OPC_SEQIH_SN, - TILE_OPC_SH, - TILE_OPC_SHADD, - TILE_OPC_SHL, - TILE_OPC_SHL_SN, - TILE_OPC_SHLB, - TILE_OPC_SHLB_SN, - TILE_OPC_SHLH, - TILE_OPC_SHLH_SN, - TILE_OPC_SHLI, - TILE_OPC_SHLI_SN, - TILE_OPC_SHLIB, - TILE_OPC_SHLIB_SN, - TILE_OPC_SHLIH, - TILE_OPC_SHLIH_SN, - TILE_OPC_SHR, - TILE_OPC_SHR_SN, - TILE_OPC_SHRB, - TILE_OPC_SHRB_SN, - TILE_OPC_SHRH, - TILE_OPC_SHRH_SN, - TILE_OPC_SHRI, - TILE_OPC_SHRI_SN, - TILE_OPC_SHRIB, - TILE_OPC_SHRIB_SN, - TILE_OPC_SHRIH, - TILE_OPC_SHRIH_SN, - TILE_OPC_SLT, - TILE_OPC_SLT_SN, - TILE_OPC_SLT_U, - TILE_OPC_SLT_U_SN, - TILE_OPC_SLTB, - TILE_OPC_SLTB_SN, - TILE_OPC_SLTB_U, - TILE_OPC_SLTB_U_SN, - TILE_OPC_SLTE, - TILE_OPC_SLTE_SN, - TILE_OPC_SLTE_U, - TILE_OPC_SLTE_U_SN, - TILE_OPC_SLTEB, - TILE_OPC_SLTEB_SN, - TILE_OPC_SLTEB_U, - TILE_OPC_SLTEB_U_SN, - TILE_OPC_SLTEH, - TILE_OPC_SLTEH_SN, - TILE_OPC_SLTEH_U, - TILE_OPC_SLTEH_U_SN, - TILE_OPC_SLTH, - TILE_OPC_SLTH_SN, - TILE_OPC_SLTH_U, - TILE_OPC_SLTH_U_SN, - TILE_OPC_SLTI, - TILE_OPC_SLTI_SN, - TILE_OPC_SLTI_U, - TILE_OPC_SLTI_U_SN, - TILE_OPC_SLTIB, - TILE_OPC_SLTIB_SN, - TILE_OPC_SLTIB_U, - TILE_OPC_SLTIB_U_SN, - TILE_OPC_SLTIH, - TILE_OPC_SLTIH_SN, - TILE_OPC_SLTIH_U, - TILE_OPC_SLTIH_U_SN, - TILE_OPC_SNE, - TILE_OPC_SNE_SN, - TILE_OPC_SNEB, - TILE_OPC_SNEB_SN, - TILE_OPC_SNEH, - TILE_OPC_SNEH_SN, - TILE_OPC_SRA, - TILE_OPC_SRA_SN, - TILE_OPC_SRAB, - TILE_OPC_SRAB_SN, - TILE_OPC_SRAH, - TILE_OPC_SRAH_SN, - TILE_OPC_SRAI, - TILE_OPC_SRAI_SN, - TILE_OPC_SRAIB, - TILE_OPC_SRAIB_SN, - TILE_OPC_SRAIH, - TILE_OPC_SRAIH_SN, - TILE_OPC_SUB, - TILE_OPC_SUB_SN, - TILE_OPC_SUBB, - TILE_OPC_SUBB_SN, - TILE_OPC_SUBBS_U, - TILE_OPC_SUBBS_U_SN, - TILE_OPC_SUBH, - TILE_OPC_SUBH_SN, - TILE_OPC_SUBHS, - TILE_OPC_SUBHS_SN, - TILE_OPC_SUBS, - TILE_OPC_SUBS_SN, - TILE_OPC_SW, - TILE_OPC_SWADD, - TILE_OPC_SWINT0, - TILE_OPC_SWINT1, - TILE_OPC_SWINT2, - TILE_OPC_SWINT3, - TILE_OPC_TBLIDXB0, - TILE_OPC_TBLIDXB0_SN, - TILE_OPC_TBLIDXB1, - TILE_OPC_TBLIDXB1_SN, - TILE_OPC_TBLIDXB2, - TILE_OPC_TBLIDXB2_SN, - TILE_OPC_TBLIDXB3, - TILE_OPC_TBLIDXB3_SN, - TILE_OPC_TNS, - TILE_OPC_TNS_SN, - TILE_OPC_WH64, - TILE_OPC_XOR, - TILE_OPC_XOR_SN, - TILE_OPC_XORI, - TILE_OPC_XORI_SN, - TILE_OPC_NONE -} tile_mnemonic; + TILEGX_OPC_BPT, + TILEGX_OPC_INFO, + TILEGX_OPC_INFOL, + TILEGX_OPC_MOVE, + TILEGX_OPC_MOVEI, + TILEGX_OPC_MOVELI, + TILEGX_OPC_PREFETCH, + TILEGX_OPC_PREFETCH_ADD_L1, + TILEGX_OPC_PREFETCH_ADD_L1_FAULT, + TILEGX_OPC_PREFETCH_ADD_L2, + TILEGX_OPC_PREFETCH_ADD_L2_FAULT, + TILEGX_OPC_PREFETCH_ADD_L3, + TILEGX_OPC_PREFETCH_ADD_L3_FAULT, + TILEGX_OPC_PREFETCH_L1, + TILEGX_OPC_PREFETCH_L1_FAULT, + TILEGX_OPC_PREFETCH_L2, + TILEGX_OPC_PREFETCH_L2_FAULT, + TILEGX_OPC_PREFETCH_L3, + TILEGX_OPC_PREFETCH_L3_FAULT, + TILEGX_OPC_RAISE, + TILEGX_OPC_ADD, + TILEGX_OPC_ADDI, + TILEGX_OPC_ADDLI, + TILEGX_OPC_ADDX, + TILEGX_OPC_ADDXI, + TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXSC, + TILEGX_OPC_AND, + TILEGX_OPC_ANDI, + TILEGX_OPC_BEQZ, + TILEGX_OPC_BEQZT, + TILEGX_OPC_BFEXTS, + TILEGX_OPC_BFEXTU, + TILEGX_OPC_BFINS, + TILEGX_OPC_BGEZ, + TILEGX_OPC_BGEZT, + TILEGX_OPC_BGTZ, + TILEGX_OPC_BGTZT, + TILEGX_OPC_BLBC, + TILEGX_OPC_BLBCT, + TILEGX_OPC_BLBS, + TILEGX_OPC_BLBST, + TILEGX_OPC_BLEZ, + TILEGX_OPC_BLEZT, + TILEGX_OPC_BLTZ, + TILEGX_OPC_BLTZT, + TILEGX_OPC_BNEZ, + TILEGX_OPC_BNEZT, + TILEGX_OPC_CLZ, + TILEGX_OPC_CMOVEQZ, + TILEGX_OPC_CMOVNEZ, + TILEGX_OPC_CMPEQ, + TILEGX_OPC_CMPEQI, + TILEGX_OPC_CMPEXCH, + TILEGX_OPC_CMPEXCH4, + TILEGX_OPC_CMPLES, + TILEGX_OPC_CMPLEU, + TILEGX_OPC_CMPLTS, + TILEGX_OPC_CMPLTSI, + TILEGX_OPC_CMPLTU, + TILEGX_OPC_CMPLTUI, + TILEGX_OPC_CMPNE, + TILEGX_OPC_CMUL, + TILEGX_OPC_CMULA, + TILEGX_OPC_CMULAF, + TILEGX_OPC_CMULF, + TILEGX_OPC_CMULFR, + TILEGX_OPC_CMULH, + TILEGX_OPC_CMULHR, + TILEGX_OPC_CRC32_32, + TILEGX_OPC_CRC32_8, + TILEGX_OPC_CTZ, + TILEGX_OPC_DBLALIGN, + TILEGX_OPC_DBLALIGN2, + TILEGX_OPC_DBLALIGN4, + TILEGX_OPC_DBLALIGN6, + TILEGX_OPC_DRAIN, + TILEGX_OPC_DTLBPR, + TILEGX_OPC_EXCH, + TILEGX_OPC_EXCH4, + TILEGX_OPC_FDOUBLE_ADD_FLAGS, + TILEGX_OPC_FDOUBLE_ADDSUB, + TILEGX_OPC_FDOUBLE_MUL_FLAGS, + TILEGX_OPC_FDOUBLE_PACK1, + TILEGX_OPC_FDOUBLE_PACK2, + TILEGX_OPC_FDOUBLE_SUB_FLAGS, + TILEGX_OPC_FDOUBLE_UNPACK_MAX, + TILEGX_OPC_FDOUBLE_UNPACK_MIN, + TILEGX_OPC_FETCHADD, + TILEGX_OPC_FETCHADD4, + TILEGX_OPC_FETCHADDGEZ, + TILEGX_OPC_FETCHADDGEZ4, + TILEGX_OPC_FETCHAND, + TILEGX_OPC_FETCHAND4, + TILEGX_OPC_FETCHOR, + TILEGX_OPC_FETCHOR4, + TILEGX_OPC_FINV, + TILEGX_OPC_FLUSH, + TILEGX_OPC_FLUSHWB, + TILEGX_OPC_FNOP, + TILEGX_OPC_FSINGLE_ADD1, + TILEGX_OPC_FSINGLE_ADDSUB2, + TILEGX_OPC_FSINGLE_MUL1, + TILEGX_OPC_FSINGLE_MUL2, + TILEGX_OPC_FSINGLE_PACK1, + TILEGX_OPC_FSINGLE_PACK2, + TILEGX_OPC_FSINGLE_SUB1, + TILEGX_OPC_ICOH, + TILEGX_OPC_ILL, + TILEGX_OPC_INV, + TILEGX_OPC_IRET, + TILEGX_OPC_J, + TILEGX_OPC_JAL, + TILEGX_OPC_JALR, + TILEGX_OPC_JALRP, + TILEGX_OPC_JR, + TILEGX_OPC_JRP, + TILEGX_OPC_LD, + TILEGX_OPC_LD1S, + TILEGX_OPC_LD1S_ADD, + TILEGX_OPC_LD1U, + TILEGX_OPC_LD1U_ADD, + TILEGX_OPC_LD2S, + TILEGX_OPC_LD2S_ADD, + TILEGX_OPC_LD2U, + TILEGX_OPC_LD2U_ADD, + TILEGX_OPC_LD4S, + TILEGX_OPC_LD4S_ADD, + TILEGX_OPC_LD4U, + TILEGX_OPC_LD4U_ADD, + TILEGX_OPC_LD_ADD, + TILEGX_OPC_LDNA, + TILEGX_OPC_LDNA_ADD, + TILEGX_OPC_LDNT, + TILEGX_OPC_LDNT1S, + TILEGX_OPC_LDNT1S_ADD, + TILEGX_OPC_LDNT1U, + TILEGX_OPC_LDNT1U_ADD, + TILEGX_OPC_LDNT2S, + TILEGX_OPC_LDNT2S_ADD, + TILEGX_OPC_LDNT2U, + TILEGX_OPC_LDNT2U_ADD, + TILEGX_OPC_LDNT4S, + TILEGX_OPC_LDNT4S_ADD, + TILEGX_OPC_LDNT4U, + TILEGX_OPC_LDNT4U_ADD, + TILEGX_OPC_LDNT_ADD, + TILEGX_OPC_LNK, + TILEGX_OPC_MF, + TILEGX_OPC_MFSPR, + TILEGX_OPC_MM, + TILEGX_OPC_MNZ, + TILEGX_OPC_MTSPR, + TILEGX_OPC_MUL_HS_HS, + TILEGX_OPC_MUL_HS_HU, + TILEGX_OPC_MUL_HS_LS, + TILEGX_OPC_MUL_HS_LU, + TILEGX_OPC_MUL_HU_HU, + TILEGX_OPC_MUL_HU_LS, + TILEGX_OPC_MUL_HU_LU, + TILEGX_OPC_MUL_LS_LS, + TILEGX_OPC_MUL_LS_LU, + TILEGX_OPC_MUL_LU_LU, + TILEGX_OPC_MULA_HS_HS, + TILEGX_OPC_MULA_HS_HU, + TILEGX_OPC_MULA_HS_LS, + TILEGX_OPC_MULA_HS_LU, + TILEGX_OPC_MULA_HU_HU, + TILEGX_OPC_MULA_HU_LS, + TILEGX_OPC_MULA_HU_LU, + TILEGX_OPC_MULA_LS_LS, + TILEGX_OPC_MULA_LS_LU, + TILEGX_OPC_MULA_LU_LU, + TILEGX_OPC_MULAX, + TILEGX_OPC_MULX, + TILEGX_OPC_MZ, + TILEGX_OPC_NAP, + TILEGX_OPC_NOP, + TILEGX_OPC_NOR, + TILEGX_OPC_OR, + TILEGX_OPC_ORI, + TILEGX_OPC_PCNT, + TILEGX_OPC_REVBITS, + TILEGX_OPC_REVBYTES, + TILEGX_OPC_ROTL, + TILEGX_OPC_ROTLI, + TILEGX_OPC_SHL, + TILEGX_OPC_SHL16INSLI, + TILEGX_OPC_SHL1ADD, + TILEGX_OPC_SHL1ADDX, + TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL2ADDX, + TILEGX_OPC_SHL3ADD, + TILEGX_OPC_SHL3ADDX, + TILEGX_OPC_SHLI, + TILEGX_OPC_SHLX, + TILEGX_OPC_SHLXI, + TILEGX_OPC_SHRS, + TILEGX_OPC_SHRSI, + TILEGX_OPC_SHRU, + TILEGX_OPC_SHRUI, + TILEGX_OPC_SHRUX, + TILEGX_OPC_SHRUXI, + TILEGX_OPC_SHUFFLEBYTES, + TILEGX_OPC_ST, + TILEGX_OPC_ST1, + TILEGX_OPC_ST1_ADD, + TILEGX_OPC_ST2, + TILEGX_OPC_ST2_ADD, + TILEGX_OPC_ST4, + TILEGX_OPC_ST4_ADD, + TILEGX_OPC_ST_ADD, + TILEGX_OPC_STNT, + TILEGX_OPC_STNT1, + TILEGX_OPC_STNT1_ADD, + TILEGX_OPC_STNT2, + TILEGX_OPC_STNT2_ADD, + TILEGX_OPC_STNT4, + TILEGX_OPC_STNT4_ADD, + TILEGX_OPC_STNT_ADD, + TILEGX_OPC_SUB, + TILEGX_OPC_SUBX, + TILEGX_OPC_SUBXSC, + TILEGX_OPC_SWINT0, + TILEGX_OPC_SWINT1, + TILEGX_OPC_SWINT2, + TILEGX_OPC_SWINT3, + TILEGX_OPC_TBLIDXB0, + TILEGX_OPC_TBLIDXB1, + TILEGX_OPC_TBLIDXB2, + TILEGX_OPC_TBLIDXB3, + TILEGX_OPC_V1ADD, + TILEGX_OPC_V1ADDI, + TILEGX_OPC_V1ADDUC, + TILEGX_OPC_V1ADIFFU, + TILEGX_OPC_V1AVGU, + TILEGX_OPC_V1CMPEQ, + TILEGX_OPC_V1CMPEQI, + TILEGX_OPC_V1CMPLES, + TILEGX_OPC_V1CMPLEU, + TILEGX_OPC_V1CMPLTS, + TILEGX_OPC_V1CMPLTSI, + TILEGX_OPC_V1CMPLTU, + TILEGX_OPC_V1CMPLTUI, + TILEGX_OPC_V1CMPNE, + TILEGX_OPC_V1DDOTPU, + TILEGX_OPC_V1DDOTPUA, + TILEGX_OPC_V1DDOTPUS, + TILEGX_OPC_V1DDOTPUSA, + TILEGX_OPC_V1DOTP, + TILEGX_OPC_V1DOTPA, + TILEGX_OPC_V1DOTPU, + TILEGX_OPC_V1DOTPUA, + TILEGX_OPC_V1DOTPUS, + TILEGX_OPC_V1DOTPUSA, + TILEGX_OPC_V1INT_H, + TILEGX_OPC_V1INT_L, + TILEGX_OPC_V1MAXU, + TILEGX_OPC_V1MAXUI, + TILEGX_OPC_V1MINU, + TILEGX_OPC_V1MINUI, + TILEGX_OPC_V1MNZ, + TILEGX_OPC_V1MULTU, + TILEGX_OPC_V1MULU, + TILEGX_OPC_V1MULUS, + TILEGX_OPC_V1MZ, + TILEGX_OPC_V1SADAU, + TILEGX_OPC_V1SADU, + TILEGX_OPC_V1SHL, + TILEGX_OPC_V1SHLI, + TILEGX_OPC_V1SHRS, + TILEGX_OPC_V1SHRSI, + TILEGX_OPC_V1SHRU, + TILEGX_OPC_V1SHRUI, + TILEGX_OPC_V1SUB, + TILEGX_OPC_V1SUBUC, + TILEGX_OPC_V2ADD, + TILEGX_OPC_V2ADDI, + TILEGX_OPC_V2ADDSC, + TILEGX_OPC_V2ADIFFS, + TILEGX_OPC_V2AVGS, + TILEGX_OPC_V2CMPEQ, + TILEGX_OPC_V2CMPEQI, + TILEGX_OPC_V2CMPLES, + TILEGX_OPC_V2CMPLEU, + TILEGX_OPC_V2CMPLTS, + TILEGX_OPC_V2CMPLTSI, + TILEGX_OPC_V2CMPLTU, + TILEGX_OPC_V2CMPLTUI, + TILEGX_OPC_V2CMPNE, + TILEGX_OPC_V2DOTP, + TILEGX_OPC_V2DOTPA, + TILEGX_OPC_V2INT_H, + TILEGX_OPC_V2INT_L, + TILEGX_OPC_V2MAXS, + TILEGX_OPC_V2MAXSI, + TILEGX_OPC_V2MINS, + TILEGX_OPC_V2MINSI, + TILEGX_OPC_V2MNZ, + TILEGX_OPC_V2MULFSC, + TILEGX_OPC_V2MULS, + TILEGX_OPC_V2MULTS, + TILEGX_OPC_V2MZ, + TILEGX_OPC_V2PACKH, + TILEGX_OPC_V2PACKL, + TILEGX_OPC_V2PACKUC, + TILEGX_OPC_V2SADAS, + TILEGX_OPC_V2SADAU, + TILEGX_OPC_V2SADS, + TILEGX_OPC_V2SADU, + TILEGX_OPC_V2SHL, + TILEGX_OPC_V2SHLI, + TILEGX_OPC_V2SHLSC, + TILEGX_OPC_V2SHRS, + TILEGX_OPC_V2SHRSI, + TILEGX_OPC_V2SHRU, + TILEGX_OPC_V2SHRUI, + TILEGX_OPC_V2SUB, + TILEGX_OPC_V2SUBSC, + TILEGX_OPC_V4ADD, + TILEGX_OPC_V4ADDSC, + TILEGX_OPC_V4INT_H, + TILEGX_OPC_V4INT_L, + TILEGX_OPC_V4PACKSC, + TILEGX_OPC_V4SHL, + TILEGX_OPC_V4SHLSC, + TILEGX_OPC_V4SHRS, + TILEGX_OPC_V4SHRU, + TILEGX_OPC_V4SUB, + TILEGX_OPC_V4SUBSC, + TILEGX_OPC_WH64, + TILEGX_OPC_XOR, + TILEGX_OPC_XORI, + TILEGX_OPC_NONE +} tilegx_mnemonic; /* 64-bit pattern for a { bpt ; nop } bundle. */ -#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL +#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL -#define TILE_ELF_MACHINE_CODE EM_TILEPRO +#define TILE_ELF_MACHINE_CODE EM_TILE64 -#define TILE_ELF_NAME "elf32-tilepro" +#define TILE_ELF_NAME "elf32-tile64" static __inline unsigned int -get_BrOff_SN(tile_bundle_bits num) +get_BFEnd_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0x3ff); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_BrOff_X1(tile_bundle_bits n) +get_BFOpcodeExtension_X0(tilegx_bundle_bits num) { - return (((unsigned int)(n >> 43)) & 0x00007fff) | - (((unsigned int)(n >> 20)) & 0x00018000); + const unsigned int n = (unsigned int)num; + return (((n >> 24)) & 0xf); } static __inline unsigned int -get_BrType_X1(tile_bundle_bits n) +get_BFStart_X0(tilegx_bundle_bits num) { - return (((unsigned int)(n >> 31)) & 0xf); + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x3f); } static __inline unsigned int -get_Dest_Imm8_X1(tile_bundle_bits n) +get_BrOff_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x0000003f) | - (((unsigned int)(n >> 43)) & 0x000000c0); + (((unsigned int)(n >> 37)) & 0x0001ffc0); } static __inline unsigned int -get_Dest_SN(tile_bundle_bits num) +get_BrType_X1(tilegx_bundle_bits n) { - const unsigned int n = (unsigned int)num; - return (((n >> 2)) & 0x3); + return (((unsigned int)(n >> 54)) & 0x1f); } static __inline unsigned int -get_Dest_X0(tile_bundle_bits num) +get_Dest_Imm8_X1(tilegx_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x0000003f) | + (((unsigned int)(n >> 43)) & 0x000000c0); +} + +static __inline unsigned int +get_Dest_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 0)) & 0x3f); } static __inline unsigned int -get_Dest_X1(tile_bundle_bits n) +get_Dest_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x3f); } static __inline unsigned int -get_Dest_Y0(tile_bundle_bits num) +get_Dest_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 0)) & 0x3f); } static __inline unsigned int -get_Dest_Y1(tile_bundle_bits n) +get_Dest_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x3f); } static __inline unsigned int -get_Imm16_X0(tile_bundle_bits num) +get_Imm16_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0xffff); } static __inline unsigned int -get_Imm16_X1(tile_bundle_bits n) +get_Imm16_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0xffff); } static __inline unsigned int -get_Imm8_SN(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0xff); -} - -static __inline unsigned int -get_Imm8_X0(tile_bundle_bits num) +get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0xff); + return (((n >> 20)) & 0xff); } static __inline unsigned int -get_Imm8_X1(tile_bundle_bits n) +get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 43)) & 0xff); + return (((unsigned int)(n >> 51)) & 0xff); } static __inline unsigned int -get_Imm8_Y0(tile_bundle_bits num) +get_Imm8_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0xff); } static __inline unsigned int -get_Imm8_Y1(tile_bundle_bits n) +get_Imm8_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0xff); } static __inline unsigned int -get_ImmOpcodeExtension_X0(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 20)) & 0x7f); -} - -static __inline unsigned int -get_ImmOpcodeExtension_X1(tile_bundle_bits n) -{ - return (((unsigned int)(n >> 51)) & 0x7f); -} - -static __inline unsigned int -get_ImmRROpcodeExtension_SN(tile_bundle_bits num) +get_Imm8_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 8)) & 0x3); -} - -static __inline unsigned int -get_JOffLong_X1(tile_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x00007fff) | - (((unsigned int)(n >> 20)) & 0x00018000) | - (((unsigned int)(n >> 14)) & 0x001e0000) | - (((unsigned int)(n >> 16)) & 0x07e00000) | - (((unsigned int)(n >> 31)) & 0x18000000); -} - -static __inline unsigned int -get_JOff_X1(tile_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x00007fff) | - (((unsigned int)(n >> 20)) & 0x00018000) | - (((unsigned int)(n >> 14)) & 0x001e0000) | - (((unsigned int)(n >> 16)) & 0x07e00000) | - (((unsigned int)(n >> 31)) & 0x08000000); -} - -static __inline unsigned int -get_MF_Imm15_X1(tile_bundle_bits n) -{ - return (((unsigned int)(n >> 37)) & 0x00003fff) | - (((unsigned int)(n >> 44)) & 0x00004000); + return (((n >> 12)) & 0xff); } static __inline unsigned int -get_MMEnd_X0(tile_bundle_bits num) +get_Imm8_Y1(tilegx_bundle_bits n) { - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x1f); + return (((unsigned int)(n >> 43)) & 0xff); } static __inline unsigned int -get_MMEnd_X1(tile_bundle_bits n) +get_JumpOff_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 49)) & 0x1f); + return (((unsigned int)(n >> 31)) & 0x7ffffff); } static __inline unsigned int -get_MMStart_X0(tile_bundle_bits num) +get_JumpOpcodeExtension_X1(tilegx_bundle_bits n) { - const unsigned int n = (unsigned int)num; - return (((n >> 23)) & 0x1f); + return (((unsigned int)(n >> 58)) & 0x1); } static __inline unsigned int -get_MMStart_X1(tile_bundle_bits n) +get_MF_Imm14_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 54)) & 0x1f); + return (((unsigned int)(n >> 37)) & 0x3fff); } static __inline unsigned int -get_MT_Imm15_X1(tile_bundle_bits n) +get_MT_Imm14_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x0000003f) | - (((unsigned int)(n >> 37)) & 0x00003fc0) | - (((unsigned int)(n >> 44)) & 0x00004000); + (((unsigned int)(n >> 37)) & 0x00003fc0); } static __inline unsigned int -get_Mode(tile_bundle_bits n) +get_Mode(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 63)) & 0x1); + return (((unsigned int)(n >> 62)) & 0x3); } static __inline unsigned int -get_NoRegOpcodeExtension_SN(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0xf); -} - -static __inline unsigned int -get_Opcode_SN(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 10)) & 0x3f); -} - -static __inline unsigned int -get_Opcode_X0(tile_bundle_bits num) +get_Opcode_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 28)) & 0x7); } static __inline unsigned int -get_Opcode_X1(tile_bundle_bits n) +get_Opcode_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 59)) & 0xf); + return (((unsigned int)(n >> 59)) & 0x7); } static __inline unsigned int -get_Opcode_Y0(tile_bundle_bits num) +get_Opcode_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 27)) & 0xf); } static __inline unsigned int -get_Opcode_Y1(tile_bundle_bits n) +get_Opcode_Y1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 59)) & 0xf); + return (((unsigned int)(n >> 58)) & 0xf); } static __inline unsigned int -get_Opcode_Y2(tile_bundle_bits n) +get_Opcode_Y2(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 56)) & 0x7); -} - -static __inline unsigned int -get_RROpcodeExtension_SN(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 4)) & 0xf); + return (((n >> 26)) & 0x00000001) | + (((unsigned int)(n >> 56)) & 0x00000002); } static __inline unsigned int -get_RRROpcodeExtension_X0(tile_bundle_bits num) +get_RRROpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x1ff); + return (((n >> 18)) & 0x3ff); } static __inline unsigned int -get_RRROpcodeExtension_X1(tile_bundle_bits n) +get_RRROpcodeExtension_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 49)) & 0x1ff); + return (((unsigned int)(n >> 49)) & 0x3ff); } static __inline unsigned int -get_RRROpcodeExtension_Y0(tile_bundle_bits num) +get_RRROpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3); } static __inline unsigned int -get_RRROpcodeExtension_Y1(tile_bundle_bits n) +get_RRROpcodeExtension_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 49)) & 0x3); } static __inline unsigned int -get_RouteOpcodeExtension_SN(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0x3ff); -} - -static __inline unsigned int -get_S_X0(tile_bundle_bits num) +get_ShAmt_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 27)) & 0x1); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_S_X1(tile_bundle_bits n) +get_ShAmt_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 58)) & 0x1); + return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int -get_ShAmt_X0(tile_bundle_bits num) +get_ShAmt_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x1f); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_ShAmt_X1(tile_bundle_bits n) +get_ShAmt_Y1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 43)) & 0x1f); + return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int -get_ShAmt_Y0(tile_bundle_bits num) +get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x1f); + return (((n >> 18)) & 0x3ff); } static __inline unsigned int -get_ShAmt_Y1(tile_bundle_bits n) +get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 43)) & 0x1f); + return (((unsigned int)(n >> 49)) & 0x3ff); } static __inline unsigned int -get_SrcA_X0(tile_bundle_bits num) +get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 6)) & 0x3f); + return (((n >> 18)) & 0x3); } static __inline unsigned int -get_SrcA_X1(tile_bundle_bits n) +get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 37)) & 0x3f); + return (((unsigned int)(n >> 49)) & 0x3); } static __inline unsigned int -get_SrcA_Y0(tile_bundle_bits num) +get_SrcA_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 6)) & 0x3f); } static __inline unsigned int -get_SrcA_Y1(tile_bundle_bits n) +get_SrcA_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 37)) & 0x3f); } static __inline unsigned int -get_SrcA_Y2(tile_bundle_bits n) +get_SrcA_Y0(tilegx_bundle_bits num) { - return (((n >> 26)) & 0x00000001) | - (((unsigned int)(n >> 50)) & 0x0000003e); + const unsigned int n = (unsigned int)num; + return (((n >> 6)) & 0x3f); } static __inline unsigned int -get_SrcBDest_Y2(tile_bundle_bits num) +get_SrcA_Y1(tilegx_bundle_bits n) { - const unsigned int n = (unsigned int)num; - return (((n >> 20)) & 0x3f); + return (((unsigned int)(n >> 37)) & 0x3f); } static __inline unsigned int -get_SrcB_X0(tile_bundle_bits num) +get_SrcA_Y2(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); + return (((n >> 20)) & 0x3f); } static __inline unsigned int -get_SrcB_X1(tile_bundle_bits n) +get_SrcBDest_Y2(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 43)) & 0x3f); + return (((unsigned int)(n >> 51)) & 0x3f); } static __inline unsigned int -get_SrcB_Y0(tile_bundle_bits num) +get_SrcB_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_SrcB_Y1(tile_bundle_bits n) +get_SrcB_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int -get_Src_SN(tile_bundle_bits num) +get_SrcB_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0x3); -} - -static __inline unsigned int -get_UnOpcodeExtension_X0(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x1f); -} - -static __inline unsigned int -get_UnOpcodeExtension_X1(tile_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x1f); -} - -static __inline unsigned int -get_UnOpcodeExtension_Y0(tile_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x1f); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_UnOpcodeExtension_Y1(tile_bundle_bits n) +get_SrcB_Y1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 43)) & 0x1f); + return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int -get_UnShOpcodeExtension_X0(tile_bundle_bits num) +get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 17)) & 0x3ff); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_UnShOpcodeExtension_X1(tile_bundle_bits n) +get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 48)) & 0x3ff); + return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int -get_UnShOpcodeExtension_Y0(tile_bundle_bits num) +get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; - return (((n >> 17)) & 0x7); + return (((n >> 12)) & 0x3f); } static __inline unsigned int -get_UnShOpcodeExtension_Y1(tile_bundle_bits n) +get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n) { - return (((unsigned int)(n >> 48)) & 0x7); + return (((unsigned int)(n >> 43)) & 0x3f); } @@ -874,546 +722,441 @@ sign_extend(int n, int num_bits) -static __inline tile_bundle_bits -create_BrOff_SN(int num) +static __inline tilegx_bundle_bits +create_BFEnd_X0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x3ff) << 0); + return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits -create_BrOff_X1(int num) +static __inline tilegx_bundle_bits +create_BFOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | - (((tile_bundle_bits)(n & 0x00018000)) << 20); + return ((n & 0xf) << 24); } -static __inline tile_bundle_bits -create_BrType_X1(int num) +static __inline tilegx_bundle_bits +create_BFStart_X0(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xf)) << 31); + return ((n & 0x3f) << 18); } -static __inline tile_bundle_bits -create_Dest_Imm8_X1(int num) +static __inline tilegx_bundle_bits +create_BrOff_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | - (((tile_bundle_bits)(n & 0x000000c0)) << 43); + return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | + (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37); } -static __inline tile_bundle_bits -create_Dest_SN(int num) +static __inline tilegx_bundle_bits +create_BrType_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tilegx_bundle_bits)(n & 0x1f)) << 54); +} + +static __inline tilegx_bundle_bits +create_Dest_Imm8_X1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x3) << 2); + return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | + (((tilegx_bundle_bits)(n & 0x000000c0)) << 43); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Dest_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 0); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Dest_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 31); + return (((tilegx_bundle_bits)(n & 0x3f)) << 31); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Dest_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 0); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Dest_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 31); + return (((tilegx_bundle_bits)(n & 0x3f)) << 31); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Imm16_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xffff) << 12); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Imm16_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xffff)) << 43); + return (((tilegx_bundle_bits)(n & 0xffff)) << 43); } -static __inline tile_bundle_bits -create_Imm8_SN(int num) +static __inline tilegx_bundle_bits +create_Imm8OpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0xff) << 0); + return ((n & 0xff) << 20); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits +create_Imm8OpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tilegx_bundle_bits)(n & 0xff)) << 51); +} + +static __inline tilegx_bundle_bits create_Imm8_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xff) << 12); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Imm8_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xff)) << 43); + return (((tilegx_bundle_bits)(n & 0xff)) << 43); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Imm8_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xff) << 12); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Imm8_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xff)) << 43); -} - -static __inline tile_bundle_bits -create_ImmOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x7f) << 20); -} - -static __inline tile_bundle_bits -create_ImmOpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x7f)) << 51); -} - -static __inline tile_bundle_bits -create_ImmRROpcodeExtension_SN(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3) << 8); -} - -static __inline tile_bundle_bits -create_JOffLong_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | - (((tile_bundle_bits)(n & 0x00018000)) << 20) | - (((tile_bundle_bits)(n & 0x001e0000)) << 14) | - (((tile_bundle_bits)(n & 0x07e00000)) << 16) | - (((tile_bundle_bits)(n & 0x18000000)) << 31); -} - -static __inline tile_bundle_bits -create_JOff_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | - (((tile_bundle_bits)(n & 0x00018000)) << 20) | - (((tile_bundle_bits)(n & 0x001e0000)) << 14) | - (((tile_bundle_bits)(n & 0x07e00000)) << 16) | - (((tile_bundle_bits)(n & 0x08000000)) << 31); -} - -static __inline tile_bundle_bits -create_MF_Imm15_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x00003fff)) << 37) | - (((tile_bundle_bits)(n & 0x00004000)) << 44); + return (((tilegx_bundle_bits)(n & 0xff)) << 43); } -static __inline tile_bundle_bits -create_MMEnd_X0(int num) +static __inline tilegx_bundle_bits +create_JumpOff_X1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 18); + return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31); } -static __inline tile_bundle_bits -create_MMEnd_X1(int num) +static __inline tilegx_bundle_bits +create_JumpOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 49); + return (((tilegx_bundle_bits)(n & 0x1)) << 58); } -static __inline tile_bundle_bits -create_MMStart_X0(int num) +static __inline tilegx_bundle_bits +create_MF_Imm14_X1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 23); + return (((tilegx_bundle_bits)(n & 0x3fff)) << 37); } -static __inline tile_bundle_bits -create_MMStart_X1(int num) +static __inline tilegx_bundle_bits +create_MT_Imm14_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 54); + return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | + (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37); } -static __inline tile_bundle_bits -create_MT_Imm15_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | - (((tile_bundle_bits)(n & 0x00003fc0)) << 37) | - (((tile_bundle_bits)(n & 0x00004000)) << 44); -} - -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Mode(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1)) << 63); + return (((tilegx_bundle_bits)(n & 0x3)) << 62); } -static __inline tile_bundle_bits -create_NoRegOpcodeExtension_SN(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xf) << 0); -} - -static __inline tile_bundle_bits -create_Opcode_SN(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 10); -} - -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Opcode_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x7) << 28); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Opcode_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xf)) << 59); + return (((tilegx_bundle_bits)(n & 0x7)) << 59); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Opcode_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xf) << 27); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Opcode_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0xf)) << 59); + return (((tilegx_bundle_bits)(n & 0xf)) << 58); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_Opcode_Y2(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x7)) << 56); -} - -static __inline tile_bundle_bits -create_RROpcodeExtension_SN(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xf) << 4); + return ((n & 0x00000001) << 26) | + (((tilegx_bundle_bits)(n & 0x00000002)) << 56); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_RRROpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1ff) << 18); + return ((n & 0x3ff) << 18); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_RRROpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1ff)) << 49); + return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_RRROpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3) << 18); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_RRROpcodeExtension_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3)) << 49); + return (((tilegx_bundle_bits)(n & 0x3)) << 49); } -static __inline tile_bundle_bits -create_RouteOpcodeExtension_SN(int num) +static __inline tilegx_bundle_bits +create_ShAmt_X0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x3ff) << 0); + return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits -create_S_X0(int num) +static __inline tilegx_bundle_bits +create_ShAmt_X1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1) << 27); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } -static __inline tile_bundle_bits -create_S_X1(int num) +static __inline tilegx_bundle_bits +create_ShAmt_Y0(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1)) << 58); + return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits -create_ShAmt_X0(int num) +static __inline tilegx_bundle_bits +create_ShAmt_Y1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 12); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } -static __inline tile_bundle_bits -create_ShAmt_X1(int num) +static __inline tilegx_bundle_bits +create_ShiftOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 43); + return ((n & 0x3ff) << 18); } -static __inline tile_bundle_bits -create_ShAmt_Y0(int num) +static __inline tilegx_bundle_bits +create_ShiftOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 12); + return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); } -static __inline tile_bundle_bits -create_ShAmt_Y1(int num) +static __inline tilegx_bundle_bits +create_ShiftOpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 43); + return ((n & 0x3) << 18); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits +create_ShiftOpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tilegx_bundle_bits)(n & 0x3)) << 49); +} + +static __inline tilegx_bundle_bits create_SrcA_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 6); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcA_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 37); + return (((tilegx_bundle_bits)(n & 0x3f)) << 37); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcA_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 6); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcA_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 37); + return (((tilegx_bundle_bits)(n & 0x3f)) << 37); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcA_Y2(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x00000001) << 26) | - (((tile_bundle_bits)(n & 0x0000003e)) << 50); + return ((n & 0x3f) << 20); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcBDest_Y2(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 20); + return (((tilegx_bundle_bits)(n & 0x3f)) << 51); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcB_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcB_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 43); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcB_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits +static __inline tilegx_bundle_bits create_SrcB_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3f)) << 43); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } -static __inline tile_bundle_bits -create_Src_SN(int num) +static __inline tilegx_bundle_bits +create_UnaryOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x3) << 0); -} - -static __inline tile_bundle_bits -create_UnOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 12); -} - -static __inline tile_bundle_bits -create_UnOpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 43); -} - -static __inline tile_bundle_bits -create_UnOpcodeExtension_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x1f) << 12); -} - -static __inline tile_bundle_bits -create_UnOpcodeExtension_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x1f)) << 43); -} - -static __inline tile_bundle_bits -create_UnShOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3ff) << 17); + return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits -create_UnShOpcodeExtension_X1(int num) +static __inline tilegx_bundle_bits +create_UnaryOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x3ff)) << 48); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } -static __inline tile_bundle_bits -create_UnShOpcodeExtension_Y0(int num) +static __inline tilegx_bundle_bits +create_UnaryOpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; - return ((n & 0x7) << 17); + return ((n & 0x3f) << 12); } -static __inline tile_bundle_bits -create_UnShOpcodeExtension_Y1(int num) +static __inline tilegx_bundle_bits +create_UnaryOpcodeExtension_Y1(int num) { const unsigned int n = (unsigned int)num; - return (((tile_bundle_bits)(n & 0x7)) << 48); + return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } - typedef enum { - TILE_PIPELINE_X0, - TILE_PIPELINE_X1, - TILE_PIPELINE_Y0, - TILE_PIPELINE_Y1, - TILE_PIPELINE_Y2, -} tile_pipeline; + TILEGX_PIPELINE_X0, + TILEGX_PIPELINE_X1, + TILEGX_PIPELINE_Y0, + TILEGX_PIPELINE_Y1, + TILEGX_PIPELINE_Y2, +} tilegx_pipeline; -#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1) +#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1) typedef enum { - TILE_OP_TYPE_REGISTER, - TILE_OP_TYPE_IMMEDIATE, - TILE_OP_TYPE_ADDRESS, - TILE_OP_TYPE_SPR -} tile_operand_type; + TILEGX_OP_TYPE_REGISTER, + TILEGX_OP_TYPE_IMMEDIATE, + TILEGX_OP_TYPE_ADDRESS, + TILEGX_OP_TYPE_SPR +} tilegx_operand_type; -/* This is the bit that determines if a bundle is in the Y encoding. */ -#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63) +/* These are the bits that determine if a bundle is in the X encoding. */ +#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62) enum { /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */ - TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3, + TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3, /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */ - TILE_NUM_PIPELINE_ENCODINGS = 5, + TILEGX_NUM_PIPELINE_ENCODINGS = 5, - /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */ - TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3, + /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */ + TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3, /* Instructions take this many bytes. */ - TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES, + TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES, - /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */ - TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, + /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */ + TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, /* Bundles should be aligned modulo this number of bytes. */ - TILE_BUNDLE_ALIGNMENT_IN_BYTES = - (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), - - /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */ - TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1, - - /* Static network instructions take this many bytes. */ - TILE_SN_INSTRUCTION_SIZE_IN_BYTES = - (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES), + TILEGX_BUNDLE_ALIGNMENT_IN_BYTES = + (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), /* Number of registers (some are magic, such as network I/O). */ - TILE_NUM_REGISTERS = 64, - - /* Number of static network registers. */ - TILE_NUM_SN_REGISTERS = 4 + TILEGX_NUM_REGISTERS = 64, }; -struct tile_operand +struct tilegx_operand { /* Is this operand a register, immediate or address? */ - tile_operand_type type; + tilegx_operand_type type; /* The default relocation type for this operand. */ signed int default_reloc : 16; @@ -1437,27 +1180,27 @@ struct tile_operand unsigned int rightshift : 2; /* Return the bits for this operand to be ORed into an existing bundle. */ - tile_bundle_bits (*insert) (int op); + tilegx_bundle_bits (*insert) (int op); /* Extract this operand and return it. */ - unsigned int (*extract) (tile_bundle_bits bundle); + unsigned int (*extract) (tilegx_bundle_bits bundle); }; -extern const struct tile_operand tile_operands[]; +extern const struct tilegx_operand tilegx_operands[]; /* One finite-state machine per pipe for rapid instruction decoding. */ extern const unsigned short * const -tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS]; +tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS]; -struct tile_opcode +struct tilegx_opcode { /* The opcode mnemonic, e.g. "add" */ const char *name; /* The enum value for this mnemonic. */ - tile_mnemonic mnemonic; + tilegx_mnemonic mnemonic; /* A bit mask of which of the five pipes this instruction is compatible with: @@ -1478,29 +1221,28 @@ struct tile_opcode unsigned char can_bundle; /* The description of the operands. Each of these is an - * index into the tile_operands[] table. */ - unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS]; + * index into the tilegx_operands[] table. */ + unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS]; }; -extern const struct tile_opcode tile_opcodes[]; - +extern const struct tilegx_opcode tilegx_opcodes[]; /* Used for non-textual disassembly into structs. */ -struct tile_decoded_instruction +struct tilegx_decoded_instruction { - const struct tile_opcode *opcode; - const struct tile_operand *operands[TILE_MAX_OPERANDS]; - int operand_values[TILE_MAX_OPERANDS]; + const struct tilegx_opcode *opcode; + const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS]; + long long operand_values[TILEGX_MAX_OPERANDS]; }; /* Disassemble a bundle into a struct for machine processing. */ -extern int parse_insn_tile(tile_bundle_bits bits, - unsigned int pc, - struct tile_decoded_instruction - decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]); +extern int parse_insn_tilegx(tilegx_bundle_bits bits, + unsigned long long pc, + struct tilegx_decoded_instruction + decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]); -#endif /* opcode_tile_h */ +#endif /* opcode_tilegx_h */ diff --git a/arch/tile/include/asm/opcode_constants_64.h b/arch/tile/include/asm/opcode_constants_64.h index 227d033b180..71019286947 100644 --- a/arch/tile/include/asm/opcode_constants_64.h +++ b/arch/tile/include/asm/opcode_constants_64.h @@ -1,5 +1,5 @@ /* - * Copyright 2010 Tilera Corporation. All Rights Reserved. + * Copyright 2011 Tilera Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,462 +19,591 @@ #define _TILE_OPCODE_CONSTANTS_H enum { - ADDBS_U_SPECIAL_0_OPCODE_X0 = 98, - ADDBS_U_SPECIAL_0_OPCODE_X1 = 68, - ADDB_SPECIAL_0_OPCODE_X0 = 1, - ADDB_SPECIAL_0_OPCODE_X1 = 1, - ADDHS_SPECIAL_0_OPCODE_X0 = 99, - ADDHS_SPECIAL_0_OPCODE_X1 = 69, - ADDH_SPECIAL_0_OPCODE_X0 = 2, - ADDH_SPECIAL_0_OPCODE_X1 = 2, - ADDIB_IMM_0_OPCODE_X0 = 1, - ADDIB_IMM_0_OPCODE_X1 = 1, - ADDIH_IMM_0_OPCODE_X0 = 2, - ADDIH_IMM_0_OPCODE_X1 = 2, - ADDI_IMM_0_OPCODE_X0 = 3, - ADDI_IMM_0_OPCODE_X1 = 3, - ADDI_IMM_1_OPCODE_SN = 1, - ADDI_OPCODE_Y0 = 9, - ADDI_OPCODE_Y1 = 7, - ADDLIS_OPCODE_X0 = 1, - ADDLIS_OPCODE_X1 = 2, - ADDLI_OPCODE_X0 = 2, - ADDLI_OPCODE_X1 = 3, - ADDS_SPECIAL_0_OPCODE_X0 = 96, - ADDS_SPECIAL_0_OPCODE_X1 = 66, - ADD_SPECIAL_0_OPCODE_X0 = 3, - ADD_SPECIAL_0_OPCODE_X1 = 3, - ADD_SPECIAL_0_OPCODE_Y0 = 0, - ADD_SPECIAL_0_OPCODE_Y1 = 0, - ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4, - ADIFFH_SPECIAL_0_OPCODE_X0 = 5, - ANDI_IMM_0_OPCODE_X0 = 1, - ANDI_IMM_0_OPCODE_X1 = 4, - ANDI_OPCODE_Y0 = 10, - ANDI_OPCODE_Y1 = 8, - AND_SPECIAL_0_OPCODE_X0 = 6, - AND_SPECIAL_0_OPCODE_X1 = 4, - AND_SPECIAL_2_OPCODE_Y0 = 0, - AND_SPECIAL_2_OPCODE_Y1 = 0, - AULI_OPCODE_X0 = 3, - AULI_OPCODE_X1 = 4, - AVGB_U_SPECIAL_0_OPCODE_X0 = 7, - AVGH_SPECIAL_0_OPCODE_X0 = 8, - BBNST_BRANCH_OPCODE_X1 = 15, - BBNS_BRANCH_OPCODE_X1 = 14, - BBNS_OPCODE_SN = 63, - BBST_BRANCH_OPCODE_X1 = 13, - BBS_BRANCH_OPCODE_X1 = 12, - BBS_OPCODE_SN = 62, - BGEZT_BRANCH_OPCODE_X1 = 7, - BGEZ_BRANCH_OPCODE_X1 = 6, - BGEZ_OPCODE_SN = 61, - BGZT_BRANCH_OPCODE_X1 = 5, - BGZ_BRANCH_OPCODE_X1 = 4, - BGZ_OPCODE_SN = 58, - BITX_UN_0_SHUN_0_OPCODE_X0 = 1, - BITX_UN_0_SHUN_0_OPCODE_Y0 = 1, - BLEZT_BRANCH_OPCODE_X1 = 11, - BLEZ_BRANCH_OPCODE_X1 = 10, - BLEZ_OPCODE_SN = 59, - BLZT_BRANCH_OPCODE_X1 = 9, - BLZ_BRANCH_OPCODE_X1 = 8, - BLZ_OPCODE_SN = 60, - BNZT_BRANCH_OPCODE_X1 = 3, - BNZ_BRANCH_OPCODE_X1 = 2, - BNZ_OPCODE_SN = 57, - BPT_NOREG_RR_IMM_0_OPCODE_SN = 1, - BRANCH_OPCODE_X1 = 5, - BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2, - BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2, - BZT_BRANCH_OPCODE_X1 = 1, - BZ_BRANCH_OPCODE_X1 = 0, - BZ_OPCODE_SN = 56, - CLZ_UN_0_SHUN_0_OPCODE_X0 = 3, - CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3, - CRC32_32_SPECIAL_0_OPCODE_X0 = 9, - CRC32_8_SPECIAL_0_OPCODE_X0 = 10, - CTZ_UN_0_SHUN_0_OPCODE_X0 = 4, - CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4, - DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1, - DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2, - DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95, - FINV_UN_0_SHUN_0_OPCODE_X1 = 3, - FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4, - FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3, - FNOP_UN_0_SHUN_0_OPCODE_X0 = 5, - FNOP_UN_0_SHUN_0_OPCODE_X1 = 5, - FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5, - FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1, - HALT_NOREG_RR_IMM_0_OPCODE_SN = 0, - ICOH_UN_0_SHUN_0_OPCODE_X1 = 6, - ILL_UN_0_SHUN_0_OPCODE_X1 = 7, - ILL_UN_0_SHUN_0_OPCODE_Y1 = 2, - IMM_0_OPCODE_SN = 0, - IMM_0_OPCODE_X0 = 4, - IMM_0_OPCODE_X1 = 6, - IMM_1_OPCODE_SN = 1, - IMM_OPCODE_0_X0 = 5, - INTHB_SPECIAL_0_OPCODE_X0 = 11, - INTHB_SPECIAL_0_OPCODE_X1 = 5, - INTHH_SPECIAL_0_OPCODE_X0 = 12, - INTHH_SPECIAL_0_OPCODE_X1 = 6, - INTLB_SPECIAL_0_OPCODE_X0 = 13, - INTLB_SPECIAL_0_OPCODE_X1 = 7, - INTLH_SPECIAL_0_OPCODE_X0 = 14, - INTLH_SPECIAL_0_OPCODE_X1 = 8, - INV_UN_0_SHUN_0_OPCODE_X1 = 8, - IRET_UN_0_SHUN_0_OPCODE_X1 = 9, - JALB_OPCODE_X1 = 13, - JALF_OPCODE_X1 = 12, - JALRP_SPECIAL_0_OPCODE_X1 = 9, - JALRR_IMM_1_OPCODE_SN = 3, - JALR_RR_IMM_0_OPCODE_SN = 5, - JALR_SPECIAL_0_OPCODE_X1 = 10, - JB_OPCODE_X1 = 11, - JF_OPCODE_X1 = 10, - JRP_SPECIAL_0_OPCODE_X1 = 11, - JRR_IMM_1_OPCODE_SN = 2, - JR_RR_IMM_0_OPCODE_SN = 4, - JR_SPECIAL_0_OPCODE_X1 = 12, - LBADD_IMM_0_OPCODE_X1 = 22, - LBADD_U_IMM_0_OPCODE_X1 = 23, - LB_OPCODE_Y2 = 0, - LB_UN_0_SHUN_0_OPCODE_X1 = 10, - LB_U_OPCODE_Y2 = 1, - LB_U_UN_0_SHUN_0_OPCODE_X1 = 11, - LHADD_IMM_0_OPCODE_X1 = 24, - LHADD_U_IMM_0_OPCODE_X1 = 25, - LH_OPCODE_Y2 = 2, - LH_UN_0_SHUN_0_OPCODE_X1 = 12, - LH_U_OPCODE_Y2 = 3, - LH_U_UN_0_SHUN_0_OPCODE_X1 = 13, - LNK_SPECIAL_0_OPCODE_X1 = 13, - LWADD_IMM_0_OPCODE_X1 = 26, - LWADD_NA_IMM_0_OPCODE_X1 = 27, - LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24, - LW_OPCODE_Y2 = 4, - LW_UN_0_SHUN_0_OPCODE_X1 = 14, - MAXB_U_SPECIAL_0_OPCODE_X0 = 15, - MAXB_U_SPECIAL_0_OPCODE_X1 = 14, - MAXH_SPECIAL_0_OPCODE_X0 = 16, - MAXH_SPECIAL_0_OPCODE_X1 = 15, - MAXIB_U_IMM_0_OPCODE_X0 = 4, - MAXIB_U_IMM_0_OPCODE_X1 = 5, - MAXIH_IMM_0_OPCODE_X0 = 5, - MAXIH_IMM_0_OPCODE_X1 = 6, - MFSPR_IMM_0_OPCODE_X1 = 7, - MF_UN_0_SHUN_0_OPCODE_X1 = 15, - MINB_U_SPECIAL_0_OPCODE_X0 = 17, - MINB_U_SPECIAL_0_OPCODE_X1 = 16, - MINH_SPECIAL_0_OPCODE_X0 = 18, - MINH_SPECIAL_0_OPCODE_X1 = 17, - MINIB_U_IMM_0_OPCODE_X0 = 6, - MINIB_U_IMM_0_OPCODE_X1 = 8, - MINIH_IMM_0_OPCODE_X0 = 7, - MINIH_IMM_0_OPCODE_X1 = 9, - MM_OPCODE_X0 = 6, - MM_OPCODE_X1 = 7, - MNZB_SPECIAL_0_OPCODE_X0 = 19, - MNZB_SPECIAL_0_OPCODE_X1 = 18, - MNZH_SPECIAL_0_OPCODE_X0 = 20, - MNZH_SPECIAL_0_OPCODE_X1 = 19, - MNZ_SPECIAL_0_OPCODE_X0 = 21, - MNZ_SPECIAL_0_OPCODE_X1 = 20, - MNZ_SPECIAL_1_OPCODE_Y0 = 0, - MNZ_SPECIAL_1_OPCODE_Y1 = 1, - MOVEI_IMM_1_OPCODE_SN = 0, - MOVE_RR_IMM_0_OPCODE_SN = 8, - MTSPR_IMM_0_OPCODE_X1 = 10, - MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22, - MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0, - MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23, - MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24, - MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1, - MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25, - MULHH_SS_SPECIAL_0_OPCODE_X0 = 26, - MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0, - MULHH_SU_SPECIAL_0_OPCODE_X0 = 27, - MULHH_UU_SPECIAL_0_OPCODE_X0 = 28, - MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1, - MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29, - MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30, - MULHLA_US_SPECIAL_0_OPCODE_X0 = 31, - MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32, - MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33, - MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0, - MULHL_SS_SPECIAL_0_OPCODE_X0 = 34, - MULHL_SU_SPECIAL_0_OPCODE_X0 = 35, - MULHL_US_SPECIAL_0_OPCODE_X0 = 36, - MULHL_UU_SPECIAL_0_OPCODE_X0 = 37, - MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38, - MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2, - MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39, - MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40, - MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3, - MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41, - MULLL_SS_SPECIAL_0_OPCODE_X0 = 42, - MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2, - MULLL_SU_SPECIAL_0_OPCODE_X0 = 43, - MULLL_UU_SPECIAL_0_OPCODE_X0 = 44, - MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3, - MVNZ_SPECIAL_0_OPCODE_X0 = 45, - MVNZ_SPECIAL_1_OPCODE_Y0 = 1, - MVZ_SPECIAL_0_OPCODE_X0 = 46, - MVZ_SPECIAL_1_OPCODE_Y0 = 2, - MZB_SPECIAL_0_OPCODE_X0 = 47, - MZB_SPECIAL_0_OPCODE_X1 = 21, - MZH_SPECIAL_0_OPCODE_X0 = 48, - MZH_SPECIAL_0_OPCODE_X1 = 22, - MZ_SPECIAL_0_OPCODE_X0 = 49, - MZ_SPECIAL_0_OPCODE_X1 = 23, - MZ_SPECIAL_1_OPCODE_Y0 = 3, - MZ_SPECIAL_1_OPCODE_Y1 = 2, - NAP_UN_0_SHUN_0_OPCODE_X1 = 16, - NOP_NOREG_RR_IMM_0_OPCODE_SN = 2, - NOP_UN_0_SHUN_0_OPCODE_X0 = 6, - NOP_UN_0_SHUN_0_OPCODE_X1 = 17, - NOP_UN_0_SHUN_0_OPCODE_Y0 = 6, - NOP_UN_0_SHUN_0_OPCODE_Y1 = 3, - NOREG_RR_IMM_0_OPCODE_SN = 0, - NOR_SPECIAL_0_OPCODE_X0 = 50, - NOR_SPECIAL_0_OPCODE_X1 = 24, - NOR_SPECIAL_2_OPCODE_Y0 = 1, - NOR_SPECIAL_2_OPCODE_Y1 = 1, - ORI_IMM_0_OPCODE_X0 = 8, - ORI_IMM_0_OPCODE_X1 = 11, - ORI_OPCODE_Y0 = 11, - ORI_OPCODE_Y1 = 9, - OR_SPECIAL_0_OPCODE_X0 = 51, - OR_SPECIAL_0_OPCODE_X1 = 25, - OR_SPECIAL_2_OPCODE_Y0 = 2, - OR_SPECIAL_2_OPCODE_Y1 = 2, - PACKBS_U_SPECIAL_0_OPCODE_X0 = 103, - PACKBS_U_SPECIAL_0_OPCODE_X1 = 73, - PACKHB_SPECIAL_0_OPCODE_X0 = 52, - PACKHB_SPECIAL_0_OPCODE_X1 = 26, - PACKHS_SPECIAL_0_OPCODE_X0 = 102, - PACKHS_SPECIAL_0_OPCODE_X1 = 72, - PACKLB_SPECIAL_0_OPCODE_X0 = 53, - PACKLB_SPECIAL_0_OPCODE_X1 = 27, - PCNT_UN_0_SHUN_0_OPCODE_X0 = 7, - PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7, - RLI_SHUN_0_OPCODE_X0 = 1, - RLI_SHUN_0_OPCODE_X1 = 1, - RLI_SHUN_0_OPCODE_Y0 = 1, - RLI_SHUN_0_OPCODE_Y1 = 1, - RL_SPECIAL_0_OPCODE_X0 = 54, - RL_SPECIAL_0_OPCODE_X1 = 28, - RL_SPECIAL_3_OPCODE_Y0 = 0, - RL_SPECIAL_3_OPCODE_Y1 = 0, - RR_IMM_0_OPCODE_SN = 0, - S1A_SPECIAL_0_OPCODE_X0 = 55, - S1A_SPECIAL_0_OPCODE_X1 = 29, - S1A_SPECIAL_0_OPCODE_Y0 = 1, - S1A_SPECIAL_0_OPCODE_Y1 = 1, - S2A_SPECIAL_0_OPCODE_X0 = 56, - S2A_SPECIAL_0_OPCODE_X1 = 30, - S2A_SPECIAL_0_OPCODE_Y0 = 2, - S2A_SPECIAL_0_OPCODE_Y1 = 2, - S3A_SPECIAL_0_OPCODE_X0 = 57, - S3A_SPECIAL_0_OPCODE_X1 = 31, - S3A_SPECIAL_5_OPCODE_Y0 = 1, - S3A_SPECIAL_5_OPCODE_Y1 = 1, - SADAB_U_SPECIAL_0_OPCODE_X0 = 58, - SADAH_SPECIAL_0_OPCODE_X0 = 59, - SADAH_U_SPECIAL_0_OPCODE_X0 = 60, - SADB_U_SPECIAL_0_OPCODE_X0 = 61, - SADH_SPECIAL_0_OPCODE_X0 = 62, - SADH_U_SPECIAL_0_OPCODE_X0 = 63, - SBADD_IMM_0_OPCODE_X1 = 28, - SB_OPCODE_Y2 = 5, - SB_SPECIAL_0_OPCODE_X1 = 32, - SEQB_SPECIAL_0_OPCODE_X0 = 64, - SEQB_SPECIAL_0_OPCODE_X1 = 33, - SEQH_SPECIAL_0_OPCODE_X0 = 65, - SEQH_SPECIAL_0_OPCODE_X1 = 34, - SEQIB_IMM_0_OPCODE_X0 = 9, - SEQIB_IMM_0_OPCODE_X1 = 12, - SEQIH_IMM_0_OPCODE_X0 = 10, - SEQIH_IMM_0_OPCODE_X1 = 13, - SEQI_IMM_0_OPCODE_X0 = 11, - SEQI_IMM_0_OPCODE_X1 = 14, - SEQI_OPCODE_Y0 = 12, - SEQI_OPCODE_Y1 = 10, - SEQ_SPECIAL_0_OPCODE_X0 = 66, - SEQ_SPECIAL_0_OPCODE_X1 = 35, - SEQ_SPECIAL_5_OPCODE_Y0 = 2, - SEQ_SPECIAL_5_OPCODE_Y1 = 2, - SHADD_IMM_0_OPCODE_X1 = 29, - SHL8II_IMM_0_OPCODE_SN = 3, - SHLB_SPECIAL_0_OPCODE_X0 = 67, - SHLB_SPECIAL_0_OPCODE_X1 = 36, - SHLH_SPECIAL_0_OPCODE_X0 = 68, - SHLH_SPECIAL_0_OPCODE_X1 = 37, - SHLIB_SHUN_0_OPCODE_X0 = 2, - SHLIB_SHUN_0_OPCODE_X1 = 2, - SHLIH_SHUN_0_OPCODE_X0 = 3, - SHLIH_SHUN_0_OPCODE_X1 = 3, - SHLI_SHUN_0_OPCODE_X0 = 4, - SHLI_SHUN_0_OPCODE_X1 = 4, - SHLI_SHUN_0_OPCODE_Y0 = 2, - SHLI_SHUN_0_OPCODE_Y1 = 2, - SHL_SPECIAL_0_OPCODE_X0 = 69, - SHL_SPECIAL_0_OPCODE_X1 = 38, - SHL_SPECIAL_3_OPCODE_Y0 = 1, - SHL_SPECIAL_3_OPCODE_Y1 = 1, - SHR1_RR_IMM_0_OPCODE_SN = 9, - SHRB_SPECIAL_0_OPCODE_X0 = 70, - SHRB_SPECIAL_0_OPCODE_X1 = 39, - SHRH_SPECIAL_0_OPCODE_X0 = 71, - SHRH_SPECIAL_0_OPCODE_X1 = 40, - SHRIB_SHUN_0_OPCODE_X0 = 5, - SHRIB_SHUN_0_OPCODE_X1 = 5, - SHRIH_SHUN_0_OPCODE_X0 = 6, - SHRIH_SHUN_0_OPCODE_X1 = 6, - SHRI_SHUN_0_OPCODE_X0 = 7, - SHRI_SHUN_0_OPCODE_X1 = 7, - SHRI_SHUN_0_OPCODE_Y0 = 3, - SHRI_SHUN_0_OPCODE_Y1 = 3, - SHR_SPECIAL_0_OPCODE_X0 = 72, - SHR_SPECIAL_0_OPCODE_X1 = 41, - SHR_SPECIAL_3_OPCODE_Y0 = 2, - SHR_SPECIAL_3_OPCODE_Y1 = 2, - SHUN_0_OPCODE_X0 = 7, - SHUN_0_OPCODE_X1 = 8, - SHUN_0_OPCODE_Y0 = 13, - SHUN_0_OPCODE_Y1 = 11, - SH_OPCODE_Y2 = 6, - SH_SPECIAL_0_OPCODE_X1 = 42, - SLTB_SPECIAL_0_OPCODE_X0 = 73, - SLTB_SPECIAL_0_OPCODE_X1 = 43, - SLTB_U_SPECIAL_0_OPCODE_X0 = 74, - SLTB_U_SPECIAL_0_OPCODE_X1 = 44, - SLTEB_SPECIAL_0_OPCODE_X0 = 75, - SLTEB_SPECIAL_0_OPCODE_X1 = 45, - SLTEB_U_SPECIAL_0_OPCODE_X0 = 76, - SLTEB_U_SPECIAL_0_OPCODE_X1 = 46, - SLTEH_SPECIAL_0_OPCODE_X0 = 77, - SLTEH_SPECIAL_0_OPCODE_X1 = 47, - SLTEH_U_SPECIAL_0_OPCODE_X0 = 78, - SLTEH_U_SPECIAL_0_OPCODE_X1 = 48, - SLTE_SPECIAL_0_OPCODE_X0 = 79, - SLTE_SPECIAL_0_OPCODE_X1 = 49, - SLTE_SPECIAL_4_OPCODE_Y0 = 0, - SLTE_SPECIAL_4_OPCODE_Y1 = 0, - SLTE_U_SPECIAL_0_OPCODE_X0 = 80, - SLTE_U_SPECIAL_0_OPCODE_X1 = 50, - SLTE_U_SPECIAL_4_OPCODE_Y0 = 1, - SLTE_U_SPECIAL_4_OPCODE_Y1 = 1, - SLTH_SPECIAL_0_OPCODE_X0 = 81, - SLTH_SPECIAL_0_OPCODE_X1 = 51, - SLTH_U_SPECIAL_0_OPCODE_X0 = 82, - SLTH_U_SPECIAL_0_OPCODE_X1 = 52, - SLTIB_IMM_0_OPCODE_X0 = 12, - SLTIB_IMM_0_OPCODE_X1 = 15, - SLTIB_U_IMM_0_OPCODE_X0 = 13, - SLTIB_U_IMM_0_OPCODE_X1 = 16, - SLTIH_IMM_0_OPCODE_X0 = 14, - SLTIH_IMM_0_OPCODE_X1 = 17, - SLTIH_U_IMM_0_OPCODE_X0 = 15, - SLTIH_U_IMM_0_OPCODE_X1 = 18, - SLTI_IMM_0_OPCODE_X0 = 16, - SLTI_IMM_0_OPCODE_X1 = 19, - SLTI_OPCODE_Y0 = 14, - SLTI_OPCODE_Y1 = 12, - SLTI_U_IMM_0_OPCODE_X0 = 17, - SLTI_U_IMM_0_OPCODE_X1 = 20, - SLTI_U_OPCODE_Y0 = 15, - SLTI_U_OPCODE_Y1 = 13, - SLT_SPECIAL_0_OPCODE_X0 = 83, - SLT_SPECIAL_0_OPCODE_X1 = 53, - SLT_SPECIAL_4_OPCODE_Y0 = 2, - SLT_SPECIAL_4_OPCODE_Y1 = 2, - SLT_U_SPECIAL_0_OPCODE_X0 = 84, - SLT_U_SPECIAL_0_OPCODE_X1 = 54, - SLT_U_SPECIAL_4_OPCODE_Y0 = 3, - SLT_U_SPECIAL_4_OPCODE_Y1 = 3, - SNEB_SPECIAL_0_OPCODE_X0 = 85, - SNEB_SPECIAL_0_OPCODE_X1 = 55, - SNEH_SPECIAL_0_OPCODE_X0 = 86, - SNEH_SPECIAL_0_OPCODE_X1 = 56, - SNE_SPECIAL_0_OPCODE_X0 = 87, - SNE_SPECIAL_0_OPCODE_X1 = 57, - SNE_SPECIAL_5_OPCODE_Y0 = 3, - SNE_SPECIAL_5_OPCODE_Y1 = 3, - SPECIAL_0_OPCODE_X0 = 0, - SPECIAL_0_OPCODE_X1 = 1, - SPECIAL_0_OPCODE_Y0 = 1, - SPECIAL_0_OPCODE_Y1 = 1, - SPECIAL_1_OPCODE_Y0 = 2, - SPECIAL_1_OPCODE_Y1 = 2, - SPECIAL_2_OPCODE_Y0 = 3, - SPECIAL_2_OPCODE_Y1 = 3, - SPECIAL_3_OPCODE_Y0 = 4, - SPECIAL_3_OPCODE_Y1 = 4, - SPECIAL_4_OPCODE_Y0 = 5, - SPECIAL_4_OPCODE_Y1 = 5, - SPECIAL_5_OPCODE_Y0 = 6, - SPECIAL_5_OPCODE_Y1 = 6, - SPECIAL_6_OPCODE_Y0 = 7, - SPECIAL_7_OPCODE_Y0 = 8, - SRAB_SPECIAL_0_OPCODE_X0 = 88, - SRAB_SPECIAL_0_OPCODE_X1 = 58, - SRAH_SPECIAL_0_OPCODE_X0 = 89, - SRAH_SPECIAL_0_OPCODE_X1 = 59, - SRAIB_SHUN_0_OPCODE_X0 = 8, - SRAIB_SHUN_0_OPCODE_X1 = 8, - SRAIH_SHUN_0_OPCODE_X0 = 9, - SRAIH_SHUN_0_OPCODE_X1 = 9, - SRAI_SHUN_0_OPCODE_X0 = 10, - SRAI_SHUN_0_OPCODE_X1 = 10, - SRAI_SHUN_0_OPCODE_Y0 = 4, - SRAI_SHUN_0_OPCODE_Y1 = 4, - SRA_SPECIAL_0_OPCODE_X0 = 90, - SRA_SPECIAL_0_OPCODE_X1 = 60, - SRA_SPECIAL_3_OPCODE_Y0 = 3, - SRA_SPECIAL_3_OPCODE_Y1 = 3, - SUBBS_U_SPECIAL_0_OPCODE_X0 = 100, - SUBBS_U_SPECIAL_0_OPCODE_X1 = 70, - SUBB_SPECIAL_0_OPCODE_X0 = 91, - SUBB_SPECIAL_0_OPCODE_X1 = 61, - SUBHS_SPECIAL_0_OPCODE_X0 = 101, - SUBHS_SPECIAL_0_OPCODE_X1 = 71, - SUBH_SPECIAL_0_OPCODE_X0 = 92, - SUBH_SPECIAL_0_OPCODE_X1 = 62, - SUBS_SPECIAL_0_OPCODE_X0 = 97, - SUBS_SPECIAL_0_OPCODE_X1 = 67, - SUB_SPECIAL_0_OPCODE_X0 = 93, - SUB_SPECIAL_0_OPCODE_X1 = 63, - SUB_SPECIAL_0_OPCODE_Y0 = 3, - SUB_SPECIAL_0_OPCODE_Y1 = 3, - SWADD_IMM_0_OPCODE_X1 = 30, - SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18, - SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19, - SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20, - SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21, - SW_OPCODE_Y2 = 7, - SW_SPECIAL_0_OPCODE_X1 = 64, - TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8, - TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8, - TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9, - TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9, - TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10, - TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10, - TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11, - TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11, - TNS_UN_0_SHUN_0_OPCODE_X1 = 22, - UN_0_SHUN_0_OPCODE_X0 = 11, - UN_0_SHUN_0_OPCODE_X1 = 11, - UN_0_SHUN_0_OPCODE_Y0 = 5, - UN_0_SHUN_0_OPCODE_Y1 = 5, - WH64_UN_0_SHUN_0_OPCODE_X1 = 23, - XORI_IMM_0_OPCODE_X0 = 2, - XORI_IMM_0_OPCODE_X1 = 21, - XOR_SPECIAL_0_OPCODE_X0 = 94, - XOR_SPECIAL_0_OPCODE_X1 = 65, - XOR_SPECIAL_2_OPCODE_Y0 = 3, - XOR_SPECIAL_2_OPCODE_Y1 = 3 + ADDI_IMM8_OPCODE_X0 = 1, + ADDI_IMM8_OPCODE_X1 = 1, + ADDI_OPCODE_Y0 = 0, + ADDI_OPCODE_Y1 = 1, + ADDLI_OPCODE_X0 = 1, + ADDLI_OPCODE_X1 = 0, + ADDXI_IMM8_OPCODE_X0 = 2, + ADDXI_IMM8_OPCODE_X1 = 2, + ADDXI_OPCODE_Y0 = 1, + ADDXI_OPCODE_Y1 = 2, + ADDXLI_OPCODE_X0 = 2, + ADDXLI_OPCODE_X1 = 1, + ADDXSC_RRR_0_OPCODE_X0 = 1, + ADDXSC_RRR_0_OPCODE_X1 = 1, + ADDX_RRR_0_OPCODE_X0 = 2, + ADDX_RRR_0_OPCODE_X1 = 2, + ADDX_RRR_0_OPCODE_Y0 = 0, + ADDX_SPECIAL_0_OPCODE_Y1 = 0, + ADD_RRR_0_OPCODE_X0 = 3, + ADD_RRR_0_OPCODE_X1 = 3, + ADD_RRR_0_OPCODE_Y0 = 1, + ADD_SPECIAL_0_OPCODE_Y1 = 1, + ANDI_IMM8_OPCODE_X0 = 3, + ANDI_IMM8_OPCODE_X1 = 3, + ANDI_OPCODE_Y0 = 2, + ANDI_OPCODE_Y1 = 3, + AND_RRR_0_OPCODE_X0 = 4, + AND_RRR_0_OPCODE_X1 = 4, + AND_RRR_5_OPCODE_Y0 = 0, + AND_RRR_5_OPCODE_Y1 = 0, + BEQZT_BRANCH_OPCODE_X1 = 16, + BEQZ_BRANCH_OPCODE_X1 = 17, + BFEXTS_BF_OPCODE_X0 = 4, + BFEXTU_BF_OPCODE_X0 = 5, + BFINS_BF_OPCODE_X0 = 6, + BF_OPCODE_X0 = 3, + BGEZT_BRANCH_OPCODE_X1 = 18, + BGEZ_BRANCH_OPCODE_X1 = 19, + BGTZT_BRANCH_OPCODE_X1 = 20, + BGTZ_BRANCH_OPCODE_X1 = 21, + BLBCT_BRANCH_OPCODE_X1 = 22, + BLBC_BRANCH_OPCODE_X1 = 23, + BLBST_BRANCH_OPCODE_X1 = 24, + BLBS_BRANCH_OPCODE_X1 = 25, + BLEZT_BRANCH_OPCODE_X1 = 26, + BLEZ_BRANCH_OPCODE_X1 = 27, + BLTZT_BRANCH_OPCODE_X1 = 28, + BLTZ_BRANCH_OPCODE_X1 = 29, + BNEZT_BRANCH_OPCODE_X1 = 30, + BNEZ_BRANCH_OPCODE_X1 = 31, + BRANCH_OPCODE_X1 = 2, + CMOVEQZ_RRR_0_OPCODE_X0 = 5, + CMOVEQZ_RRR_4_OPCODE_Y0 = 0, + CMOVNEZ_RRR_0_OPCODE_X0 = 6, + CMOVNEZ_RRR_4_OPCODE_Y0 = 1, + CMPEQI_IMM8_OPCODE_X0 = 4, + CMPEQI_IMM8_OPCODE_X1 = 4, + CMPEQI_OPCODE_Y0 = 3, + CMPEQI_OPCODE_Y1 = 4, + CMPEQ_RRR_0_OPCODE_X0 = 7, + CMPEQ_RRR_0_OPCODE_X1 = 5, + CMPEQ_RRR_3_OPCODE_Y0 = 0, + CMPEQ_RRR_3_OPCODE_Y1 = 2, + CMPEXCH4_RRR_0_OPCODE_X1 = 6, + CMPEXCH_RRR_0_OPCODE_X1 = 7, + CMPLES_RRR_0_OPCODE_X0 = 8, + CMPLES_RRR_0_OPCODE_X1 = 8, + CMPLES_RRR_2_OPCODE_Y0 = 0, + CMPLES_RRR_2_OPCODE_Y1 = 0, + CMPLEU_RRR_0_OPCODE_X0 = 9, + CMPLEU_RRR_0_OPCODE_X1 = 9, + CMPLEU_RRR_2_OPCODE_Y0 = 1, + CMPLEU_RRR_2_OPCODE_Y1 = 1, + CMPLTSI_IMM8_OPCODE_X0 = 5, + CMPLTSI_IMM8_OPCODE_X1 = 5, + CMPLTSI_OPCODE_Y0 = 4, + CMPLTSI_OPCODE_Y1 = 5, + CMPLTS_RRR_0_OPCODE_X0 = 10, + CMPLTS_RRR_0_OPCODE_X1 = 10, + CMPLTS_RRR_2_OPCODE_Y0 = 2, + CMPLTS_RRR_2_OPCODE_Y1 = 2, + CMPLTUI_IMM8_OPCODE_X0 = 6, + CMPLTUI_IMM8_OPCODE_X1 = 6, + CMPLTU_RRR_0_OPCODE_X0 = 11, + CMPLTU_RRR_0_OPCODE_X1 = 11, + CMPLTU_RRR_2_OPCODE_Y0 = 3, + CMPLTU_RRR_2_OPCODE_Y1 = 3, + CMPNE_RRR_0_OPCODE_X0 = 12, + CMPNE_RRR_0_OPCODE_X1 = 12, + CMPNE_RRR_3_OPCODE_Y0 = 1, + CMPNE_RRR_3_OPCODE_Y1 = 3, + CMULAF_RRR_0_OPCODE_X0 = 13, + CMULA_RRR_0_OPCODE_X0 = 14, + CMULFR_RRR_0_OPCODE_X0 = 15, + CMULF_RRR_0_OPCODE_X0 = 16, + CMULHR_RRR_0_OPCODE_X0 = 17, + CMULH_RRR_0_OPCODE_X0 = 18, + CMUL_RRR_0_OPCODE_X0 = 19, + CNTLZ_UNARY_OPCODE_X0 = 1, + CNTLZ_UNARY_OPCODE_Y0 = 1, + CNTTZ_UNARY_OPCODE_X0 = 2, + CNTTZ_UNARY_OPCODE_Y0 = 2, + CRC32_32_RRR_0_OPCODE_X0 = 20, + CRC32_8_RRR_0_OPCODE_X0 = 21, + DBLALIGN2_RRR_0_OPCODE_X0 = 22, + DBLALIGN2_RRR_0_OPCODE_X1 = 13, + DBLALIGN4_RRR_0_OPCODE_X0 = 23, + DBLALIGN4_RRR_0_OPCODE_X1 = 14, + DBLALIGN6_RRR_0_OPCODE_X0 = 24, + DBLALIGN6_RRR_0_OPCODE_X1 = 15, + DBLALIGN_RRR_0_OPCODE_X0 = 25, + DRAIN_UNARY_OPCODE_X1 = 1, + DTLBPR_UNARY_OPCODE_X1 = 2, + EXCH4_RRR_0_OPCODE_X1 = 16, + EXCH_RRR_0_OPCODE_X1 = 17, + FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26, + FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27, + FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28, + FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29, + FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30, + FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31, + FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32, + FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33, + FETCHADD4_RRR_0_OPCODE_X1 = 18, + FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19, + FETCHADDGEZ_RRR_0_OPCODE_X1 = 20, + FETCHADD_RRR_0_OPCODE_X1 = 21, + FETCHAND4_RRR_0_OPCODE_X1 = 22, + FETCHAND_RRR_0_OPCODE_X1 = 23, + FETCHOR4_RRR_0_OPCODE_X1 = 24, + FETCHOR_RRR_0_OPCODE_X1 = 25, + FINV_UNARY_OPCODE_X1 = 3, + FLUSHWB_UNARY_OPCODE_X1 = 4, + FLUSH_UNARY_OPCODE_X1 = 5, + FNOP_UNARY_OPCODE_X0 = 3, + FNOP_UNARY_OPCODE_X1 = 6, + FNOP_UNARY_OPCODE_Y0 = 3, + FNOP_UNARY_OPCODE_Y1 = 8, + FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34, + FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35, + FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36, + FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37, + FSINGLE_PACK1_UNARY_OPCODE_X0 = 4, + FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4, + FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38, + FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39, + ICOH_UNARY_OPCODE_X1 = 7, + ILL_UNARY_OPCODE_X1 = 8, + ILL_UNARY_OPCODE_Y1 = 9, + IMM8_OPCODE_X0 = 4, + IMM8_OPCODE_X1 = 3, + INV_UNARY_OPCODE_X1 = 9, + IRET_UNARY_OPCODE_X1 = 10, + JALRP_UNARY_OPCODE_X1 = 11, + JALRP_UNARY_OPCODE_Y1 = 10, + JALR_UNARY_OPCODE_X1 = 12, + JALR_UNARY_OPCODE_Y1 = 11, + JAL_JUMP_OPCODE_X1 = 0, + JRP_UNARY_OPCODE_X1 = 13, + JRP_UNARY_OPCODE_Y1 = 12, + JR_UNARY_OPCODE_X1 = 14, + JR_UNARY_OPCODE_Y1 = 13, + JUMP_OPCODE_X1 = 4, + J_JUMP_OPCODE_X1 = 1, + LD1S_ADD_IMM8_OPCODE_X1 = 7, + LD1S_OPCODE_Y2 = 0, + LD1S_UNARY_OPCODE_X1 = 15, + LD1U_ADD_IMM8_OPCODE_X1 = 8, + LD1U_OPCODE_Y2 = 1, + LD1U_UNARY_OPCODE_X1 = 16, + LD2S_ADD_IMM8_OPCODE_X1 = 9, + LD2S_OPCODE_Y2 = 2, + LD2S_UNARY_OPCODE_X1 = 17, + LD2U_ADD_IMM8_OPCODE_X1 = 10, + LD2U_OPCODE_Y2 = 3, + LD2U_UNARY_OPCODE_X1 = 18, + LD4S_ADD_IMM8_OPCODE_X1 = 11, + LD4S_OPCODE_Y2 = 1, + LD4S_UNARY_OPCODE_X1 = 19, + LD4U_ADD_IMM8_OPCODE_X1 = 12, + LD4U_OPCODE_Y2 = 2, + LD4U_UNARY_OPCODE_X1 = 20, + LDNA_UNARY_OPCODE_X1 = 21, + LDNT1S_ADD_IMM8_OPCODE_X1 = 13, + LDNT1S_UNARY_OPCODE_X1 = 22, + LDNT1U_ADD_IMM8_OPCODE_X1 = 14, + LDNT1U_UNARY_OPCODE_X1 = 23, + LDNT2S_ADD_IMM8_OPCODE_X1 = 15, + LDNT2S_UNARY_OPCODE_X1 = 24, + LDNT2U_ADD_IMM8_OPCODE_X1 = 16, + LDNT2U_UNARY_OPCODE_X1 = 25, + LDNT4S_ADD_IMM8_OPCODE_X1 = 17, + LDNT4S_UNARY_OPCODE_X1 = 26, + LDNT4U_ADD_IMM8_OPCODE_X1 = 18, + LDNT4U_UNARY_OPCODE_X1 = 27, + LDNT_ADD_IMM8_OPCODE_X1 = 19, + LDNT_UNARY_OPCODE_X1 = 28, + LD_ADD_IMM8_OPCODE_X1 = 20, + LD_OPCODE_Y2 = 3, + LD_UNARY_OPCODE_X1 = 29, + LNK_UNARY_OPCODE_X1 = 30, + LNK_UNARY_OPCODE_Y1 = 14, + LWNA_ADD_IMM8_OPCODE_X1 = 21, + MFSPR_IMM8_OPCODE_X1 = 22, + MF_UNARY_OPCODE_X1 = 31, + MM_BF_OPCODE_X0 = 7, + MNZ_RRR_0_OPCODE_X0 = 40, + MNZ_RRR_0_OPCODE_X1 = 26, + MNZ_RRR_4_OPCODE_Y0 = 2, + MNZ_RRR_4_OPCODE_Y1 = 2, + MODE_OPCODE_YA2 = 1, + MODE_OPCODE_YB2 = 2, + MODE_OPCODE_YC2 = 3, + MTSPR_IMM8_OPCODE_X1 = 23, + MULAX_RRR_0_OPCODE_X0 = 41, + MULAX_RRR_3_OPCODE_Y0 = 2, + MULA_HS_HS_RRR_0_OPCODE_X0 = 42, + MULA_HS_HS_RRR_9_OPCODE_Y0 = 0, + MULA_HS_HU_RRR_0_OPCODE_X0 = 43, + MULA_HS_LS_RRR_0_OPCODE_X0 = 44, + MULA_HS_LU_RRR_0_OPCODE_X0 = 45, + MULA_HU_HU_RRR_0_OPCODE_X0 = 46, + MULA_HU_HU_RRR_9_OPCODE_Y0 = 1, + MULA_HU_LS_RRR_0_OPCODE_X0 = 47, + MULA_HU_LU_RRR_0_OPCODE_X0 = 48, + MULA_LS_LS_RRR_0_OPCODE_X0 = 49, + MULA_LS_LS_RRR_9_OPCODE_Y0 = 2, + MULA_LS_LU_RRR_0_OPCODE_X0 = 50, + MULA_LU_LU_RRR_0_OPCODE_X0 = 51, + MULA_LU_LU_RRR_9_OPCODE_Y0 = 3, + MULX_RRR_0_OPCODE_X0 = 52, + MULX_RRR_3_OPCODE_Y0 = 3, + MUL_HS_HS_RRR_0_OPCODE_X0 = 53, + MUL_HS_HS_RRR_8_OPCODE_Y0 = 0, + MUL_HS_HU_RRR_0_OPCODE_X0 = 54, + MUL_HS_LS_RRR_0_OPCODE_X0 = 55, + MUL_HS_LU_RRR_0_OPCODE_X0 = 56, + MUL_HU_HU_RRR_0_OPCODE_X0 = 57, + MUL_HU_HU_RRR_8_OPCODE_Y0 = 1, + MUL_HU_LS_RRR_0_OPCODE_X0 = 58, + MUL_HU_LU_RRR_0_OPCODE_X0 = 59, + MUL_LS_LS_RRR_0_OPCODE_X0 = 60, + MUL_LS_LS_RRR_8_OPCODE_Y0 = 2, + MUL_LS_LU_RRR_0_OPCODE_X0 = 61, + MUL_LU_LU_RRR_0_OPCODE_X0 = 62, + MUL_LU_LU_RRR_8_OPCODE_Y0 = 3, + MZ_RRR_0_OPCODE_X0 = 63, + MZ_RRR_0_OPCODE_X1 = 27, + MZ_RRR_4_OPCODE_Y0 = 3, + MZ_RRR_4_OPCODE_Y1 = 3, + NAP_UNARY_OPCODE_X1 = 32, + NOP_UNARY_OPCODE_X0 = 5, + NOP_UNARY_OPCODE_X1 = 33, + NOP_UNARY_OPCODE_Y0 = 5, + NOP_UNARY_OPCODE_Y1 = 15, + NOR_RRR_0_OPCODE_X0 = 64, + NOR_RRR_0_OPCODE_X1 = 28, + NOR_RRR_5_OPCODE_Y0 = 1, + NOR_RRR_5_OPCODE_Y1 = 1, + ORI_IMM8_OPCODE_X0 = 7, + ORI_IMM8_OPCODE_X1 = 24, + OR_RRR_0_OPCODE_X0 = 65, + OR_RRR_0_OPCODE_X1 = 29, + OR_RRR_5_OPCODE_Y0 = 2, + OR_RRR_5_OPCODE_Y1 = 2, + PCNT_UNARY_OPCODE_X0 = 6, + PCNT_UNARY_OPCODE_Y0 = 6, + REVBITS_UNARY_OPCODE_X0 = 7, + REVBITS_UNARY_OPCODE_Y0 = 7, + REVBYTES_UNARY_OPCODE_X0 = 8, + REVBYTES_UNARY_OPCODE_Y0 = 8, + ROTLI_SHIFT_OPCODE_X0 = 1, + ROTLI_SHIFT_OPCODE_X1 = 1, + ROTLI_SHIFT_OPCODE_Y0 = 0, + ROTLI_SHIFT_OPCODE_Y1 = 0, + ROTL_RRR_0_OPCODE_X0 = 66, + ROTL_RRR_0_OPCODE_X1 = 30, + ROTL_RRR_6_OPCODE_Y0 = 0, + ROTL_RRR_6_OPCODE_Y1 = 0, + RRR_0_OPCODE_X0 = 5, + RRR_0_OPCODE_X1 = 5, + RRR_0_OPCODE_Y0 = 5, + RRR_0_OPCODE_Y1 = 6, + RRR_1_OPCODE_Y0 = 6, + RRR_1_OPCODE_Y1 = 7, + RRR_2_OPCODE_Y0 = 7, + RRR_2_OPCODE_Y1 = 8, + RRR_3_OPCODE_Y0 = 8, + RRR_3_OPCODE_Y1 = 9, + RRR_4_OPCODE_Y0 = 9, + RRR_4_OPCODE_Y1 = 10, + RRR_5_OPCODE_Y0 = 10, + RRR_5_OPCODE_Y1 = 11, + RRR_6_OPCODE_Y0 = 11, + RRR_6_OPCODE_Y1 = 12, + RRR_7_OPCODE_Y0 = 12, + RRR_7_OPCODE_Y1 = 13, + RRR_8_OPCODE_Y0 = 13, + RRR_9_OPCODE_Y0 = 14, + SHIFT_OPCODE_X0 = 6, + SHIFT_OPCODE_X1 = 6, + SHIFT_OPCODE_Y0 = 15, + SHIFT_OPCODE_Y1 = 14, + SHL16INSLI_OPCODE_X0 = 7, + SHL16INSLI_OPCODE_X1 = 7, + SHL1ADDX_RRR_0_OPCODE_X0 = 67, + SHL1ADDX_RRR_0_OPCODE_X1 = 31, + SHL1ADDX_RRR_7_OPCODE_Y0 = 1, + SHL1ADDX_RRR_7_OPCODE_Y1 = 1, + SHL1ADD_RRR_0_OPCODE_X0 = 68, + SHL1ADD_RRR_0_OPCODE_X1 = 32, + SHL1ADD_RRR_1_OPCODE_Y0 = 0, + SHL1ADD_RRR_1_OPCODE_Y1 = 0, + SHL2ADDX_RRR_0_OPCODE_X0 = 69, + SHL2ADDX_RRR_0_OPCODE_X1 = 33, + SHL2ADDX_RRR_7_OPCODE_Y0 = 2, + SHL2ADDX_RRR_7_OPCODE_Y1 = 2, + SHL2ADD_RRR_0_OPCODE_X0 = 70, + SHL2ADD_RRR_0_OPCODE_X1 = 34, + SHL2ADD_RRR_1_OPCODE_Y0 = 1, + SHL2ADD_RRR_1_OPCODE_Y1 = 1, + SHL3ADDX_RRR_0_OPCODE_X0 = 71, + SHL3ADDX_RRR_0_OPCODE_X1 = 35, + SHL3ADDX_RRR_7_OPCODE_Y0 = 3, + SHL3ADDX_RRR_7_OPCODE_Y1 = 3, + SHL3ADD_RRR_0_OPCODE_X0 = 72, + SHL3ADD_RRR_0_OPCODE_X1 = 36, + SHL3ADD_RRR_1_OPCODE_Y0 = 2, + SHL3ADD_RRR_1_OPCODE_Y1 = 2, + SHLI_SHIFT_OPCODE_X0 = 2, + SHLI_SHIFT_OPCODE_X1 = 2, + SHLI_SHIFT_OPCODE_Y0 = 1, + SHLI_SHIFT_OPCODE_Y1 = 1, + SHLXI_SHIFT_OPCODE_X0 = 3, + SHLXI_SHIFT_OPCODE_X1 = 3, + SHLX_RRR_0_OPCODE_X0 = 73, + SHLX_RRR_0_OPCODE_X1 = 37, + SHL_RRR_0_OPCODE_X0 = 74, + SHL_RRR_0_OPCODE_X1 = 38, + SHL_RRR_6_OPCODE_Y0 = 1, + SHL_RRR_6_OPCODE_Y1 = 1, + SHRSI_SHIFT_OPCODE_X0 = 4, + SHRSI_SHIFT_OPCODE_X1 = 4, + SHRSI_SHIFT_OPCODE_Y0 = 2, + SHRSI_SHIFT_OPCODE_Y1 = 2, + SHRS_RRR_0_OPCODE_X0 = 75, + SHRS_RRR_0_OPCODE_X1 = 39, + SHRS_RRR_6_OPCODE_Y0 = 2, + SHRS_RRR_6_OPCODE_Y1 = 2, + SHRUI_SHIFT_OPCODE_X0 = 5, + SHRUI_SHIFT_OPCODE_X1 = 5, + SHRUI_SHIFT_OPCODE_Y0 = 3, + SHRUI_SHIFT_OPCODE_Y1 = 3, + SHRUXI_SHIFT_OPCODE_X0 = 6, + SHRUXI_SHIFT_OPCODE_X1 = 6, + SHRUX_RRR_0_OPCODE_X0 = 76, + SHRUX_RRR_0_OPCODE_X1 = 40, + SHRU_RRR_0_OPCODE_X0 = 77, + SHRU_RRR_0_OPCODE_X1 = 41, + SHRU_RRR_6_OPCODE_Y0 = 3, + SHRU_RRR_6_OPCODE_Y1 = 3, + SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78, + ST1_ADD_IMM8_OPCODE_X1 = 25, + ST1_OPCODE_Y2 = 0, + ST1_RRR_0_OPCODE_X1 = 42, + ST2_ADD_IMM8_OPCODE_X1 = 26, + ST2_OPCODE_Y2 = 1, + ST2_RRR_0_OPCODE_X1 = 43, + ST4_ADD_IMM8_OPCODE_X1 = 27, + ST4_OPCODE_Y2 = 2, + ST4_RRR_0_OPCODE_X1 = 44, + STNT1_ADD_IMM8_OPCODE_X1 = 28, + STNT1_RRR_0_OPCODE_X1 = 45, + STNT2_ADD_IMM8_OPCODE_X1 = 29, + STNT2_RRR_0_OPCODE_X1 = 46, + STNT4_ADD_IMM8_OPCODE_X1 = 30, + STNT4_RRR_0_OPCODE_X1 = 47, + STNT_ADD_IMM8_OPCODE_X1 = 31, + STNT_RRR_0_OPCODE_X1 = 48, + ST_ADD_IMM8_OPCODE_X1 = 32, + ST_OPCODE_Y2 = 3, + ST_RRR_0_OPCODE_X1 = 49, + SUBXSC_RRR_0_OPCODE_X0 = 79, + SUBXSC_RRR_0_OPCODE_X1 = 50, + SUBX_RRR_0_OPCODE_X0 = 80, + SUBX_RRR_0_OPCODE_X1 = 51, + SUBX_RRR_0_OPCODE_Y0 = 2, + SUBX_RRR_0_OPCODE_Y1 = 2, + SUB_RRR_0_OPCODE_X0 = 81, + SUB_RRR_0_OPCODE_X1 = 52, + SUB_RRR_0_OPCODE_Y0 = 3, + SUB_RRR_0_OPCODE_Y1 = 3, + SWINT0_UNARY_OPCODE_X1 = 34, + SWINT1_UNARY_OPCODE_X1 = 35, + SWINT2_UNARY_OPCODE_X1 = 36, + SWINT3_UNARY_OPCODE_X1 = 37, + TBLIDXB0_UNARY_OPCODE_X0 = 9, + TBLIDXB0_UNARY_OPCODE_Y0 = 9, + TBLIDXB1_UNARY_OPCODE_X0 = 10, + TBLIDXB1_UNARY_OPCODE_Y0 = 10, + TBLIDXB2_UNARY_OPCODE_X0 = 11, + TBLIDXB2_UNARY_OPCODE_Y0 = 11, + TBLIDXB3_UNARY_OPCODE_X0 = 12, + TBLIDXB3_UNARY_OPCODE_Y0 = 12, + UNARY_RRR_0_OPCODE_X0 = 82, + UNARY_RRR_0_OPCODE_X1 = 53, + UNARY_RRR_1_OPCODE_Y0 = 3, + UNARY_RRR_1_OPCODE_Y1 = 3, + V1ADDI_IMM8_OPCODE_X0 = 8, + V1ADDI_IMM8_OPCODE_X1 = 33, + V1ADDUC_RRR_0_OPCODE_X0 = 83, + V1ADDUC_RRR_0_OPCODE_X1 = 54, + V1ADD_RRR_0_OPCODE_X0 = 84, + V1ADD_RRR_0_OPCODE_X1 = 55, + V1ADIFFU_RRR_0_OPCODE_X0 = 85, + V1AVGU_RRR_0_OPCODE_X0 = 86, + V1CMPEQI_IMM8_OPCODE_X0 = 9, + V1CMPEQI_IMM8_OPCODE_X1 = 34, + V1CMPEQ_RRR_0_OPCODE_X0 = 87, + V1CMPEQ_RRR_0_OPCODE_X1 = 56, + V1CMPLES_RRR_0_OPCODE_X0 = 88, + V1CMPLES_RRR_0_OPCODE_X1 = 57, + V1CMPLEU_RRR_0_OPCODE_X0 = 89, + V1CMPLEU_RRR_0_OPCODE_X1 = 58, + V1CMPLTSI_IMM8_OPCODE_X0 = 10, + V1CMPLTSI_IMM8_OPCODE_X1 = 35, + V1CMPLTS_RRR_0_OPCODE_X0 = 90, + V1CMPLTS_RRR_0_OPCODE_X1 = 59, + V1CMPLTUI_IMM8_OPCODE_X0 = 11, + V1CMPLTUI_IMM8_OPCODE_X1 = 36, + V1CMPLTU_RRR_0_OPCODE_X0 = 91, + V1CMPLTU_RRR_0_OPCODE_X1 = 60, + V1CMPNE_RRR_0_OPCODE_X0 = 92, + V1CMPNE_RRR_0_OPCODE_X1 = 61, + V1DDOTPUA_RRR_0_OPCODE_X0 = 161, + V1DDOTPUSA_RRR_0_OPCODE_X0 = 93, + V1DDOTPUS_RRR_0_OPCODE_X0 = 94, + V1DDOTPU_RRR_0_OPCODE_X0 = 162, + V1DOTPA_RRR_0_OPCODE_X0 = 95, + V1DOTPUA_RRR_0_OPCODE_X0 = 163, + V1DOTPUSA_RRR_0_OPCODE_X0 = 96, + V1DOTPUS_RRR_0_OPCODE_X0 = 97, + V1DOTPU_RRR_0_OPCODE_X0 = 164, + V1DOTP_RRR_0_OPCODE_X0 = 98, + V1INT_H_RRR_0_OPCODE_X0 = 99, + V1INT_H_RRR_0_OPCODE_X1 = 62, + V1INT_L_RRR_0_OPCODE_X0 = 100, + V1INT_L_RRR_0_OPCODE_X1 = 63, + V1MAXUI_IMM8_OPCODE_X0 = 12, + V1MAXUI_IMM8_OPCODE_X1 = 37, + V1MAXU_RRR_0_OPCODE_X0 = 101, + V1MAXU_RRR_0_OPCODE_X1 = 64, + V1MINUI_IMM8_OPCODE_X0 = 13, + V1MINUI_IMM8_OPCODE_X1 = 38, + V1MINU_RRR_0_OPCODE_X0 = 102, + V1MINU_RRR_0_OPCODE_X1 = 65, + V1MNZ_RRR_0_OPCODE_X0 = 103, + V1MNZ_RRR_0_OPCODE_X1 = 66, + V1MULTU_RRR_0_OPCODE_X0 = 104, + V1MULUS_RRR_0_OPCODE_X0 = 105, + V1MULU_RRR_0_OPCODE_X0 = 106, + V1MZ_RRR_0_OPCODE_X0 = 107, + V1MZ_RRR_0_OPCODE_X1 = 67, + V1SADAU_RRR_0_OPCODE_X0 = 108, + V1SADU_RRR_0_OPCODE_X0 = 109, + V1SHLI_SHIFT_OPCODE_X0 = 7, + V1SHLI_SHIFT_OPCODE_X1 = 7, + V1SHL_RRR_0_OPCODE_X0 = 110, + V1SHL_RRR_0_OPCODE_X1 = 68, + V1SHRSI_SHIFT_OPCODE_X0 = 8, + V1SHRSI_SHIFT_OPCODE_X1 = 8, + V1SHRS_RRR_0_OPCODE_X0 = 111, + V1SHRS_RRR_0_OPCODE_X1 = 69, + V1SHRUI_SHIFT_OPCODE_X0 = 9, + V1SHRUI_SHIFT_OPCODE_X1 = 9, + V1SHRU_RRR_0_OPCODE_X0 = 112, + V1SHRU_RRR_0_OPCODE_X1 = 70, + V1SUBUC_RRR_0_OPCODE_X0 = 113, + V1SUBUC_RRR_0_OPCODE_X1 = 71, + V1SUB_RRR_0_OPCODE_X0 = 114, + V1SUB_RRR_0_OPCODE_X1 = 72, + V2ADDI_IMM8_OPCODE_X0 = 14, + V2ADDI_IMM8_OPCODE_X1 = 39, + V2ADDSC_RRR_0_OPCODE_X0 = 115, + V2ADDSC_RRR_0_OPCODE_X1 = 73, + V2ADD_RRR_0_OPCODE_X0 = 116, + V2ADD_RRR_0_OPCODE_X1 = 74, + V2ADIFFS_RRR_0_OPCODE_X0 = 117, + V2AVGS_RRR_0_OPCODE_X0 = 118, + V2CMPEQI_IMM8_OPCODE_X0 = 15, + V2CMPEQI_IMM8_OPCODE_X1 = 40, + V2CMPEQ_RRR_0_OPCODE_X0 = 119, + V2CMPEQ_RRR_0_OPCODE_X1 = 75, + V2CMPLES_RRR_0_OPCODE_X0 = 120, + V2CMPLES_RRR_0_OPCODE_X1 = 76, + V2CMPLEU_RRR_0_OPCODE_X0 = 121, + V2CMPLEU_RRR_0_OPCODE_X1 = 77, + V2CMPLTSI_IMM8_OPCODE_X0 = 16, + V2CMPLTSI_IMM8_OPCODE_X1 = 41, + V2CMPLTS_RRR_0_OPCODE_X0 = 122, + V2CMPLTS_RRR_0_OPCODE_X1 = 78, + V2CMPLTUI_IMM8_OPCODE_X0 = 17, + V2CMPLTUI_IMM8_OPCODE_X1 = 42, + V2CMPLTU_RRR_0_OPCODE_X0 = 123, + V2CMPLTU_RRR_0_OPCODE_X1 = 79, + V2CMPNE_RRR_0_OPCODE_X0 = 124, + V2CMPNE_RRR_0_OPCODE_X1 = 80, + V2DOTPA_RRR_0_OPCODE_X0 = 125, + V2DOTP_RRR_0_OPCODE_X0 = 126, + V2INT_H_RRR_0_OPCODE_X0 = 127, + V2INT_H_RRR_0_OPCODE_X1 = 81, + V2INT_L_RRR_0_OPCODE_X0 = 128, + V2INT_L_RRR_0_OPCODE_X1 = 82, + V2MAXSI_IMM8_OPCODE_X0 = 18, + V2MAXSI_IMM8_OPCODE_X1 = 43, + V2MAXS_RRR_0_OPCODE_X0 = 129, + V2MAXS_RRR_0_OPCODE_X1 = 83, + V2MINSI_IMM8_OPCODE_X0 = 19, + V2MINSI_IMM8_OPCODE_X1 = 44, + V2MINS_RRR_0_OPCODE_X0 = 130, + V2MINS_RRR_0_OPCODE_X1 = 84, + V2MNZ_RRR_0_OPCODE_X0 = 131, + V2MNZ_RRR_0_OPCODE_X1 = 85, + V2MULFSC_RRR_0_OPCODE_X0 = 132, + V2MULS_RRR_0_OPCODE_X0 = 133, + V2MULTS_RRR_0_OPCODE_X0 = 134, + V2MZ_RRR_0_OPCODE_X0 = 135, + V2MZ_RRR_0_OPCODE_X1 = 86, + V2PACKH_RRR_0_OPCODE_X0 = 136, + V2PACKH_RRR_0_OPCODE_X1 = 87, + V2PACKL_RRR_0_OPCODE_X0 = 137, + V2PACKL_RRR_0_OPCODE_X1 = 88, + V2PACKUC_RRR_0_OPCODE_X0 = 138, + V2PACKUC_RRR_0_OPCODE_X1 = 89, + V2SADAS_RRR_0_OPCODE_X0 = 139, + V2SADAU_RRR_0_OPCODE_X0 = 140, + V2SADS_RRR_0_OPCODE_X0 = 141, + V2SADU_RRR_0_OPCODE_X0 = 142, + V2SHLI_SHIFT_OPCODE_X0 = 10, + V2SHLI_SHIFT_OPCODE_X1 = 10, + V2SHLSC_RRR_0_OPCODE_X0 = 143, + V2SHLSC_RRR_0_OPCODE_X1 = 90, + V2SHL_RRR_0_OPCODE_X0 = 144, + V2SHL_RRR_0_OPCODE_X1 = 91, + V2SHRSI_SHIFT_OPCODE_X0 = 11, + V2SHRSI_SHIFT_OPCODE_X1 = 11, + V2SHRS_RRR_0_OPCODE_X0 = 145, + V2SHRS_RRR_0_OPCODE_X1 = 92, + V2SHRUI_SHIFT_OPCODE_X0 = 12, + V2SHRUI_SHIFT_OPCODE_X1 = 12, + V2SHRU_RRR_0_OPCODE_X0 = 146, + V2SHRU_RRR_0_OPCODE_X1 = 93, + V2SUBSC_RRR_0_OPCODE_X0 = 147, + V2SUBSC_RRR_0_OPCODE_X1 = 94, + V2SUB_RRR_0_OPCODE_X0 = 148, + V2SUB_RRR_0_OPCODE_X1 = 95, + V4ADDSC_RRR_0_OPCODE_X0 = 149, + V4ADDSC_RRR_0_OPCODE_X1 = 96, + V4ADD_RRR_0_OPCODE_X0 = 150, + V4ADD_RRR_0_OPCODE_X1 = 97, + V4INT_H_RRR_0_OPCODE_X0 = 151, + V4INT_H_RRR_0_OPCODE_X1 = 98, + V4INT_L_RRR_0_OPCODE_X0 = 152, + V4INT_L_RRR_0_OPCODE_X1 = 99, + V4PACKSC_RRR_0_OPCODE_X0 = 153, + V4PACKSC_RRR_0_OPCODE_X1 = 100, + V4SHLSC_RRR_0_OPCODE_X0 = 154, + V4SHLSC_RRR_0_OPCODE_X1 = 101, + V4SHL_RRR_0_OPCODE_X0 = 155, + V4SHL_RRR_0_OPCODE_X1 = 102, + V4SHRS_RRR_0_OPCODE_X0 = 156, + V4SHRS_RRR_0_OPCODE_X1 = 103, + V4SHRU_RRR_0_OPCODE_X0 = 157, + V4SHRU_RRR_0_OPCODE_X1 = 104, + V4SUBSC_RRR_0_OPCODE_X0 = 158, + V4SUBSC_RRR_0_OPCODE_X1 = 105, + V4SUB_RRR_0_OPCODE_X0 = 159, + V4SUB_RRR_0_OPCODE_X1 = 106, + WH64_UNARY_OPCODE_X1 = 38, + XORI_IMM8_OPCODE_X0 = 20, + XORI_IMM8_OPCODE_X1 = 45, + XOR_RRR_0_OPCODE_X0 = 160, + XOR_RRR_0_OPCODE_X1 = 107, + XOR_RRR_5_OPCODE_Y0 = 3, + XOR_RRR_5_OPCODE_Y1 = 3 }; #endif /* !_TILE_OPCODE_CONSTANTS_H */ diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h index 3eb53525bf9..db93518fac0 100644 --- a/arch/tile/include/asm/page.h +++ b/arch/tile/include/asm/page.h @@ -16,7 +16,8 @@ #define _ASM_TILE_PAGE_H #include <linux/const.h> -#include <hv/pagesize.h> +#include <hv/hypervisor.h> +#include <arch/chip.h> /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ #define PAGE_SHIFT HV_LOG2_PAGE_SIZE_SMALL @@ -28,8 +29,6 @@ #define PAGE_MASK (~(PAGE_SIZE - 1)) #define HPAGE_MASK (~(HPAGE_SIZE - 1)) -#ifdef __KERNEL__ - /* * If the Kconfig doesn't specify, set a maximum zone order that * is enough so that we can create huge pages from small pages given @@ -39,9 +38,6 @@ #define CONFIG_FORCE_MAX_ZONEORDER (HPAGE_SHIFT - PAGE_SHIFT + 1) #endif -#include <hv/hypervisor.h> -#include <arch/chip.h> - #ifndef __ASSEMBLY__ #include <linux/types.h> @@ -91,6 +87,10 @@ typedef struct page *pgtable_t; /* Must be a macro since it is used to create constants. */ #define __pgprot(val) hv_pte(val) +/* Rarely-used initializers, typically with a "zero" value. */ +#define __pte(x) hv_pte(x) +#define __pgd(x) hv_pte(x) + static inline u64 pgprot_val(pgprot_t pgprot) { return hv_pte_val(pgprot); @@ -110,6 +110,8 @@ static inline u64 pgd_val(pgd_t pgd) typedef HV_PTE pmd_t; +#define __pmd(x) hv_pte(x) + static inline u64 pmd_val(pmd_t pmd) { return hv_pte_val(pmd); @@ -318,7 +320,7 @@ static inline int pfn_valid(unsigned long pfn) /* Provide as macros since these require some other headers included. */ #define page_to_pa(page) ((phys_addr_t)(page_to_pfn(page)) << PAGE_SHIFT) -#define virt_to_page(kaddr) pfn_to_page(kaddr_to_pfn(kaddr)) +#define virt_to_page(kaddr) pfn_to_page(kaddr_to_pfn((void *)(kaddr))) #define page_to_virt(page) pfn_to_kaddr(page_to_pfn(page)) struct mm_struct; @@ -331,6 +333,4 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); #include <asm-generic/memory_model.h> -#endif /* __KERNEL__ */ - #endif /* _ASM_TILE_PAGE_H */ diff --git a/arch/tile/include/asm/parport.h b/arch/tile/include/asm/parport.h new file mode 100644 index 00000000000..cf252af6459 --- /dev/null +++ b/arch/tile/include/asm/parport.h @@ -0,0 +1 @@ +#include <asm-generic/parport.h> diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h index c3fc458a0d3..7f03cefed1b 100644 --- a/arch/tile/include/asm/pci.h +++ b/arch/tile/include/asm/pci.h @@ -46,7 +46,8 @@ struct pci_controller { */ #define PCI_DMA_BUS_IS_PHYS 1 -int __init tile_pci_init(void); +int __devinit tile_pci_init(void); +int __devinit pcibios_init(void); void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} diff --git a/arch/tile/include/asm/pgtable_64.h b/arch/tile/include/asm/pgtable_64.h new file mode 100644 index 00000000000..fd80328523b --- /dev/null +++ b/arch/tile/include/asm/pgtable_64.h @@ -0,0 +1,175 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ASM_TILE_PGTABLE_64_H +#define _ASM_TILE_PGTABLE_64_H + +/* The level-0 page table breaks the address space into 32-bit chunks. */ +#define PGDIR_SHIFT HV_LOG2_L1_SPAN +#define PGDIR_SIZE HV_L1_SPAN +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define PTRS_PER_PGD HV_L0_ENTRIES +#define SIZEOF_PGD (PTRS_PER_PGD * sizeof(pgd_t)) + +/* + * The level-1 index is defined by the huge page size. A PMD is composed + * of PTRS_PER_PMD pgd_t's and is the middle level of the page table. + */ +#define PMD_SHIFT HV_LOG2_PAGE_SIZE_LARGE +#define PMD_SIZE HV_PAGE_SIZE_LARGE +#define PMD_MASK (~(PMD_SIZE-1)) +#define PTRS_PER_PMD (1 << (PGDIR_SHIFT - PMD_SHIFT)) +#define SIZEOF_PMD (PTRS_PER_PMD * sizeof(pmd_t)) + +/* + * The level-2 index is defined by the difference between the huge + * page size and the normal page size. A PTE is composed of + * PTRS_PER_PTE pte_t's and is the bottom level of the page table. + * Note that the hypervisor docs use PTE for what we call pte_t, so + * this nomenclature is somewhat confusing. + */ +#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) +#define SIZEOF_PTE (PTRS_PER_PTE * sizeof(pte_t)) + +/* + * Align the vmalloc area to an L2 page table, and leave a guard page + * at the beginning and end. The vmalloc code also puts in an internal + * guard page between each allocation. + */ +#define _VMALLOC_END HUGE_VMAP_BASE +#define VMALLOC_END (_VMALLOC_END - PAGE_SIZE) +#define VMALLOC_START (_VMALLOC_START + PAGE_SIZE) + +#define HUGE_VMAP_END (HUGE_VMAP_BASE + PGDIR_SIZE) + +#ifndef __ASSEMBLY__ + +/* We have no pud since we are a three-level page table. */ +#include <asm-generic/pgtable-nopud.h> + +static inline int pud_none(pud_t pud) +{ + return pud_val(pud) == 0; +} + +static inline int pud_present(pud_t pud) +{ + return pud_val(pud) & _PAGE_PRESENT; +} + +#define pmd_ERROR(e) \ + pr_err("%s:%d: bad pmd 0x%016llx.\n", __FILE__, __LINE__, pmd_val(e)) + +static inline void pud_clear(pud_t *pudp) +{ + __pte_clear(&pudp->pgd); +} + +static inline int pud_bad(pud_t pud) +{ + return ((pud_val(pud) & _PAGE_ALL) != _PAGE_TABLE); +} + +/* Return the page-table frame number (ptfn) that a pud_t points at. */ +#define pud_ptfn(pud) hv_pte_get_ptfn((pud).pgd) + +/* + * A given kernel pud_t maps to a kernel pmd_t table at a specific + * virtual address. Since kernel pmd_t tables can be aligned at + * sub-page granularity, this macro can return non-page-aligned + * pointers, despite its name. + */ +#define pud_page_vaddr(pud) \ + (__va((phys_addr_t)pud_ptfn(pud) << HV_LOG2_PAGE_TABLE_ALIGN)) + +/* + * A pud_t points to a pmd_t array. Since we can have multiple per + * page, we don't have a one-to-one mapping of pud_t's to pages. + */ +#define pud_page(pud) pfn_to_page(HV_PTFN_TO_PFN(pud_ptfn(pud))) + +static inline unsigned long pud_index(unsigned long address) +{ + return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1); +} + +#define pmd_offset(pud, address) \ + ((pmd_t *)pud_page_vaddr(*(pud)) + pmd_index(address)) + +static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval) +{ + set_pte(pmdp, pmdval); +} + +/* Create a pmd from a PTFN and pgprot. */ +static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot) +{ + return hv_pte_set_ptfn(prot, ptfn); +} + +/* Return the page-table frame number (ptfn) that a pmd_t points at. */ +static inline unsigned long pmd_ptfn(pmd_t pmd) +{ + return hv_pte_get_ptfn(pmd); +} + +static inline void pmd_clear(pmd_t *pmdp) +{ + __pte_clear(pmdp); +} + +/* Normalize an address to having the correct high bits set. */ +#define pgd_addr_normalize pgd_addr_normalize +static inline unsigned long pgd_addr_normalize(unsigned long addr) +{ + return ((long)addr << (CHIP_WORD_SIZE() - CHIP_VA_WIDTH())) >> + (CHIP_WORD_SIZE() - CHIP_VA_WIDTH()); +} + +/* We don't define any pgds for these addresses. */ +static inline int pgd_addr_invalid(unsigned long addr) +{ + return addr >= MEM_HV_START || + (addr > MEM_LOW_END && addr < MEM_HIGH_START); +} + +/* + * Use atomic instructions to provide atomicity against the hypervisor. + */ +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG +static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) +{ + return (__insn_fetchand(&ptep->val, ~HV_PTE_ACCESSED) >> + HV_PTE_INDEX_ACCESSED) & 0x1; +} + +#define __HAVE_ARCH_PTEP_SET_WRPROTECT +static inline void ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + __insn_fetchand(&ptep->val, ~HV_PTE_WRITABLE); +} + +#define __HAVE_ARCH_PTEP_GET_AND_CLEAR +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + return hv_pte(__insn_exch(&ptep->val, 0UL)); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_TILE_PGTABLE_64_H */ diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index e6889474038..34c1e01ffb5 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h @@ -215,6 +215,8 @@ static inline void release_thread(struct task_struct *dead_task) extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); +extern int do_work_pending(struct pt_regs *regs, u32 flags); + /* * Return saved (kernel) PC of a blocked thread. @@ -255,10 +257,6 @@ static inline void cpu_relax(void) barrier(); } -struct siginfo; -extern void arch_coredump_signal(struct siginfo *, struct pt_regs *); -#define arch_coredump_signal arch_coredump_signal - /* Info on this processor (see fs/proc/cpuinfo.c) */ struct seq_operations; extern const struct seq_operations cpuinfo_op; @@ -269,9 +267,6 @@ extern char chip_model[64]; /* Data on which physical memory controller corresponds to which NUMA node. */ extern int node_controller[]; -/* Do we dump information to the console when a user application crashes? */ -extern int show_crashinfo; - #if CHIP_HAS_CBOX_HOME_MAP() /* Does the heap allocator return hash-for-home pages by default? */ extern int hash_default; diff --git a/arch/tile/include/asm/serial.h b/arch/tile/include/asm/serial.h new file mode 100644 index 00000000000..a0cb0caff15 --- /dev/null +++ b/arch/tile/include/asm/serial.h @@ -0,0 +1 @@ +#include <asm-generic/serial.h> diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index 81d92a45cd4..1e1e616783e 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -28,6 +28,10 @@ struct pt_regs; int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); void do_signal(struct pt_regs *regs); +void signal_fault(const char *type, struct pt_regs *, + void __user *frame, int sig); +void trace_unhandled_signal(const char *type, struct pt_regs *regs, + unsigned long address, int signo); #endif #endif /* _ASM_TILE_SIGNAL_H */ diff --git a/arch/tile/include/asm/spinlock_64.h b/arch/tile/include/asm/spinlock_64.h new file mode 100644 index 00000000000..72be5904e02 --- /dev/null +++ b/arch/tile/include/asm/spinlock_64.h @@ -0,0 +1,161 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * 64-bit SMP ticket spinlocks, allowing only a single CPU anywhere + * (the type definitions are in asm/spinlock_types.h) + */ + +#ifndef _ASM_TILE_SPINLOCK_64_H +#define _ASM_TILE_SPINLOCK_64_H + +/* Shifts and masks for the various fields in "lock". */ +#define __ARCH_SPIN_CURRENT_SHIFT 17 +#define __ARCH_SPIN_NEXT_MASK 0x7fff +#define __ARCH_SPIN_NEXT_OVERFLOW 0x8000 + +/* + * Return the "current" portion of a ticket lock value, + * i.e. the number that currently owns the lock. + */ +static inline int arch_spin_current(u32 val) +{ + return val >> __ARCH_SPIN_CURRENT_SHIFT; +} + +/* + * Return the "next" portion of a ticket lock value, + * i.e. the number that the next task to try to acquire the lock will get. + */ +static inline int arch_spin_next(u32 val) +{ + return val & __ARCH_SPIN_NEXT_MASK; +} + +/* The lock is locked if a task would have to wait to get it. */ +static inline int arch_spin_is_locked(arch_spinlock_t *lock) +{ + u32 val = lock->lock; + return arch_spin_current(val) != arch_spin_next(val); +} + +/* Bump the current ticket so the next task owns the lock. */ +static inline void arch_spin_unlock(arch_spinlock_t *lock) +{ + wmb(); /* guarantee anything modified under the lock is visible */ + __insn_fetchadd4(&lock->lock, 1U << __ARCH_SPIN_CURRENT_SHIFT); +} + +void arch_spin_unlock_wait(arch_spinlock_t *lock); + +void arch_spin_lock_slow(arch_spinlock_t *lock, u32 val); + +/* Grab the "next" ticket number and bump it atomically. + * If the current ticket is not ours, go to the slow path. + * We also take the slow path if the "next" value overflows. + */ +static inline void arch_spin_lock(arch_spinlock_t *lock) +{ + u32 val = __insn_fetchadd4(&lock->lock, 1); + u32 ticket = val & (__ARCH_SPIN_NEXT_MASK | __ARCH_SPIN_NEXT_OVERFLOW); + if (unlikely(arch_spin_current(val) != ticket)) + arch_spin_lock_slow(lock, ticket); +} + +/* Try to get the lock, and return whether we succeeded. */ +int arch_spin_trylock(arch_spinlock_t *lock); + +/* We cannot take an interrupt after getting a ticket, so don't enable them. */ +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * We use fetchadd() for readers, and fetchor() with the sign bit + * for writers. + */ + +#define __WRITE_LOCK_BIT (1 << 31) + +static inline int arch_write_val_locked(int val) +{ + return val < 0; /* Optimize "val & __WRITE_LOCK_BIT". */ +} + +/** + * read_can_lock - would read_trylock() succeed? + * @lock: the rwlock in question. + */ +static inline int arch_read_can_lock(arch_rwlock_t *rw) +{ + return !arch_write_val_locked(rw->lock); +} + +/** + * write_can_lock - would write_trylock() succeed? + * @lock: the rwlock in question. + */ +static inline int arch_write_can_lock(arch_rwlock_t *rw) +{ + return rw->lock == 0; +} + +extern void __read_lock_failed(arch_rwlock_t *rw); + +static inline void arch_read_lock(arch_rwlock_t *rw) +{ + u32 val = __insn_fetchaddgez4(&rw->lock, 1); + if (unlikely(arch_write_val_locked(val))) + __read_lock_failed(rw); +} + +extern void __write_lock_failed(arch_rwlock_t *rw, u32 val); + +static inline void arch_write_lock(arch_rwlock_t *rw) +{ + u32 val = __insn_fetchor4(&rw->lock, __WRITE_LOCK_BIT); + if (unlikely(val != 0)) + __write_lock_failed(rw, val); +} + +static inline void arch_read_unlock(arch_rwlock_t *rw) +{ + __insn_mf(); + __insn_fetchadd4(&rw->lock, -1); +} + +static inline void arch_write_unlock(arch_rwlock_t *rw) +{ + __insn_mf(); + rw->lock = 0; +} + +static inline int arch_read_trylock(arch_rwlock_t *rw) +{ + return !arch_write_val_locked(__insn_fetchaddgez4(&rw->lock, 1)); +} + +static inline int arch_write_trylock(arch_rwlock_t *rw) +{ + u32 val = __insn_fetchor4(&rw->lock, __WRITE_LOCK_BIT); + if (likely(val == 0)) + return 1; + if (!arch_write_val_locked(val)) + __insn_fetchand4(&rw->lock, ~__WRITE_LOCK_BIT); + return 0; +} + +#define arch_read_lock_flags(lock, flags) arch_read_lock(lock) +#define arch_write_lock_flags(lock, flags) arch_write_lock(lock) + +#endif /* _ASM_TILE_SPINLOCK_64_H */ diff --git a/arch/tile/include/asm/stat.h b/arch/tile/include/asm/stat.h index b16e5db8f0e..c0db34d56be 100644 --- a/arch/tile/include/asm/stat.h +++ b/arch/tile/include/asm/stat.h @@ -1,4 +1,4 @@ -#ifdef CONFIG_COMPAT +#if defined(__KERNEL__) && defined(CONFIG_COMPAT) #define __ARCH_WANT_STAT64 /* Used for compat_sys_stat64() etc. */ #endif #include <asm-generic/stat.h> diff --git a/arch/tile/include/asm/swab.h b/arch/tile/include/asm/swab.h index 25c686a00f1..7c37b38f6c8 100644 --- a/arch/tile/include/asm/swab.h +++ b/arch/tile/include/asm/swab.h @@ -18,12 +18,6 @@ /* Tile gcc is always >= 4.3.0, so we use __builtin_bswap. */ #define __arch_swab32(x) __builtin_bswap32(x) #define __arch_swab64(x) __builtin_bswap64(x) - -/* Use the variant that is natural for the wordsize. */ -#ifdef CONFIG_64BIT -#define __arch_swab16(x) (__builtin_bswap64(x) >> 48) -#else #define __arch_swab16(x) (__builtin_bswap32(x) >> 16) -#endif #endif /* _ASM_TILE_SWAB_H */ diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h index 3405b52853b..bc4f562bd45 100644 --- a/arch/tile/include/asm/thread_info.h +++ b/arch/tile/include/asm/thread_info.h @@ -125,6 +125,7 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti, #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ #define TIF_SECCOMP 6 /* secure computing */ #define TIF_MEMDIE 7 /* OOM killer at work */ +#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) @@ -134,10 +135,12 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti, #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1<<TIF_SECCOMP) #define _TIF_MEMDIE (1<<TIF_MEMDIE) +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) /* Work to do on any return to user space. */ #define _TIF_ALLWORK_MASK \ - (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|_TIF_ASYNC_TLB) + (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|\ + _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME) /* * Thread-synchronous status. diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h index 343172d422a..6fdd0c86019 100644 --- a/arch/tile/include/asm/topology.h +++ b/arch/tile/include/asm/topology.h @@ -44,25 +44,64 @@ static inline const struct cpumask *cpumask_of_node(int node) /* For now, use numa node -1 for global allocation. */ #define pcibus_to_node(bus) ((void)(bus), -1) +/* + * TILE architecture has many cores integrated in one processor, so we need + * setup bigger balance_interval for both CPU/NODE scheduling domains to + * reduce process scheduling costs. + */ + +/* sched_domains SD_CPU_INIT for TILE architecture */ +#define SD_CPU_INIT (struct sched_domain) { \ + .min_interval = 4, \ + .max_interval = 128, \ + .busy_factor = 64, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .busy_idx = 2, \ + .idle_idx = 1, \ + .newidle_idx = 0, \ + .wake_idx = 0, \ + .forkexec_idx = 0, \ + \ + .flags = 1*SD_LOAD_BALANCE \ + | 1*SD_BALANCE_NEWIDLE \ + | 1*SD_BALANCE_EXEC \ + | 1*SD_BALANCE_FORK \ + | 0*SD_BALANCE_WAKE \ + | 0*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ + | 0*SD_SHARE_CPUPOWER \ + | 0*SD_SHARE_PKG_RESOURCES \ + | 0*SD_SERIALIZE \ + , \ + .last_balance = jiffies, \ + .balance_interval = 32, \ +} + /* sched_domains SD_NODE_INIT for TILE architecture */ -#define SD_NODE_INIT (struct sched_domain) { \ - .min_interval = 8, \ - .max_interval = 32, \ - .busy_factor = 32, \ - .imbalance_pct = 125, \ - .cache_nice_tries = 1, \ - .busy_idx = 3, \ - .idle_idx = 1, \ - .newidle_idx = 2, \ - .wake_idx = 1, \ - .flags = SD_LOAD_BALANCE \ - | SD_BALANCE_NEWIDLE \ - | SD_BALANCE_EXEC \ - | SD_BALANCE_FORK \ - | SD_WAKE_AFFINE \ - | SD_SERIALIZE, \ - .last_balance = jiffies, \ - .balance_interval = 1, \ +#define SD_NODE_INIT (struct sched_domain) { \ + .min_interval = 16, \ + .max_interval = 512, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .busy_idx = 3, \ + .idle_idx = 1, \ + .newidle_idx = 2, \ + .wake_idx = 1, \ + .flags = 1*SD_LOAD_BALANCE \ + | 1*SD_BALANCE_NEWIDLE \ + | 1*SD_BALANCE_EXEC \ + | 1*SD_BALANCE_FORK \ + | 0*SD_BALANCE_WAKE \ + | 0*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ + | 0*SD_SHARE_CPUPOWER \ + | 0*SD_SHARE_PKG_RESOURCES \ + | 1*SD_SERIALIZE \ + , \ + .last_balance = jiffies, \ + .balance_interval = 128, \ } /* By definition, we create nodes based on online memory. */ diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h index d06e35f5720..5f20f920f93 100644 --- a/arch/tile/include/asm/traps.h +++ b/arch/tile/include/asm/traps.h @@ -15,10 +15,14 @@ #ifndef _ASM_TILE_TRAPS_H #define _ASM_TILE_TRAPS_H +#include <arch/chip.h> + /* mm/fault.c */ void do_page_fault(struct pt_regs *, int fault_num, unsigned long address, unsigned long write); +#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() void do_async_page_fault(struct pt_regs *); +#endif #ifndef __tilegx__ /* diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h index b35c2db7119..f70bf1c541f 100644 --- a/arch/tile/include/asm/unistd.h +++ b/arch/tile/include/asm/unistd.h @@ -15,7 +15,7 @@ #if !defined(_ASM_TILE_UNISTD_H) || defined(__SYSCALL) #define _ASM_TILE_UNISTD_H -#ifndef __LP64__ +#if !defined(__LP64__) || defined(__SYSCALL_COMPAT) /* Use the flavor of this syscall that matches the 32-bit API better. */ #define __ARCH_WANT_SYNC_FILE_RANGE2 #endif diff --git a/arch/tile/include/hv/pagesize.h b/arch/tile/include/asm/vga.h index 58bed114fed..7b46e754d61 100644 --- a/arch/tile/include/hv/pagesize.h +++ b/arch/tile/include/asm/vga.h @@ -10,23 +10,30 @@ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for * more details. + * + * Access to VGA videoram. */ -/** - * @file pagesize.h - */ +#ifndef _ASM_TILE_VGA_H +#define _ASM_TILE_VGA_H -#ifndef _HV_PAGESIZE_H -#define _HV_PAGESIZE_H +#include <asm/io.h> -/** The log2 of the size of small pages, in bytes. This value should - * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). - */ -#define HV_LOG2_PAGE_SIZE_SMALL 16 +#define VT_BUF_HAVE_RW -/** The log2 of the size of large pages, in bytes. This value should be - * verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). - */ -#define HV_LOG2_PAGE_SIZE_LARGE 24 +static inline void scr_writew(u16 val, volatile u16 *addr) +{ + __raw_writew(val, (volatile u16 __iomem *) addr); +} + +static inline u16 scr_readw(volatile const u16 *addr) +{ + return __raw_readw((volatile const u16 __iomem *) addr); +} + +#define vga_readb(a) readb((u8 __iomem *)(a)) +#define vga_writeb(v,a) writeb(v, (u8 __iomem *)(a)) + +#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(x, s)) -#endif /* _HV_PAGESIZE_H */ +#endif diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h index ee41bca4c8c..72ec1e972f1 100644 --- a/arch/tile/include/hv/hypervisor.h +++ b/arch/tile/include/hv/hypervisor.h @@ -22,8 +22,6 @@ #include <arch/chip.h> -#include <hv/pagesize.h> - /* Linux builds want unsigned long constants, but assembler wants numbers */ #ifdef __ASSEMBLER__ /** One, for assembler */ @@ -44,11 +42,21 @@ */ #define HV_L1_SPAN (__HV_SIZE_ONE << HV_LOG2_L1_SPAN) +/** The log2 of the size of small pages, in bytes. This value should + * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). + */ +#define HV_LOG2_PAGE_SIZE_SMALL 16 + /** The size of small pages, in bytes. This value should be verified * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). */ #define HV_PAGE_SIZE_SMALL (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_SMALL) +/** The log2 of the size of large pages, in bytes. This value should be + * verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). + */ +#define HV_LOG2_PAGE_SIZE_LARGE 24 + /** The size of large pages, in bytes. This value should be verified * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). */ diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index 55a6a74974b..1dc71eabfc5 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c @@ -14,19 +14,11 @@ #include <linux/kernel.h> #include <linux/string.h> - #include <asm/backtrace.h> - -#include <arch/chip.h> - #include <asm/opcode-tile.h> +#include <arch/abi.h> - -#define TREG_SP 54 -#define TREG_LR 55 - - -#if TILE_CHIP >= 10 +#ifdef __tilegx__ #define tile_bundle_bits tilegx_bundle_bits #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES @@ -47,7 +39,7 @@ typedef long long bt_int_reg_t; typedef int bt_int_reg_t; #endif -/** A decoded bundle used for backtracer analysis. */ +/* A decoded bundle used for backtracer analysis. */ struct BacktraceBundle { tile_bundle_bits bits; int num_insns; @@ -56,23 +48,7 @@ struct BacktraceBundle { }; -/* This implementation only makes sense for native tools. */ -/** Default function to read memory. */ -static bool bt_read_memory(void *result, VirtualAddress addr, - unsigned int size, void *extra) -{ - /* FIXME: this should do some horrible signal stuff to catch - * SEGV cleanly and fail. - * - * Or else the caller should do the setjmp for efficiency. - */ - - memcpy(result, (const void *)addr, size); - return true; -} - - -/** Locates an instruction inside the given bundle that +/* Locates an instruction inside the given bundle that * has the specified mnemonic, and whose first 'num_operands_to_match' * operands exactly match those in 'operand_values'. */ @@ -107,13 +83,13 @@ static const struct tile_decoded_instruction *find_matching_insn( return NULL; } -/** Does this bundle contain an 'iret' instruction? */ +/* Does this bundle contain an 'iret' instruction? */ static inline bool bt_has_iret(const struct BacktraceBundle *bundle) { return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL; } -/** Does this bundle contain an 'addi sp, sp, OFFSET' or +/* Does this bundle contain an 'addi sp, sp, OFFSET' or * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET? */ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) @@ -124,7 +100,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); if (insn == NULL) insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); -#if TILE_CHIP >= 10 +#ifdef __tilegx__ if (insn == NULL) insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2); if (insn == NULL) @@ -137,7 +113,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) return true; } -/** Does this bundle contain any 'info OP' or 'infol OP' +/* Does this bundle contain any 'info OP' or 'infol OP' * instruction, and if so, what are their OP? Note that OP is interpreted * as an unsigned value by this code since that's what the caller wants. * Returns the number of info ops found. @@ -161,7 +137,7 @@ static int bt_get_info_ops(const struct BacktraceBundle *bundle, return num_ops; } -/** Does this bundle contain a jrp instruction, and if so, to which +/* Does this bundle contain a jrp instruction, and if so, to which * register is it jumping? */ static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) @@ -175,7 +151,7 @@ static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) return true; } -/** Does this bundle modify the specified register in any way? */ +/* Does this bundle modify the specified register in any way? */ static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg) { int i, j; @@ -195,34 +171,34 @@ static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg) return false; } -/** Does this bundle modify sp? */ +/* Does this bundle modify sp? */ static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle) { return bt_modifies_reg(bundle, TREG_SP); } -/** Does this bundle modify lr? */ +/* Does this bundle modify lr? */ static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle) { return bt_modifies_reg(bundle, TREG_LR); } -/** Does this bundle contain the instruction 'move fp, sp'? */ +/* Does this bundle contain the instruction 'move fp, sp'? */ static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle) { static const int vals[2] = { 52, TREG_SP }; return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; } -/** Does this bundle contain a store of lr to sp? */ +/* Does this bundle contain a store of lr to sp? */ static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) { static const int vals[2] = { TREG_SP, TREG_LR }; return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL; } -#if TILE_CHIP >= 10 -/** Track moveli values placed into registers. */ +#ifdef __tilegx__ +/* Track moveli values placed into registers. */ static inline void bt_update_moveli(const struct BacktraceBundle *bundle, int moveli_args[]) { @@ -238,7 +214,7 @@ static inline void bt_update_moveli(const struct BacktraceBundle *bundle, } } -/** Does this bundle contain an 'add sp, sp, reg' instruction +/* Does this bundle contain an 'add sp, sp, reg' instruction * from a register that we saw a moveli into, and if so, what * is the value in the register? */ @@ -260,11 +236,11 @@ static bool bt_has_add_sp(const struct BacktraceBundle *bundle, int *adjust, } #endif -/** Locates the caller's PC and SP for a program starting at the +/* Locates the caller's PC and SP for a program starting at the * given address. */ static void find_caller_pc_and_caller_sp(CallerLocation *location, - const VirtualAddress start_pc, + const unsigned long start_pc, BacktraceMemoryReader read_memory_func, void *read_memory_func_extra) { @@ -288,9 +264,9 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, tile_bundle_bits prefetched_bundles[32]; int num_bundles_prefetched = 0; int next_bundle = 0; - VirtualAddress pc; + unsigned long pc; -#if TILE_CHIP >= 10 +#ifdef __tilegx__ /* Naively try to track moveli values to support addx for -m32. */ int moveli_args[TILEGX_NUM_REGISTERS] = { 0 }; #endif @@ -369,10 +345,6 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, /* Weird; reserved value, ignore it. */ continue; } - if (info_operand & ENTRY_POINT_INFO_OP) { - /* This info op is ignored by the backtracer. */ - continue; - } /* Skip info ops which are not in the * "one_ago" mode we want right now. @@ -453,7 +425,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, if (!sp_determined) { int adjust; if (bt_has_addi_sp(&bundle, &adjust) -#if TILE_CHIP >= 10 +#ifdef __tilegx__ || bt_has_add_sp(&bundle, &adjust, moveli_args) #endif ) { @@ -504,7 +476,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, } } -#if TILE_CHIP >= 10 +#ifdef __tilegx__ /* Track moveli arguments for -m32 mode. */ bt_update_moveli(&bundle, moveli_args); #endif @@ -546,18 +518,26 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, } } +/* Initializes a backtracer to start from the given location. + * + * If the frame pointer cannot be determined it is set to -1. + * + * state: The state to be filled in. + * read_memory_func: A callback that reads memory. + * read_memory_func_extra: An arbitrary argument to read_memory_func. + * pc: The current PC. + * lr: The current value of the 'lr' register. + * sp: The current value of the 'sp' register. + * r52: The current value of the 'r52' register. + */ void backtrace_init(BacktraceIterator *state, BacktraceMemoryReader read_memory_func, void *read_memory_func_extra, - VirtualAddress pc, VirtualAddress lr, - VirtualAddress sp, VirtualAddress r52) + unsigned long pc, unsigned long lr, + unsigned long sp, unsigned long r52) { CallerLocation location; - VirtualAddress fp, initial_frame_caller_pc; - - if (read_memory_func == NULL) { - read_memory_func = bt_read_memory; - } + unsigned long fp, initial_frame_caller_pc; /* Find out where we are in the initial frame. */ find_caller_pc_and_caller_sp(&location, pc, @@ -630,12 +610,15 @@ void backtrace_init(BacktraceIterator *state, /* Handle the case where the register holds more bits than the VA. */ static bool valid_addr_reg(bt_int_reg_t reg) { - return ((VirtualAddress)reg == reg); + return ((unsigned long)reg == reg); } +/* Advances the backtracing state to the calling frame, returning + * true iff successful. + */ bool backtrace_next(BacktraceIterator *state) { - VirtualAddress next_fp, next_pc; + unsigned long next_fp, next_pc; bt_int_reg_t next_frame[2]; if (state->fp == -1) { diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index dbc213adf5e..bf5e9d70266 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c @@ -135,26 +135,15 @@ long tile_compat_sys_msgrcv(int msqid, /* Provide the compat syscall number to call mapping. */ #undef __SYSCALL -#define __SYSCALL(nr, call) [nr] = (compat_##call), +#define __SYSCALL(nr, call) [nr] = (call), /* The generic versions of these don't work for Tile. */ #define compat_sys_msgrcv tile_compat_sys_msgrcv #define compat_sys_msgsnd tile_compat_sys_msgsnd /* See comments in sys.c */ -#define compat_sys_fadvise64 sys32_fadvise64 #define compat_sys_fadvise64_64 sys32_fadvise64_64 #define compat_sys_readahead sys32_readahead -#define compat_sys_sync_file_range compat_sys_sync_file_range2 - -/* We leverage the "struct stat64" type for 32-bit time_t/nsec. */ -#define compat_sys_stat64 sys_stat64 -#define compat_sys_lstat64 sys_lstat64 -#define compat_sys_fstat64 sys_fstat64 -#define compat_sys_fstatat64 sys_fstatat64 - -/* The native sys_ptrace dynamically handles compat binaries. */ -#define compat_sys_ptrace sys_ptrace /* Call the trampolines to manage pt_regs where necessary. */ #define compat_sys_execve _compat_sys_execve diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index dbb0dfc7bec..a7869ad6277 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -317,7 +317,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) return 0; badframe: - force_sig(SIGSEGV, current); + signal_fault("bad sigreturn frame", regs, frame, 0); return 0; } @@ -431,6 +431,6 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sigsegv(sig, current); + signal_fault("bad setup frame", regs, frame, sig); return -EFAULT; } diff --git a/arch/tile/kernel/futex_64.S b/arch/tile/kernel/futex_64.S new file mode 100644 index 00000000000..f465d1eda20 --- /dev/null +++ b/arch/tile/kernel/futex_64.S @@ -0,0 +1,55 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Atomically access user memory, but use MMU to avoid propagating + * kernel exceptions. + */ + +#include <linux/linkage.h> +#include <asm/errno.h> +#include <asm/futex.h> +#include <asm/page.h> +#include <asm/processor.h> + +/* + * Provide a set of atomic memory operations supporting <asm/futex.h>. + * + * r0: user address to manipulate + * r1: new value to write, or for cmpxchg, old value to compare against + * r2: (cmpxchg only) new value to write + * + * Return __get_user struct, r0 with value, r1 with error. + */ +#define FUTEX_OP(name, ...) \ +STD_ENTRY(futex_##name) \ + __VA_ARGS__; \ + { \ + move r1, zero; \ + jrp lr \ + }; \ + STD_ENDPROC(futex_##name); \ + .pushsection __ex_table,"a"; \ + .quad 1b, get_user_fault; \ + .popsection + + .pushsection .fixup,"ax" +get_user_fault: + { movei r1, -EFAULT; jrp lr } + ENDPROC(get_user_fault) + .popsection + +FUTEX_OP(cmpxchg, mtspr CMPEXCH_VALUE, r1; 1: cmpexch4 r0, r0, r2) +FUTEX_OP(set, 1: exch4 r0, r0, r1) +FUTEX_OP(add, 1: fetchadd4 r0, r0, r1) +FUTEX_OP(or, 1: fetchor4 r0, r0, r1) +FUTEX_OP(andn, nor r1, r1, zero; 1: fetchand4 r0, r0, r1) diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c index e910530436e..3bddef710de 100644 --- a/arch/tile/kernel/hardwall.c +++ b/arch/tile/kernel/hardwall.c @@ -268,12 +268,10 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num) found_processes = 0; list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { BUG_ON(p->thread.hardwall != rect); - if (p->sighand) { + if (!(p->flags & PF_EXITING)) { found_processes = 1; pr_notice("hardwall: killing %d\n", p->pid); - spin_lock(&p->sighand->siglock); - __group_send_sig_info(info.si_signo, &info, p); - spin_unlock(&p->sighand->siglock); + do_send_sig_info(info.si_signo, &info, p, false); } } if (!found_processes) diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S new file mode 100644 index 00000000000..6bc3a932fe4 --- /dev/null +++ b/arch/tile/kernel/head_64.S @@ -0,0 +1,269 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * TILE startup code. + */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/thread_info.h> +#include <asm/processor.h> +#include <asm/asm-offsets.h> +#include <hv/hypervisor.h> +#include <arch/chip.h> +#include <arch/spr_def.h> + +/* + * This module contains the entry code for kernel images. It performs the + * minimal setup needed to call the generic C routines. + */ + + __HEAD +ENTRY(_start) + /* Notify the hypervisor of what version of the API we want */ + { + movei r1, TILE_CHIP + movei r2, TILE_CHIP_REV + } + { + moveli r0, _HV_VERSION + jal hv_init + } + /* Get a reasonable default ASID in r0 */ + { + move r0, zero + jal hv_inquire_asid + } + + /* + * Install the default page table. The relocation required to + * statically define the table is a bit too complex, so we have + * to plug in the pointer from the L0 to the L1 table by hand. + * We only do this on the first cpu to boot, though, since the + * other CPUs should see a properly-constructed page table. + */ + { + v4int_l r2, zero, r0 /* ASID for hv_install_context */ + moveli r4, hw1_last(swapper_pgprot - PAGE_OFFSET) + } + { + shl16insli r4, r4, hw0(swapper_pgprot - PAGE_OFFSET) + } + { + ld r1, r4 /* access_pte for hv_install_context */ + } + { + moveli r0, hw1_last(.Lsv_data_pmd - PAGE_OFFSET) + moveli r6, hw1_last(temp_data_pmd - PAGE_OFFSET) + } + { + /* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */ + bfextu r7, r1, HV_PTE_INDEX_GLOBAL, HV_PTE_INDEX_GLOBAL + inv r4 + } + bnez r7, .Lno_write + { + shl16insli r0, r0, hw0(.Lsv_data_pmd - PAGE_OFFSET) + shl16insli r6, r6, hw0(temp_data_pmd - PAGE_OFFSET) + } + { + /* Cut off the low bits of the PT address. */ + shrui r6, r6, HV_LOG2_PAGE_TABLE_ALIGN + /* Start with our access pte. */ + move r5, r1 + } + { + /* Stuff the address into the page table pointer slot of the PTE. */ + bfins r5, r6, HV_PTE_INDEX_PTFN, \ + HV_PTE_INDEX_PTFN + HV_PTE_PTFN_BITS - 1 + } + { + /* Store the L0 data PTE. */ + st r0, r5 + addli r6, r6, (temp_code_pmd - temp_data_pmd) >> \ + HV_LOG2_PAGE_TABLE_ALIGN + } + { + addli r0, r0, .Lsv_code_pmd - .Lsv_data_pmd + bfins r5, r6, HV_PTE_INDEX_PTFN, \ + HV_PTE_INDEX_PTFN + HV_PTE_PTFN_BITS - 1 + } + /* Store the L0 code PTE. */ + st r0, r5 + +.Lno_write: + moveli lr, hw2_last(1f) + { + shl16insli lr, lr, hw1(1f) + moveli r0, hw1_last(swapper_pg_dir - PAGE_OFFSET) + } + { + shl16insli lr, lr, hw0(1f) + shl16insli r0, r0, hw0(swapper_pg_dir - PAGE_OFFSET) + } + { + move r3, zero + j hv_install_context + } +1: + + /* Install the interrupt base. */ + moveli r0, hw2_last(MEM_SV_START) + shl16insli r0, r0, hw1(MEM_SV_START) + shl16insli r0, r0, hw0(MEM_SV_START) + mtspr SPR_INTERRUPT_VECTOR_BASE_K, r0 + + /* + * Get our processor number and save it away in SAVE_K_0. + * Extract stuff from the topology structure: r4 = y, r6 = x, + * r5 = width. FIXME: consider whether we want to just make these + * 64-bit values (and if so fix smp_topology write below, too). + */ + jal hv_inquire_topology + { + v4int_l r5, zero, r1 /* r5 = width */ + shrui r4, r0, 32 /* r4 = y */ + } + { + v4int_l r6, zero, r0 /* r6 = x */ + mul_lu_lu r4, r4, r5 + } + { + add r4, r4, r6 /* r4 == cpu == y*width + x */ + } + +#ifdef CONFIG_SMP + /* + * Load up our per-cpu offset. When the first (master) tile + * boots, this value is still zero, so we will load boot_pc + * with start_kernel, and boot_sp with init_stack + THREAD_SIZE. + * The master tile initializes the per-cpu offset array, so that + * when subsequent (secondary) tiles boot, they will instead load + * from their per-cpu versions of boot_sp and boot_pc. + */ + moveli r5, hw2_last(__per_cpu_offset) + shl16insli r5, r5, hw1(__per_cpu_offset) + shl16insli r5, r5, hw0(__per_cpu_offset) + shl3add r5, r4, r5 + ld r5, r5 + bnez r5, 1f + + /* + * Save the width and height to the smp_topology variable + * for later use. + */ + moveli r0, hw2_last(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) + shl16insli r0, r0, hw1(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) + shl16insli r0, r0, hw0(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) + st r0, r1 +1: +#else + move r5, zero +#endif + + /* Load and go with the correct pc and sp. */ + { + moveli r1, hw2_last(boot_sp) + moveli r0, hw2_last(boot_pc) + } + { + shl16insli r1, r1, hw1(boot_sp) + shl16insli r0, r0, hw1(boot_pc) + } + { + shl16insli r1, r1, hw0(boot_sp) + shl16insli r0, r0, hw0(boot_pc) + } + { + add r1, r1, r5 + add r0, r0, r5 + } + ld r0, r0 + ld sp, r1 + or r4, sp, r4 + mtspr SPR_SYSTEM_SAVE_K_0, r4 /* save ksp0 + cpu */ + addi sp, sp, -STACK_TOP_DELTA + { + move lr, zero /* stop backtraces in the called function */ + jr r0 + } + ENDPROC(_start) + +__PAGE_ALIGNED_BSS + .align PAGE_SIZE +ENTRY(empty_zero_page) + .fill PAGE_SIZE,1,0 + END(empty_zero_page) + + .macro PTE cpa, bits1 + .quad HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED |\ + HV_PTE_GLOBAL | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |\ + (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) + .endm + +__PAGE_ALIGNED_DATA + .align PAGE_SIZE +ENTRY(swapper_pg_dir) + .org swapper_pg_dir + HV_L0_INDEX(PAGE_OFFSET) * HV_PTE_SIZE +.Lsv_data_pmd: + .quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */ + .org swapper_pg_dir + HV_L0_INDEX(MEM_SV_START) * HV_PTE_SIZE +.Lsv_code_pmd: + .quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */ + .org swapper_pg_dir + HV_L0_SIZE + END(swapper_pg_dir) + + .align HV_PAGE_TABLE_ALIGN +ENTRY(temp_data_pmd) + /* + * We fill the PAGE_OFFSET pmd with huge pages with + * VA = PA + PAGE_OFFSET. We remap things with more precise access + * permissions later. + */ + .set addr, 0 + .rept HV_L1_ENTRIES + PTE addr, HV_PTE_READABLE | HV_PTE_WRITABLE + .set addr, addr + HV_PAGE_SIZE_LARGE + .endr + .org temp_data_pmd + HV_L1_SIZE + END(temp_data_pmd) + + .align HV_PAGE_TABLE_ALIGN +ENTRY(temp_code_pmd) + /* + * We fill the MEM_SV_START pmd with huge pages with + * VA = PA + PAGE_OFFSET. We remap things with more precise access + * permissions later. + */ + .set addr, 0 + .rept HV_L1_ENTRIES + PTE addr, HV_PTE_READABLE | HV_PTE_EXECUTABLE + .set addr, addr + HV_PAGE_SIZE_LARGE + .endr + .org temp_code_pmd + HV_L1_SIZE + END(temp_code_pmd) + + /* + * Isolate swapper_pgprot to its own cache line, since each cpu + * starting up will read it using VA-is-PA and local homing. + * This would otherwise likely conflict with other data on the cache + * line, once we have set its permanent home in the page tables. + */ + __INITDATA + .align CHIP_L2_LINE_SIZE() +ENTRY(swapper_pgprot) + .quad HV_PTE_PRESENT | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) + .align CHIP_L2_LINE_SIZE() + END(swapper_pgprot) diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index fffcfa6b3a6..72ade79b621 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -851,14 +851,27 @@ STD_ENTRY(interrupt_return) /* Check to see if there is any work to do before returning to user. */ { addi r29, r32, THREAD_INFO_FLAGS_OFFSET - moveli r28, lo16(_TIF_ALLWORK_MASK) + moveli r1, lo16(_TIF_ALLWORK_MASK) } { lw r29, r29 - auli r28, r28, ha16(_TIF_ALLWORK_MASK) + auli r1, r1, ha16(_TIF_ALLWORK_MASK) } - and r28, r29, r28 - bnz r28, .Lwork_pending + and r1, r29, r1 + bzt r1, .Lrestore_all + + /* + * Make sure we have all the registers saved for signal + * handling or single-step. Call out to C code to figure out + * exactly what we need to do for each flag bit, then if + * necessary, reload the flags and recheck. + */ + push_extra_callee_saves r0 + { + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + jal do_work_pending + } + bnz r0, .Lresume_userspace /* * In the NMI case we @@ -1099,99 +1112,6 @@ STD_ENTRY(interrupt_return) pop_reg r50 pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) j .Lcontinue_restore_regs - -.Lwork_pending: - /* Mask the reschedule flag */ - andi r28, r29, _TIF_NEED_RESCHED - - { - /* - * If the NEED_RESCHED flag is called, we call schedule(), which - * may drop this context right here and go do something else. - * On return, jump back to .Lresume_userspace and recheck. - */ - bz r28, .Lasync_tlb - - /* Mask the async-tlb flag */ - andi r28, r29, _TIF_ASYNC_TLB - } - - jal schedule - FEEDBACK_REENTER(interrupt_return) - - /* Reload the flags and check again */ - j .Lresume_userspace - -.Lasync_tlb: - { - bz r28, .Lneed_sigpending - - /* Mask the sigpending flag */ - andi r28, r29, _TIF_SIGPENDING - } - - PTREGS_PTR(r0, PTREGS_OFFSET_BASE) - jal do_async_page_fault - FEEDBACK_REENTER(interrupt_return) - - /* - * Go restart the "resume userspace" process. We may have - * fired a signal, and we need to disable interrupts again. - */ - j .Lresume_userspace - -.Lneed_sigpending: - /* - * At this point we are either doing signal handling or single-step, - * so either way make sure we have all the registers saved. - */ - push_extra_callee_saves r0 - - { - /* If no signal pending, skip to singlestep check */ - bz r28, .Lneed_singlestep - - /* Mask the singlestep flag */ - andi r28, r29, _TIF_SINGLESTEP - } - - jal do_signal - FEEDBACK_REENTER(interrupt_return) - - /* Reload the flags and check again */ - j .Lresume_userspace - -.Lneed_singlestep: - { - /* Get a pointer to the EX1 field */ - PTREGS_PTR(r29, PTREGS_OFFSET_EX1) - - /* If we get here, our bit must be set. */ - bz r28, .Lwork_confusion - } - /* If we are in priv mode, don't single step */ - lw r28, r29 - andi r28, r28, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ - bnz r28, .Lrestore_all - - /* Allow interrupts within the single step code */ - TRACE_IRQS_ON /* Note: clobbers registers r0-r29 */ - IRQ_ENABLE(r20, r21) - - /* try to single-step the current instruction */ - PTREGS_PTR(r0, PTREGS_OFFSET_BASE) - jal single_step_once - FEEDBACK_REENTER(interrupt_return) - - /* Re-disable interrupts. TRACE_IRQS_OFF in .Lrestore_all. */ - IRQ_DISABLE(r20,r21) - - j .Lrestore_all - -.Lwork_confusion: - move r0, r28 - panic "thread_info allwork flags unhandled on userspace resume: %#x" - STD_ENDPROC(interrupt_return) /* @@ -1550,7 +1470,10 @@ STD_ENTRY(_sys_clone) * We place it in the __HEAD section to ensure it is relatively * near to the intvec_SWINT_1 code (reachable by a conditional branch). * - * Must match register usage in do_page_fault(). + * Our use of ATOMIC_LOCK_REG here must match do_page_fault_ics(). + * + * As we do in lib/atomic_asm_32.S, we bypass a store if the value we + * would store is the same as the value we just loaded. */ __HEAD .align 64 @@ -1611,17 +1534,7 @@ ENTRY(sys_cmpxchg) { shri r20, r25, 32 - ATOMIC_HASH_L1_SHIFT slt_u r23, r0, r23 - - /* - * Ensure that the TLB is loaded before we take out the lock. - * On TILEPro, this will start fetching the value all the way - * into our L1 as well (and if it gets modified before we - * grab the lock, it will be invalidated from our cache - * before we reload it). On tile64, we'll start fetching it - * into our L1 if we're the home, and if we're not, we'll - * still at least start fetching it into the home's L2. - */ - lw r26, r0 + lw r26, r0 /* see comment in the "#else" for the "lw r26". */ } { s2a r21, r20, r21 @@ -1637,18 +1550,9 @@ ENTRY(sys_cmpxchg) bbs r23, .Lcmpxchg64 andi r23, r0, 7 /* Precompute alignment for cmpxchg64. */ } - { - /* - * We very carefully align the code that actually runs with - * the lock held (nine bundles) so that we know it is all in - * the icache when we start. This instruction (the jump) is - * at the start of the first cache line, address zero mod 64; - * we jump to somewhere in the second cache line to issue the - * tns, then jump back to finish up. - */ s2a ATOMIC_LOCK_REG_NAME, r25, r21 - j .Lcmpxchg32_tns + j .Lcmpxchg32_tns /* see comment in the #else for the jump. */ } #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ @@ -1713,24 +1617,25 @@ ENTRY(sys_cmpxchg) { /* * We very carefully align the code that actually runs with - * the lock held (nine bundles) so that we know it is all in + * the lock held (twelve bundles) so that we know it is all in * the icache when we start. This instruction (the jump) is * at the start of the first cache line, address zero mod 64; - * we jump to somewhere in the second cache line to issue the - * tns, then jump back to finish up. + * we jump to the very end of the second cache line to get that + * line loaded in the icache, then fall through to issue the tns + * in the third cache line, at which point it's all cached. + * Note that is for performance, not correctness. */ j .Lcmpxchg32_tns } #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ - ENTRY(__sys_cmpxchg_grab_lock) +/* Symbol for do_page_fault_ics() to use to compare against the PC. */ +.global __sys_cmpxchg_grab_lock +__sys_cmpxchg_grab_lock: /* * Perform the actual cmpxchg or atomic_update. - * Note that the system <arch/atomic.h> header relies on - * atomic_update() to always perform an "mf", so don't make - * it optional or conditional without modifying that code. */ .Ldo_cmpxchg32: { @@ -1748,10 +1653,13 @@ ENTRY(sys_cmpxchg) } { mvnz r24, r23, r25 /* Use atomic_update value if appropriate. */ - bbns r22, .Lcmpxchg32_mismatch + bbns r22, .Lcmpxchg32_nostore } + seq r22, r24, r21 /* Are we storing the value we loaded? */ + bbs r22, .Lcmpxchg32_nostore sw r0, r24 + /* The following instruction is the start of the second cache line. */ /* Do slow mtspr here so the following "mf" waits less. */ { move sp, r27 @@ -1759,7 +1667,6 @@ ENTRY(sys_cmpxchg) } mf - /* The following instruction is the start of the second cache line. */ { move r0, r21 sw ATOMIC_LOCK_REG_NAME, zero @@ -1767,7 +1674,7 @@ ENTRY(sys_cmpxchg) iret /* Duplicated code here in the case where we don't overlap "mf" */ -.Lcmpxchg32_mismatch: +.Lcmpxchg32_nostore: { move r0, r21 sw ATOMIC_LOCK_REG_NAME, zero @@ -1783,8 +1690,6 @@ ENTRY(sys_cmpxchg) * and for 64-bit cmpxchg. We provide it as a macro and put * it into both versions. We can't share the code literally * since it depends on having the right branch-back address. - * Note that the first few instructions should share the cache - * line with the second half of the actual locked code. */ .macro cmpxchg_lock, bitwidth @@ -1810,7 +1715,7 @@ ENTRY(sys_cmpxchg) } /* * The preceding instruction is the last thing that must be - * on the second cache line. + * hot in the icache before we do the "tns" above. */ #ifdef CONFIG_SMP @@ -1841,6 +1746,12 @@ ENTRY(sys_cmpxchg) .endm .Lcmpxchg32_tns: + /* + * This is the last instruction on the second cache line. + * The nop here loads the second line, then we fall through + * to the tns to load the third line before we take the lock. + */ + nop cmpxchg_lock 32 /* diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S new file mode 100644 index 00000000000..79c93e10ba2 --- /dev/null +++ b/arch/tile/kernel/intvec_64.S @@ -0,0 +1,1231 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Linux interrupt vectors. + */ + +#include <linux/linkage.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <asm/ptrace.h> +#include <asm/thread_info.h> +#include <asm/irqflags.h> +#include <asm/asm-offsets.h> +#include <asm/types.h> +#include <hv/hypervisor.h> +#include <arch/abi.h> +#include <arch/interrupts.h> +#include <arch/spr_def.h> + +#ifdef CONFIG_PREEMPT +# error "No support for kernel preemption currently" +#endif + +#define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg) + +#define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) + + + .macro push_reg reg, ptr=sp, delta=-8 + { + st \ptr, \reg + addli \ptr, \ptr, \delta + } + .endm + + .macro pop_reg reg, ptr=sp, delta=8 + { + ld \reg, \ptr + addli \ptr, \ptr, \delta + } + .endm + + .macro pop_reg_zero reg, zreg, ptr=sp, delta=8 + { + move \zreg, zero + ld \reg, \ptr + addi \ptr, \ptr, \delta + } + .endm + + .macro push_extra_callee_saves reg + PTREGS_PTR(\reg, PTREGS_OFFSET_REG(51)) + push_reg r51, \reg + push_reg r50, \reg + push_reg r49, \reg + push_reg r48, \reg + push_reg r47, \reg + push_reg r46, \reg + push_reg r45, \reg + push_reg r44, \reg + push_reg r43, \reg + push_reg r42, \reg + push_reg r41, \reg + push_reg r40, \reg + push_reg r39, \reg + push_reg r38, \reg + push_reg r37, \reg + push_reg r36, \reg + push_reg r35, \reg + push_reg r34, \reg, PTREGS_OFFSET_BASE - PTREGS_OFFSET_REG(34) + .endm + + .macro panic str + .pushsection .rodata, "a" +1: + .asciz "\str" + .popsection + { + moveli r0, hw2_last(1b) + } + { + shl16insli r0, r0, hw1(1b) + } + { + shl16insli r0, r0, hw0(1b) + jal panic + } + .endm + + +#ifdef __COLLECT_LINKER_FEEDBACK__ + .pushsection .text.intvec_feedback,"ax" +intvec_feedback: + .popsection +#endif + + /* + * Default interrupt handler. + * + * vecnum is where we'll put this code. + * c_routine is the C routine we'll call. + * + * The C routine is passed two arguments: + * - A pointer to the pt_regs state. + * - The interrupt vector number. + * + * The "processing" argument specifies the code for processing + * the interrupt. Defaults to "handle_interrupt". + */ + .macro int_hand vecnum, vecname, c_routine, processing=handle_interrupt + .org (\vecnum << 8) +intvec_\vecname: + /* Temporarily save a register so we have somewhere to work. */ + + mtspr SPR_SYSTEM_SAVE_K_1, r0 + mfspr r0, SPR_EX_CONTEXT_K_1 + + andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + + .ifc \vecnum, INT_DOUBLE_FAULT + /* + * For double-faults from user-space, fall through to the normal + * register save and stack setup path. Otherwise, it's the + * hypervisor giving us one last chance to dump diagnostics, and we + * branch to the kernel_double_fault routine to do so. + */ + beqz r0, 1f + j _kernel_double_fault +1: + .else + /* + * If we're coming from user-space, then set sp to the top of + * the kernel stack. Otherwise, assume sp is already valid. + */ + { + bnez r0, 0f + move r0, sp + } + .endif + + .ifc \c_routine, do_page_fault + /* + * The page_fault handler may be downcalled directly by the + * hypervisor even when Linux is running and has ICS set. + * + * In this case the contents of EX_CONTEXT_K_1 reflect the + * previous fault and can't be relied on to choose whether or + * not to reinitialize the stack pointer. So we add a test + * to see whether SYSTEM_SAVE_K_2 has the high bit set, + * and if so we don't reinitialize sp, since we must be coming + * from Linux. (In fact the precise case is !(val & ~1), + * but any Linux PC has to have the high bit set.) + * + * Note that the hypervisor *always* sets SYSTEM_SAVE_K_2 for + * any path that turns into a downcall to one of our TLB handlers. + * + * FIXME: if we end up never using this path, perhaps we should + * prevent the hypervisor from generating downcalls in this case. + * The advantage of getting a downcall is we can panic in Linux. + */ + mfspr r0, SPR_SYSTEM_SAVE_K_2 + { + bltz r0, 0f /* high bit in S_S_1_2 is for a PC to use */ + move r0, sp + } + .endif + + + /* + * SYSTEM_SAVE_K_0 holds the cpu number in the low bits, and + * the current stack top in the higher bits. So we recover + * our stack top by just masking off the low bits, then + * point sp at the top aligned address on the actual stack page. + */ + mfspr r0, SPR_SYSTEM_SAVE_K_0 + mm r0, zero, LOG2_THREAD_SIZE, 63 + +0: + /* + * Align the stack mod 64 so we can properly predict what + * cache lines we need to write-hint to reduce memory fetch + * latency as we enter the kernel. The layout of memory is + * as follows, with cache line 0 at the lowest VA, and cache + * line 8 just below the r0 value this "andi" computes. + * Note that we never write to cache line 8, and we skip + * cache lines 1-3 for syscalls. + * + * cache line 8: ptregs padding (two words) + * cache line 7: sp, lr, pc, ex1, faultnum, orig_r0, flags, cmpexch + * cache line 6: r46...r53 (tp) + * cache line 5: r38...r45 + * cache line 4: r30...r37 + * cache line 3: r22...r29 + * cache line 2: r14...r21 + * cache line 1: r6...r13 + * cache line 0: 2 x frame, r0..r5 + */ + andi r0, r0, -64 + + /* + * Push the first four registers on the stack, so that we can set + * them to vector-unique values before we jump to the common code. + * + * Registers are pushed on the stack as a struct pt_regs, + * with the sp initially just above the struct, and when we're + * done, sp points to the base of the struct, minus + * C_ABI_SAVE_AREA_SIZE, so we can directly jal to C code. + * + * This routine saves just the first four registers, plus the + * stack context so we can do proper backtracing right away, + * and defers to handle_interrupt to save the rest. + * The backtracer needs pc, ex1, lr, sp, r52, and faultnum. + */ + addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP) + wh64 r0 /* cache line 7 */ + { + st r0, lr + addli r0, r0, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR + } + { + st r0, sp + addli sp, r0, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_SP + } + wh64 sp /* cache line 6 */ + { + st sp, r52 + addli sp, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(52) + } + wh64 sp /* cache line 0 */ + { + st sp, r1 + addli sp, sp, PTREGS_OFFSET_REG(2) - PTREGS_OFFSET_REG(1) + } + { + st sp, r2 + addli sp, sp, PTREGS_OFFSET_REG(3) - PTREGS_OFFSET_REG(2) + } + { + st sp, r3 + addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3) + } + mfspr r0, SPR_EX_CONTEXT_K_0 + .ifc \processing,handle_syscall + /* + * Bump the saved PC by one bundle so that when we return, we won't + * execute the same swint instruction again. We need to do this while + * we're in the critical section. + */ + addi r0, r0, 8 + .endif + { + st sp, r0 + addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC + } + mfspr r0, SPR_EX_CONTEXT_K_1 + { + st sp, r0 + addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 + /* + * Use r0 for syscalls so it's a temporary; use r1 for interrupts + * so that it gets passed through unchanged to the handler routine. + * Note that the .if conditional confusingly spans bundles. + */ + .ifc \processing,handle_syscall + movei r0, \vecnum + } + { + st sp, r0 + .else + movei r1, \vecnum + } + { + st sp, r1 + .endif + addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM + } + mfspr r0, SPR_SYSTEM_SAVE_K_1 /* Original r0 */ + { + st sp, r0 + addi sp, sp, -PTREGS_OFFSET_REG(0) - 8 + } + { + st sp, zero /* write zero into "Next SP" frame pointer */ + addi sp, sp, -8 /* leave SP pointing at bottom of frame */ + } + .ifc \processing,handle_syscall + j handle_syscall + .else + /* Capture per-interrupt SPR context to registers. */ + .ifc \c_routine, do_page_fault + mfspr r2, SPR_SYSTEM_SAVE_K_3 /* address of page fault */ + mfspr r3, SPR_SYSTEM_SAVE_K_2 /* info about page fault */ + .else + .ifc \vecnum, INT_ILL_TRANS + mfspr r2, ILL_TRANS_REASON + .else + .ifc \vecnum, INT_DOUBLE_FAULT + mfspr r2, SPR_SYSTEM_SAVE_K_2 /* double fault info from HV */ + .else + .ifc \c_routine, do_trap + mfspr r2, GPV_REASON + .else + .ifc \c_routine, op_handle_perf_interrupt + mfspr r2, PERF_COUNT_STS +#if CHIP_HAS_AUX_PERF_COUNTERS() + .else + .ifc \c_routine, op_handle_aux_perf_interrupt + mfspr r2, AUX_PERF_COUNT_STS + .endif +#endif + .endif + .endif + .endif + .endif + .endif + /* Put function pointer in r0 */ + moveli r0, hw2_last(\c_routine) + shl16insli r0, r0, hw1(\c_routine) + { + shl16insli r0, r0, hw0(\c_routine) + j \processing + } + .endif + ENDPROC(intvec_\vecname) + +#ifdef __COLLECT_LINKER_FEEDBACK__ + .pushsection .text.intvec_feedback,"ax" + .org (\vecnum << 5) + FEEDBACK_ENTER_EXPLICIT(intvec_\vecname, .intrpt1, 1 << 8) + jrp lr + .popsection +#endif + + .endm + + + /* + * Save the rest of the registers that we didn't save in the actual + * vector itself. We can't use r0-r10 inclusive here. + */ + .macro finish_interrupt_save, function + + /* If it's a syscall, save a proper orig_r0, otherwise just zero. */ + PTREGS_PTR(r52, PTREGS_OFFSET_ORIG_R0) + { + .ifc \function,handle_syscall + st r52, r0 + .else + st r52, zero + .endif + PTREGS_PTR(r52, PTREGS_OFFSET_TP) + } + st r52, tp + { + mfspr tp, CMPEXCH_VALUE + PTREGS_PTR(r52, PTREGS_OFFSET_CMPEXCH) + } + + /* + * For ordinary syscalls, we save neither caller- nor callee- + * save registers, since the syscall invoker doesn't expect the + * caller-saves to be saved, and the called kernel functions will + * take care of saving the callee-saves for us. + * + * For interrupts we save just the caller-save registers. Saving + * them is required (since the "caller" can't save them). Again, + * the called kernel functions will restore the callee-save + * registers for us appropriately. + * + * On return, we normally restore nothing special for syscalls, + * and just the caller-save registers for interrupts. + * + * However, there are some important caveats to all this: + * + * - We always save a few callee-save registers to give us + * some scratchpad registers to carry across function calls. + * + * - fork/vfork/etc require us to save all the callee-save + * registers, which we do in PTREGS_SYSCALL_ALL_REGS, below. + * + * - We always save r0..r5 and r10 for syscalls, since we need + * to reload them a bit later for the actual kernel call, and + * since we might need them for -ERESTARTNOINTR, etc. + * + * - Before invoking a signal handler, we save the unsaved + * callee-save registers so they are visible to the + * signal handler or any ptracer. + * + * - If the unsaved callee-save registers are modified, we set + * a bit in pt_regs so we know to reload them from pt_regs + * and not just rely on the kernel function unwinding. + * (Done for ptrace register writes and SA_SIGINFO handler.) + */ + { + st r52, tp + PTREGS_PTR(r52, PTREGS_OFFSET_REG(33)) + } + wh64 r52 /* cache line 4 */ + push_reg r33, r52 + push_reg r32, r52 + push_reg r31, r52 + .ifc \function,handle_syscall + push_reg r30, r52, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(30) + push_reg TREG_SYSCALL_NR_NAME, r52, \ + PTREGS_OFFSET_REG(5) - PTREGS_OFFSET_SYSCALL + .else + + push_reg r30, r52, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(30) + wh64 r52 /* cache line 3 */ + push_reg r29, r52 + push_reg r28, r52 + push_reg r27, r52 + push_reg r26, r52 + push_reg r25, r52 + push_reg r24, r52 + push_reg r23, r52 + push_reg r22, r52 + wh64 r52 /* cache line 2 */ + push_reg r21, r52 + push_reg r20, r52 + push_reg r19, r52 + push_reg r18, r52 + push_reg r17, r52 + push_reg r16, r52 + push_reg r15, r52 + push_reg r14, r52 + wh64 r52 /* cache line 1 */ + push_reg r13, r52 + push_reg r12, r52 + push_reg r11, r52 + push_reg r10, r52 + push_reg r9, r52 + push_reg r8, r52 + push_reg r7, r52 + push_reg r6, r52 + + .endif + + push_reg r5, r52 + st r52, r4 + + /* Load tp with our per-cpu offset. */ +#ifdef CONFIG_SMP + { + mfspr r20, SPR_SYSTEM_SAVE_K_0 + moveli r21, hw2_last(__per_cpu_offset) + } + { + shl16insli r21, r21, hw1(__per_cpu_offset) + bfextu r20, r20, 0, LOG2_THREAD_SIZE-1 + } + shl16insli r21, r21, hw0(__per_cpu_offset) + shl3add r20, r20, r21 + ld tp, r20 +#else + move tp, zero +#endif + + /* + * If we will be returning to the kernel, we will need to + * reset the interrupt masks to the state they had before. + * Set DISABLE_IRQ in flags iff we came from PL1 with irqs disabled. + */ + mfspr r32, SPR_EX_CONTEXT_K_1 + { + andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) + } + beqzt r32, 1f /* zero if from user space */ + IRQS_DISABLED(r32) /* zero if irqs enabled */ +#if PT_FLAGS_DISABLE_IRQ != 1 +# error Value of IRQS_DISABLED used to set PT_FLAGS_DISABLE_IRQ; fix +#endif +1: + .ifnc \function,handle_syscall + /* Record the fact that we saved the caller-save registers above. */ + ori r32, r32, PT_FLAGS_CALLER_SAVES + .endif + st r21, r32 + +#ifdef __COLLECT_LINKER_FEEDBACK__ + /* + * Notify the feedback routines that we were in the + * appropriate fixed interrupt vector area. Note that we + * still have ICS set at this point, so we can't invoke any + * atomic operations or we will panic. The feedback + * routines internally preserve r0..r10 and r30 up. + */ + .ifnc \function,handle_syscall + shli r20, r1, 5 + .else + moveli r20, INT_SWINT_1 << 5 + .endif + moveli r21, hw2_last(intvec_feedback) + shl16insli r21, r21, hw1(intvec_feedback) + shl16insli r21, r21, hw0(intvec_feedback) + add r20, r20, r21 + jalr r20 + + /* And now notify the feedback routines that we are here. */ + FEEDBACK_ENTER(\function) +#endif + + /* + * we've captured enough state to the stack (including in + * particular our EX_CONTEXT state) that we can now release + * the interrupt critical section and replace it with our + * standard "interrupts disabled" mask value. This allows + * synchronous interrupts (and profile interrupts) to punch + * through from this point onwards. + */ + .ifc \function,handle_nmi + IRQ_DISABLE_ALL(r20) + .else + IRQ_DISABLE(r20, r21) + .endif + mtspr INTERRUPT_CRITICAL_SECTION, zero + + /* + * Prepare the first 256 stack bytes to be rapidly accessible + * without having to fetch the background data. + */ + addi r52, sp, -64 + { + wh64 r52 + addi r52, r52, -64 + } + { + wh64 r52 + addi r52, r52, -64 + } + { + wh64 r52 + addi r52, r52, -64 + } + wh64 r52 + +#ifdef CONFIG_TRACE_IRQFLAGS + .ifnc \function,handle_nmi + /* + * We finally have enough state set up to notify the irq + * tracing code that irqs were disabled on entry to the handler. + * The TRACE_IRQS_OFF call clobbers registers r0-r29. + * For syscalls, we already have the register state saved away + * on the stack, so we don't bother to do any register saves here, + * and later we pop the registers back off the kernel stack. + * For interrupt handlers, save r0-r3 in callee-saved registers. + */ + .ifnc \function,handle_syscall + { move r30, r0; move r31, r1 } + { move r32, r2; move r33, r3 } + .endif + TRACE_IRQS_OFF + .ifnc \function,handle_syscall + { move r0, r30; move r1, r31 } + { move r2, r32; move r3, r33 } + .endif + .endif +#endif + + .endm + + /* + * Redispatch a downcall. + */ + .macro dc_dispatch vecnum, vecname + .org (\vecnum << 8) +intvec_\vecname: + j hv_downcall_dispatch + ENDPROC(intvec_\vecname) + .endm + + /* + * Common code for most interrupts. The C function we're eventually + * going to is in r0, and the faultnum is in r1; the original + * values for those registers are on the stack. + */ + .pushsection .text.handle_interrupt,"ax" +handle_interrupt: + finish_interrupt_save handle_interrupt + + /* Jump to the C routine; it should enable irqs as soon as possible. */ + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_interrupt) + { + movei r30, 0 /* not an NMI */ + j interrupt_return + } + STD_ENDPROC(handle_interrupt) + +/* + * This routine takes a boolean in r30 indicating if this is an NMI. + * If so, we also expect a boolean in r31 indicating whether to + * re-enable the oprofile interrupts. + */ +STD_ENTRY(interrupt_return) + /* If we're resuming to kernel space, don't check thread flags. */ + { + bnez r30, .Lrestore_all /* NMIs don't special-case user-space */ + PTREGS_PTR(r29, PTREGS_OFFSET_EX1) + } + ld r29, r29 + andi r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + { + beqzt r29, .Lresume_userspace + PTREGS_PTR(r29, PTREGS_OFFSET_PC) + } + + /* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */ + moveli r27, hw2_last(_cpu_idle_nap) + { + ld r28, r29 + shl16insli r27, r27, hw1(_cpu_idle_nap) + } + { + shl16insli r27, r27, hw0(_cpu_idle_nap) + } + { + cmpeq r27, r27, r28 + } + { + blbc r27, .Lrestore_all + addi r28, r28, 8 + } + st r29, r28 + j .Lrestore_all + +.Lresume_userspace: + FEEDBACK_REENTER(interrupt_return) + + /* + * Disable interrupts so as to make sure we don't + * miss an interrupt that sets any of the thread flags (like + * need_resched or sigpending) between sampling and the iret. + * Routines like schedule() or do_signal() may re-enable + * interrupts before returning. + */ + IRQ_DISABLE(r20, r21) + TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ + + /* Get base of stack in r32; note r30/31 are used as arguments here. */ + GET_THREAD_INFO(r32) + + + /* Check to see if there is any work to do before returning to user. */ + { + addi r29, r32, THREAD_INFO_FLAGS_OFFSET + moveli r1, hw1_last(_TIF_ALLWORK_MASK) + } + { + ld r29, r29 + shl16insli r1, r1, hw0(_TIF_ALLWORK_MASK) + } + and r1, r29, r1 + beqzt r1, .Lrestore_all + + /* + * Make sure we have all the registers saved for signal + * handling or single-step. Call out to C code to figure out + * exactly what we need to do for each flag bit, then if + * necessary, reload the flags and recheck. + */ + push_extra_callee_saves r0 + { + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + jal do_work_pending + } + bnez r0, .Lresume_userspace + + /* + * In the NMI case we + * omit the call to single_process_check_nohz, which normally checks + * to see if we should start or stop the scheduler tick, because + * we can't call arbitrary Linux code from an NMI context. + * We always call the homecache TLB deferral code to re-trigger + * the deferral mechanism. + * + * The other chunk of responsibility this code has is to reset the + * interrupt masks appropriately to reset irqs and NMIs. We have + * to call TRACE_IRQS_OFF and TRACE_IRQS_ON to support all the + * lockdep-type stuff, but we can't set ICS until afterwards, since + * ICS can only be used in very tight chunks of code to avoid + * tripping over various assertions that it is off. + */ +.Lrestore_all: + PTREGS_PTR(r0, PTREGS_OFFSET_EX1) + { + ld r0, r0 + PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) + } + { + andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK + ld r32, r32 + } + bnez r0, 1f + j 2f +#if PT_FLAGS_DISABLE_IRQ != 1 +# error Assuming PT_FLAGS_DISABLE_IRQ == 1 so we can use blbct below +#endif +1: blbct r32, 2f + IRQ_DISABLE(r20,r21) + TRACE_IRQS_OFF + movei r0, 1 + mtspr INTERRUPT_CRITICAL_SECTION, r0 + beqzt r30, .Lrestore_regs + j 3f +2: TRACE_IRQS_ON + movei r0, 1 + mtspr INTERRUPT_CRITICAL_SECTION, r0 + IRQ_ENABLE(r20, r21) + beqzt r30, .Lrestore_regs +3: + + + /* + * We now commit to returning from this interrupt, since we will be + * doing things like setting EX_CONTEXT SPRs and unwinding the stack + * frame. No calls should be made to any other code after this point. + * This code should only be entered with ICS set. + * r32 must still be set to ptregs.flags. + * We launch loads to each cache line separately first, so we can + * get some parallelism out of the memory subsystem. + * We start zeroing caller-saved registers throughout, since + * that will save some cycles if this turns out to be a syscall. + */ +.Lrestore_regs: + FEEDBACK_REENTER(interrupt_return) /* called from elsewhere */ + + /* + * Rotate so we have one high bit and one low bit to test. + * - low bit says whether to restore all the callee-saved registers, + * or just r30-r33, and r52 up. + * - high bit (i.e. sign bit) says whether to restore all the + * caller-saved registers, or just r0. + */ +#if PT_FLAGS_CALLER_SAVES != 2 || PT_FLAGS_RESTORE_REGS != 4 +# error Rotate trick does not work :-) +#endif + { + rotli r20, r32, 62 + PTREGS_PTR(sp, PTREGS_OFFSET_REG(0)) + } + + /* + * Load cache lines 0, 4, 6 and 7, in that order, then use + * the last loaded value, which makes it likely that the other + * cache lines have also loaded, at which point we should be + * able to safely read all the remaining words on those cache + * lines without waiting for the memory subsystem. + */ + pop_reg r0, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0) + pop_reg r30, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_REG(30) + pop_reg_zero r52, r3, sp, PTREGS_OFFSET_CMPEXCH - PTREGS_OFFSET_REG(52) + pop_reg_zero r21, r27, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_CMPEXCH + pop_reg_zero lr, r2, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_EX1 + { + mtspr CMPEXCH_VALUE, r21 + move r4, zero + } + pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC + { + mtspr SPR_EX_CONTEXT_K_1, lr + andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + } + { + mtspr SPR_EX_CONTEXT_K_0, r21 + move r5, zero + } + + /* Restore callee-saveds that we actually use. */ + pop_reg_zero r31, r6 + pop_reg_zero r32, r7 + pop_reg_zero r33, r8, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(33) + + /* + * If we modified other callee-saveds, restore them now. + * This is rare, but could be via ptrace or signal handler. + */ + { + move r9, zero + blbs r20, .Lrestore_callees + } +.Lcontinue_restore_regs: + + /* Check if we're returning from a syscall. */ + { + move r10, zero + bltzt r20, 1f /* no, so go restore callee-save registers */ + } + + /* + * Check if we're returning to userspace. + * Note that if we're not, we don't worry about zeroing everything. + */ + { + addli sp, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(29) + bnez lr, .Lkernel_return + } + + /* + * On return from syscall, we've restored r0 from pt_regs, but we + * clear the remainder of the caller-saved registers. We could + * restore the syscall arguments, but there's not much point, + * and it ensures user programs aren't trying to use the + * caller-saves if we clear them, as well as avoiding leaking + * kernel pointers into userspace. + */ + pop_reg_zero lr, r11, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR + pop_reg_zero tp, r12, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP + { + ld sp, sp + move r13, zero + move r14, zero + } + { move r15, zero; move r16, zero } + { move r17, zero; move r18, zero } + { move r19, zero; move r20, zero } + { move r21, zero; move r22, zero } + { move r23, zero; move r24, zero } + { move r25, zero; move r26, zero } + + /* Set r1 to errno if we are returning an error, otherwise zero. */ + { + moveli r29, 4096 + sub r1, zero, r0 + } + { + move r28, zero + cmpltu r29, r1, r29 + } + { + mnz r1, r29, r1 + move r29, zero + } + iret + + /* + * Not a syscall, so restore caller-saved registers. + * First kick off loads for cache lines 1-3, which we're touching + * for the first time here. + */ + .align 64 +1: pop_reg r29, sp, PTREGS_OFFSET_REG(21) - PTREGS_OFFSET_REG(29) + pop_reg r21, sp, PTREGS_OFFSET_REG(13) - PTREGS_OFFSET_REG(21) + pop_reg r13, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(13) + pop_reg r1 + pop_reg r2 + pop_reg r3 + pop_reg r4 + pop_reg r5 + pop_reg r6 + pop_reg r7 + pop_reg r8 + pop_reg r9 + pop_reg r10 + pop_reg r11 + pop_reg r12, sp, 16 + /* r13 already restored above */ + pop_reg r14 + pop_reg r15 + pop_reg r16 + pop_reg r17 + pop_reg r18 + pop_reg r19 + pop_reg r20, sp, 16 + /* r21 already restored above */ + pop_reg r22 + pop_reg r23 + pop_reg r24 + pop_reg r25 + pop_reg r26 + pop_reg r27 + pop_reg r28, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(28) + /* r29 already restored above */ + bnez lr, .Lkernel_return + pop_reg lr, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR + pop_reg tp, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP + ld sp, sp + iret + + /* + * We can't restore tp when in kernel mode, since a thread might + * have migrated from another cpu and brought a stale tp value. + */ +.Lkernel_return: + pop_reg lr, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR + ld sp, sp + iret + + /* Restore callee-saved registers from r34 to r51. */ +.Lrestore_callees: + addli sp, sp, PTREGS_OFFSET_REG(34) - PTREGS_OFFSET_REG(29) + pop_reg r34 + pop_reg r35 + pop_reg r36 + pop_reg r37 + pop_reg r38 + pop_reg r39 + pop_reg r40 + pop_reg r41 + pop_reg r42 + pop_reg r43 + pop_reg r44 + pop_reg r45 + pop_reg r46 + pop_reg r47 + pop_reg r48 + pop_reg r49 + pop_reg r50 + pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) + j .Lcontinue_restore_regs + STD_ENDPROC(interrupt_return) + + /* + * "NMI" interrupts mask ALL interrupts before calling the + * handler, and don't check thread flags, etc., on the way + * back out. In general, the only things we do here for NMIs + * are register save/restore and dataplane kernel-TLB management. + * We don't (for example) deal with start/stop of the sched tick. + */ + .pushsection .text.handle_nmi,"ax" +handle_nmi: + finish_interrupt_save handle_nmi + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_nmi) + { + movei r30, 1 + move r31, r0 + } + j interrupt_return + STD_ENDPROC(handle_nmi) + + /* + * Parallel code for syscalls to handle_interrupt. + */ + .pushsection .text.handle_syscall,"ax" +handle_syscall: + finish_interrupt_save handle_syscall + + /* Enable irqs. */ + TRACE_IRQS_ON + IRQ_ENABLE(r20, r21) + + /* Bump the counter for syscalls made on this tile. */ + moveli r20, hw2_last(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) + shl16insli r20, r20, hw1(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) + shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) + add r20, r20, tp + ld4s r21, r20 + addi r21, r21, 1 + st4 r20, r21 + + /* Trace syscalls, if requested. */ + GET_THREAD_INFO(r31) + addi r31, r31, THREAD_INFO_FLAGS_OFFSET + ld r30, r31 + andi r30, r30, _TIF_SYSCALL_TRACE + { + addi r30, r31, THREAD_INFO_STATUS_OFFSET - THREAD_INFO_FLAGS_OFFSET + beqzt r30, .Lrestore_syscall_regs + } + jal do_syscall_trace + FEEDBACK_REENTER(handle_syscall) + + /* + * We always reload our registers from the stack at this + * point. They might be valid, if we didn't build with + * TRACE_IRQFLAGS, and this isn't a dataplane tile, and we're not + * doing syscall tracing, but there are enough cases now that it + * seems simplest just to do the reload unconditionally. + */ +.Lrestore_syscall_regs: + { + ld r30, r30 + PTREGS_PTR(r11, PTREGS_OFFSET_REG(0)) + } + pop_reg r0, r11 + pop_reg r1, r11 + pop_reg r2, r11 + pop_reg r3, r11 + pop_reg r4, r11 + pop_reg r5, r11, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(5) + { + ld TREG_SYSCALL_NR_NAME, r11 + moveli r21, __NR_syscalls + } + + /* Ensure that the syscall number is within the legal range. */ + { + moveli r20, hw2(sys_call_table) + blbs r30, .Lcompat_syscall + } + { + cmpltu r21, TREG_SYSCALL_NR_NAME, r21 + shl16insli r20, r20, hw1(sys_call_table) + } + { + blbc r21, .Linvalid_syscall + shl16insli r20, r20, hw0(sys_call_table) + } +.Lload_syscall_pointer: + shl3add r20, TREG_SYSCALL_NR_NAME, r20 + ld r20, r20 + + /* Jump to syscall handler. */ + jalr r20 +.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ + + /* + * Write our r0 onto the stack so it gets restored instead + * of whatever the user had there before. + * In compat mode, sign-extend r0 before storing it. + */ + { + PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) + blbct r30, 1f + } + addxi r0, r0, 0 +1: st r29, r0 + +.Lsyscall_sigreturn_skip: + FEEDBACK_REENTER(handle_syscall) + + /* Do syscall trace again, if requested. */ + ld r30, r31 + andi r30, r30, _TIF_SYSCALL_TRACE + beqzt r30, 1f + jal do_syscall_trace + FEEDBACK_REENTER(handle_syscall) +1: j .Lresume_userspace /* jump into middle of interrupt_return */ + +.Lcompat_syscall: + /* + * Load the base of the compat syscall table in r20, and + * range-check the syscall number (duplicated from 64-bit path). + * Sign-extend all the user's passed arguments to make them consistent. + * Also save the original "r(n)" values away in "r(11+n)" in + * case the syscall table entry wants to validate them. + */ + moveli r20, hw2(compat_sys_call_table) + { + cmpltu r21, TREG_SYSCALL_NR_NAME, r21 + shl16insli r20, r20, hw1(compat_sys_call_table) + } + { + blbc r21, .Linvalid_syscall + shl16insli r20, r20, hw0(compat_sys_call_table) + } + { move r11, r0; addxi r0, r0, 0 } + { move r12, r1; addxi r1, r1, 0 } + { move r13, r2; addxi r2, r2, 0 } + { move r14, r3; addxi r3, r3, 0 } + { move r15, r4; addxi r4, r4, 0 } + { move r16, r5; addxi r5, r5, 0 } + j .Lload_syscall_pointer + +.Linvalid_syscall: + /* Report an invalid syscall back to the user program */ + { + PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) + movei r28, -ENOSYS + } + st r29, r28 + j .Lresume_userspace /* jump into middle of interrupt_return */ + STD_ENDPROC(handle_syscall) + + /* Return the address for oprofile to suppress in backtraces. */ +STD_ENTRY_SECTION(handle_syscall_link_address, .text.handle_syscall) + lnk r0 + { + addli r0, r0, .Lhandle_syscall_link - . + jrp lr + } + STD_ENDPROC(handle_syscall_link_address) + +STD_ENTRY(ret_from_fork) + jal sim_notify_fork + jal schedule_tail + FEEDBACK_REENTER(ret_from_fork) + j .Lresume_userspace + STD_ENDPROC(ret_from_fork) + +/* Various stub interrupt handlers and syscall handlers */ + +STD_ENTRY_LOCAL(_kernel_double_fault) + mfspr r1, SPR_EX_CONTEXT_K_0 + move r2, lr + move r3, sp + move r4, r52 + addi sp, sp, -C_ABI_SAVE_AREA_SIZE + j kernel_double_fault + STD_ENDPROC(_kernel_double_fault) + +STD_ENTRY_LOCAL(bad_intr) + mfspr r2, SPR_EX_CONTEXT_K_0 + panic "Unhandled interrupt %#x: PC %#lx" + STD_ENDPROC(bad_intr) + +/* Put address of pt_regs in reg and jump. */ +#define PTREGS_SYSCALL(x, reg) \ + STD_ENTRY(_##x); \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j x \ + }; \ + STD_ENDPROC(_##x) + +/* + * Special-case sigreturn to not write r0 to the stack on return. + * This is technically more efficient, but it also avoids difficulties + * in the 64-bit OS when handling 32-bit compat code, since we must not + * sign-extend r0 for the sigreturn return-value case. + */ +#define PTREGS_SYSCALL_SIGRETURN(x, reg) \ + STD_ENTRY(_##x); \ + addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j x \ + }; \ + STD_ENDPROC(_##x) + +PTREGS_SYSCALL(sys_execve, r3) +PTREGS_SYSCALL(sys_sigaltstack, r2) +PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) +#ifdef CONFIG_COMPAT +PTREGS_SYSCALL(compat_sys_execve, r3) +PTREGS_SYSCALL(compat_sys_sigaltstack, r2) +PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) +#endif + +/* Save additional callee-saves to pt_regs, put address in r4 and jump. */ +STD_ENTRY(_sys_clone) + push_extra_callee_saves r4 + j sys_clone + STD_ENDPROC(_sys_clone) + +/* The single-step support may need to read all the registers. */ +int_unalign: + push_extra_callee_saves r0 + j do_trap + +/* Include .intrpt1 array of interrupt vectors */ + .section ".intrpt1", "ax" + +#define op_handle_perf_interrupt bad_intr +#define op_handle_aux_perf_interrupt bad_intr + +#ifndef CONFIG_HARDWALL +#define do_hardwall_trap bad_intr +#endif + + int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr + int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr +#if CONFIG_KERNEL_PL == 2 + int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle + int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, bad_intr +#else + int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, bad_intr + int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, gx_singlestep_handle +#endif + int_hand INT_SINGLE_STEP_0, SINGLE_STEP_0, bad_intr + int_hand INT_IDN_COMPLETE, IDN_COMPLETE, bad_intr + int_hand INT_UDN_COMPLETE, UDN_COMPLETE, bad_intr + int_hand INT_ITLB_MISS, ITLB_MISS, do_page_fault + int_hand INT_ILL, ILL, do_trap + int_hand INT_GPV, GPV, do_trap + int_hand INT_IDN_ACCESS, IDN_ACCESS, do_trap + int_hand INT_UDN_ACCESS, UDN_ACCESS, do_trap + int_hand INT_SWINT_3, SWINT_3, do_trap + int_hand INT_SWINT_2, SWINT_2, do_trap + int_hand INT_SWINT_1, SWINT_1, SYSCALL, handle_syscall + int_hand INT_SWINT_0, SWINT_0, do_trap + int_hand INT_ILL_TRANS, ILL_TRANS, do_trap + int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign + int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault + int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault + int_hand INT_IDN_FIREWALL, IDN_FIREWALL, bad_intr + int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap + int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt + int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr + int_hand INT_UDN_TIMER, UDN_TIMER, bad_intr + int_hand INT_IDN_AVAIL, IDN_AVAIL, bad_intr + int_hand INT_UDN_AVAIL, UDN_AVAIL, bad_intr + int_hand INT_IPI_3, IPI_3, bad_intr +#if CONFIG_KERNEL_PL == 2 + int_hand INT_IPI_2, IPI_2, tile_dev_intr + int_hand INT_IPI_1, IPI_1, bad_intr +#else + int_hand INT_IPI_2, IPI_2, bad_intr + int_hand INT_IPI_1, IPI_1, tile_dev_intr +#endif + int_hand INT_IPI_0, IPI_0, bad_intr + int_hand INT_PERF_COUNT, PERF_COUNT, \ + op_handle_perf_interrupt, handle_nmi + int_hand INT_AUX_PERF_COUNT, AUX_PERF_COUNT, \ + op_handle_perf_interrupt, handle_nmi + int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr +#if CONFIG_KERNEL_PL == 2 + dc_dispatch INT_INTCTRL_2, INTCTRL_2 + int_hand INT_INTCTRL_1, INTCTRL_1, bad_intr +#else + int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr + dc_dispatch INT_INTCTRL_1, INTCTRL_1 +#endif + int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr + int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \ + hv_message_intr + int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, bad_intr + int_hand INT_I_ASID, I_ASID, bad_intr + int_hand INT_D_ASID, D_ASID, bad_intr + int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap + + /* Synthetic interrupt delivered only by the simulator */ + int_hand INT_BREAKPOINT, BREAKPOINT, do_breakpoint diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index e2ab82b7c7e..f68df69f1f6 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <asm/opcode-tile.h> #include <asm/pgtable.h> +#include <asm/homecache.h> #ifdef __tilegx__ # define Elf_Rela Elf64_Rela @@ -86,8 +87,13 @@ error: void module_free(struct module *mod, void *module_region) { vfree(module_region); + + /* Globally flush the L1 icache. */ + flush_remote(0, HV_FLUSH_EVICT_L1I, cpu_online_mask, + 0, 0, 0, NULL, NULL, 0); + /* - * FIXME: If module_region == mod->init_region, trim exception + * FIXME: If module_region == mod->module_init, trim exception * table entries. */ } diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c index 658752b2835..658f2ce426a 100644 --- a/arch/tile/kernel/pci-dma.c +++ b/arch/tile/kernel/pci-dma.c @@ -244,7 +244,7 @@ EXPORT_SYMBOL(dma_sync_single_range_for_device); * dma_alloc_noncoherent() returns non-cacheable memory, so there's no * need to do any flushing here. */ -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { } diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index ea38f0c9ec7..6d4cb5d7a9f 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -1,5 +1,5 @@ /* - * Copyright 2010 Tilera Corporation. All Rights Reserved. + * Copyright 2011 Tilera Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -59,6 +59,7 @@ int __write_once tile_plx_gen1; static struct pci_controller controllers[TILE_NUM_PCIE]; static int num_controllers; +static int pci_scan_flags[TILE_NUM_PCIE]; static struct pci_ops tile_cfg_ops; @@ -79,7 +80,7 @@ EXPORT_SYMBOL(pcibios_align_resource); * controller_id is the controller number, config type is 0 or 1 for * config0 or config1 operations. */ -static int __init tile_pcie_open(int controller_id, int config_type) +static int __devinit tile_pcie_open(int controller_id, int config_type) { char filename[32]; int fd; @@ -95,7 +96,7 @@ static int __init tile_pcie_open(int controller_id, int config_type) /* * Get the IRQ numbers from the HV and set up the handlers for them. */ -static int __init tile_init_irqs(int controller_id, +static int __devinit tile_init_irqs(int controller_id, struct pci_controller *controller) { char filename[32]; @@ -139,71 +140,74 @@ static int __init tile_init_irqs(int controller_id, * * Returns the number of controllers discovered. */ -int __init tile_pci_init(void) +int __devinit tile_pci_init(void) { int i; pr_info("PCI: Searching for controllers...\n"); + /* Re-init number of PCIe controllers to support hot-plug feature. */ + num_controllers = 0; + /* Do any configuration we need before using the PCIe */ for (i = 0; i < TILE_NUM_PCIE; i++) { - int hv_cfg_fd0 = -1; - int hv_cfg_fd1 = -1; - int hv_mem_fd = -1; - char name[32]; - struct pci_controller *controller; - /* - * Open the fd to the HV. If it fails then this - * device doesn't exist. + * To see whether we need a real config op based on + * the results of pcibios_init(), to support PCIe hot-plug. */ - hv_cfg_fd0 = tile_pcie_open(i, 0); - if (hv_cfg_fd0 < 0) - continue; - hv_cfg_fd1 = tile_pcie_open(i, 1); - if (hv_cfg_fd1 < 0) { - pr_err("PCI: Couldn't open config fd to HV " - "for controller %d\n", i); - goto err_cont; - } - - sprintf(name, "pcie/%d/mem", i); - hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0); - if (hv_mem_fd < 0) { - pr_err("PCI: Could not open mem fd to HV!\n"); - goto err_cont; - } + if (pci_scan_flags[i] == 0) { + int hv_cfg_fd0 = -1; + int hv_cfg_fd1 = -1; + int hv_mem_fd = -1; + char name[32]; + struct pci_controller *controller; + + /* + * Open the fd to the HV. If it fails then this + * device doesn't exist. + */ + hv_cfg_fd0 = tile_pcie_open(i, 0); + if (hv_cfg_fd0 < 0) + continue; + hv_cfg_fd1 = tile_pcie_open(i, 1); + if (hv_cfg_fd1 < 0) { + pr_err("PCI: Couldn't open config fd to HV " + "for controller %d\n", i); + goto err_cont; + } - pr_info("PCI: Found PCI controller #%d\n", i); + sprintf(name, "pcie/%d/mem", i); + hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0); + if (hv_mem_fd < 0) { + pr_err("PCI: Could not open mem fd to HV!\n"); + goto err_cont; + } - controller = &controllers[num_controllers]; + pr_info("PCI: Found PCI controller #%d\n", i); - if (tile_init_irqs(i, controller)) { - pr_err("PCI: Could not initialize " - "IRQs, aborting.\n"); - goto err_cont; - } + controller = &controllers[i]; - controller->index = num_controllers; - controller->hv_cfg_fd[0] = hv_cfg_fd0; - controller->hv_cfg_fd[1] = hv_cfg_fd1; - controller->hv_mem_fd = hv_mem_fd; - controller->first_busno = 0; - controller->last_busno = 0xff; - controller->ops = &tile_cfg_ops; + controller->index = i; + controller->hv_cfg_fd[0] = hv_cfg_fd0; + controller->hv_cfg_fd[1] = hv_cfg_fd1; + controller->hv_mem_fd = hv_mem_fd; + controller->first_busno = 0; + controller->last_busno = 0xff; + controller->ops = &tile_cfg_ops; - num_controllers++; - continue; + num_controllers++; + continue; err_cont: - if (hv_cfg_fd0 >= 0) - hv_dev_close(hv_cfg_fd0); - if (hv_cfg_fd1 >= 0) - hv_dev_close(hv_cfg_fd1); - if (hv_mem_fd >= 0) - hv_dev_close(hv_mem_fd); - continue; + if (hv_cfg_fd0 >= 0) + hv_dev_close(hv_cfg_fd0); + if (hv_cfg_fd1 >= 0) + hv_dev_close(hv_cfg_fd1); + if (hv_mem_fd >= 0) + hv_dev_close(hv_mem_fd); + continue; + } } /* @@ -232,7 +236,7 @@ static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin) } -static void __init fixup_read_and_payload_sizes(void) +static void __devinit fixup_read_and_payload_sizes(void) { struct pci_dev *dev = NULL; int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */ @@ -282,7 +286,7 @@ static void __init fixup_read_and_payload_sizes(void) * The controllers have been set up by the time we get here, by a call to * tile_pci_init. */ -static int __init pcibios_init(void) +int __devinit pcibios_init(void) { int i; @@ -296,25 +300,36 @@ static int __init pcibios_init(void) mdelay(250); /* Scan all of the recorded PCI controllers. */ - for (i = 0; i < num_controllers; i++) { - struct pci_controller *controller = &controllers[i]; - struct pci_bus *bus; - - pr_info("PCI: initializing controller #%d\n", i); - + for (i = 0; i < TILE_NUM_PCIE; i++) { /* - * This comes from the generic Linux PCI driver. - * - * It reads the PCI tree for this bus into the Linux - * data structures. - * - * This is inlined in linux/pci.h and calls into - * pci_scan_bus_parented() in probe.c. + * Do real pcibios init ops if the controller is initialized + * by tile_pci_init() successfully and not initialized by + * pcibios_init() yet to support PCIe hot-plug. */ - bus = pci_scan_bus(0, controller->ops, controller); - controller->root_bus = bus; - controller->last_busno = bus->subordinate; + if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { + struct pci_controller *controller = &controllers[i]; + struct pci_bus *bus; + if (tile_init_irqs(i, controller)) { + pr_err("PCI: Could not initialize IRQs\n"); + continue; + } + + pr_info("PCI: initializing controller #%d\n", i); + + /* + * This comes from the generic Linux PCI driver. + * + * It reads the PCI tree for this bus into the Linux + * data structures. + * + * This is inlined in linux/pci.h and calls into + * pci_scan_bus_parented() in probe.c. + */ + bus = pci_scan_bus(0, controller->ops, controller); + controller->root_bus = bus; + controller->last_busno = bus->subordinate; + } } /* Do machine dependent PCI interrupt routing */ @@ -326,34 +341,45 @@ static int __init pcibios_init(void) * It allocates all of the resources (I/O memory, etc) * associated with the devices read in above. */ - pci_assign_unassigned_resources(); /* Configure the max_read_size and max_payload_size values. */ fixup_read_and_payload_sizes(); /* Record the I/O resources in the PCI controller structure. */ - for (i = 0; i < num_controllers; i++) { - struct pci_bus *root_bus = controllers[i].root_bus; - struct pci_bus *next_bus; - struct pci_dev *dev; - - list_for_each_entry(dev, &root_bus->devices, bus_list) { - /* Find the PCI host controller, ie. the 1st bridge. */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && - (PCI_SLOT(dev->devfn) == 0)) { - next_bus = dev->subordinate; - controllers[i].mem_resources[0] = - *next_bus->resource[0]; - controllers[i].mem_resources[1] = - *next_bus->resource[1]; - controllers[i].mem_resources[2] = - *next_bus->resource[2]; - - break; + for (i = 0; i < TILE_NUM_PCIE; i++) { + /* + * Do real pcibios init ops if the controller is initialized + * by tile_pci_init() successfully and not initialized by + * pcibios_init() yet to support PCIe hot-plug. + */ + if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { + struct pci_bus *root_bus = controllers[i].root_bus; + struct pci_bus *next_bus; + struct pci_dev *dev; + + list_for_each_entry(dev, &root_bus->devices, bus_list) { + /* + * Find the PCI host controller, ie. the 1st + * bridge. + */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && + (PCI_SLOT(dev->devfn) == 0)) { + next_bus = dev->subordinate; + controllers[i].mem_resources[0] = + *next_bus->resource[0]; + controllers[i].mem_resources[1] = + *next_bus->resource[1]; + controllers[i].mem_resources[2] = + *next_bus->resource[2]; + + /* Setup flags. */ + pci_scan_flags[i] = 1; + + break; + } } } - } return 0; @@ -381,7 +407,7 @@ char __devinit *pcibios_setup(char *str) /* * This is called from the generic Linux layer. */ -void __init pcibios_update_irq(struct pci_dev *dev, int irq) +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) { pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index d0065103eb7..9c45d8bbdf5 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -25,10 +25,13 @@ #include <linux/hardirq.h> #include <linux/syscalls.h> #include <linux/kernel.h> +#include <linux/tracehook.h> +#include <linux/signal.h> #include <asm/system.h> #include <asm/stack.h> #include <asm/homecache.h> #include <asm/syscalls.h> +#include <asm/traps.h> #ifdef CONFIG_HARDWALL #include <asm/hardwall.h> #endif @@ -546,6 +549,51 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, return __switch_to(prev, next, next_current_ksp0(next)); } +/* + * This routine is called on return from interrupt if any of the + * TIF_WORK_MASK flags are set in thread_info->flags. It is + * entered with interrupts disabled so we don't miss an event + * that modified the thread_info flags. If any flag is set, we + * handle it and return, and the calling assembly code will + * re-disable interrupts, reload the thread flags, and call back + * if more flags need to be handled. + * + * We return whether we need to check the thread_info flags again + * or not. Note that we don't clear TIF_SINGLESTEP here, so it's + * important that it be tested last, and then claim that we don't + * need to recheck the flags. + */ +int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) +{ + if (thread_info_flags & _TIF_NEED_RESCHED) { + schedule(); + return 1; + } +#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() + if (thread_info_flags & _TIF_ASYNC_TLB) { + do_async_page_fault(regs); + return 1; + } +#endif + if (thread_info_flags & _TIF_SIGPENDING) { + do_signal(regs); + return 1; + } + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + return 1; + } + if (thread_info_flags & _TIF_SINGLESTEP) { + if ((regs->ex1 & SPR_EX_CONTEXT_1_1__PL_MASK) == 0) + single_step_once(regs); + return 0; + } + panic("work_pending: bad flags %#x\n", thread_info_flags); +} + /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, void __user *, parent_tidptr, void __user *, child_tidptr, @@ -582,8 +630,8 @@ out: #ifdef CONFIG_COMPAT long compat_sys_execve(const char __user *path, - const compat_uptr_t __user *argv, - const compat_uptr_t __user *envp, + compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs *regs) { long error; diff --git a/arch/tile/kernel/regs_64.S b/arch/tile/kernel/regs_64.S new file mode 100644 index 00000000000..f748c1e8528 --- /dev/null +++ b/arch/tile/kernel/regs_64.S @@ -0,0 +1,145 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/linkage.h> +#include <asm/system.h> +#include <asm/ptrace.h> +#include <asm/asm-offsets.h> +#include <arch/spr_def.h> +#include <asm/processor.h> + +/* + * See <asm/system.h>; called with prev and next task_struct pointers. + * "prev" is returned in r0 for _switch_to and also for ret_from_fork. + * + * We want to save pc/sp in "prev", and get the new pc/sp from "next". + * We also need to save all the callee-saved registers on the stack. + * + * Intel enables/disables access to the hardware cycle counter in + * seccomp (secure computing) environments if necessary, based on + * has_secure_computing(). We might want to do this at some point, + * though it would require virtualizing the other SPRs under WORLD_ACCESS. + * + * Since we're saving to the stack, we omit sp from this list. + * And for parallels with other architectures, we save lr separately, + * in the thread_struct itself (as the "pc" field). + * + * This code also needs to be aligned with process.c copy_thread() + */ + +#if CALLEE_SAVED_REGS_COUNT != 24 +# error Mismatch between <asm/system.h> and kernel/entry.S +#endif +#define FRAME_SIZE ((2 + CALLEE_SAVED_REGS_COUNT) * 8) + +#define SAVE_REG(r) { st r12, r; addi r12, r12, 8 } +#define LOAD_REG(r) { ld r, r12; addi r12, r12, 8 } +#define FOR_EACH_CALLEE_SAVED_REG(f) \ + f(r30); f(r31); \ + f(r32); f(r33); f(r34); f(r35); f(r36); f(r37); f(r38); f(r39); \ + f(r40); f(r41); f(r42); f(r43); f(r44); f(r45); f(r46); f(r47); \ + f(r48); f(r49); f(r50); f(r51); f(r52); + +STD_ENTRY_SECTION(__switch_to, .sched.text) + { + move r10, sp + st sp, lr + } + { + addli r11, sp, -FRAME_SIZE + 8 + addli sp, sp, -FRAME_SIZE + } + { + st r11, r10 + addli r4, r1, TASK_STRUCT_THREAD_KSP_OFFSET + } + { + ld r13, r4 /* Load new sp to a temp register early. */ + addi r12, sp, 16 + } + FOR_EACH_CALLEE_SAVED_REG(SAVE_REG) + addli r3, r0, TASK_STRUCT_THREAD_KSP_OFFSET + { + st r3, sp + addli r3, r0, TASK_STRUCT_THREAD_PC_OFFSET + } + { + st r3, lr + addli r4, r1, TASK_STRUCT_THREAD_PC_OFFSET + } + { + ld lr, r4 + addi r12, r13, 16 + } + { + /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */ + move sp, r13 + mtspr SPR_SYSTEM_SAVE_K_0, r2 + } + FOR_EACH_CALLEE_SAVED_REG(LOAD_REG) +.L__switch_to_pc: + { + addli sp, sp, FRAME_SIZE + jrp lr /* r0 is still valid here, so return it */ + } + STD_ENDPROC(__switch_to) + +/* Return a suitable address for the backtracer for suspended threads */ +STD_ENTRY_SECTION(get_switch_to_pc, .sched.text) + lnk r0 + { + addli r0, r0, .L__switch_to_pc - . + jrp lr + } + STD_ENDPROC(get_switch_to_pc) + +STD_ENTRY(get_pt_regs) + .irp reg, r0, r1, r2, r3, r4, r5, r6, r7, \ + r8, r9, r10, r11, r12, r13, r14, r15, \ + r16, r17, r18, r19, r20, r21, r22, r23, \ + r24, r25, r26, r27, r28, r29, r30, r31, \ + r32, r33, r34, r35, r36, r37, r38, r39, \ + r40, r41, r42, r43, r44, r45, r46, r47, \ + r48, r49, r50, r51, r52, tp, sp + { + st r0, \reg + addi r0, r0, 8 + } + .endr + { + st r0, lr + addi r0, r0, PTREGS_OFFSET_PC - PTREGS_OFFSET_LR + } + lnk r1 + { + st r0, r1 + addi r0, r0, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC + } + mfspr r1, INTERRUPT_CRITICAL_SECTION + shli r1, r1, SPR_EX_CONTEXT_1_1__ICS_SHIFT + ori r1, r1, KERNEL_PL + { + st r0, r1 + addi r0, r0, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 + } + { + st r0, zero /* clear faultnum */ + addi r0, r0, PTREGS_OFFSET_ORIG_R0 - PTREGS_OFFSET_FAULTNUM + } + { + st r0, zero /* clear orig_r0 */ + addli r0, r0, -PTREGS_OFFSET_ORIG_R0 /* restore r0 to base */ + } + jrp lr + STD_ENDPROC(get_pt_regs) diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 3696b183256..6cdc9ba55fe 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -912,6 +912,8 @@ void __cpuinit setup_cpu(int boot) #endif } +#ifdef CONFIG_BLK_DEV_INITRD + static int __initdata set_initramfs_file; static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; @@ -969,6 +971,10 @@ void __init free_initrd_mem(unsigned long begin, unsigned long end) free_bootmem(__pa(begin), end - begin); } +#else +static inline void load_hv_initrd(void) {} +#endif /* CONFIG_BLK_DEV_INITRD */ + static void __init validate_hv(void) { /* diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 1260321155f..bedaf4e9f3a 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -39,7 +39,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, stack_t __user *, uoss, struct pt_regs *, regs) { @@ -78,6 +77,13 @@ int restore_sigcontext(struct pt_regs *regs, return err; } +void signal_fault(const char *type, struct pt_regs *regs, + void __user *frame, int sig) +{ + trace_unhandled_signal(type, regs, (unsigned long)frame, SIGSEGV); + force_sigsegv(sig, current); +} + /* The assembly shim for this function arranges to ignore the return value. */ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) { @@ -105,7 +111,7 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) return 0; badframe: - force_sig(SIGSEGV, current); + signal_fault("bad sigreturn frame", regs, frame, 0); return 0; } @@ -231,7 +237,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sigsegv(sig, current); + signal_fault("bad setup frame", regs, frame, sig); return -EFAULT; } @@ -245,7 +251,6 @@ static int handle_signal(unsigned long sig, siginfo_t *info, { int ret; - /* Are we from a system call? */ if (regs->faultnum == INT_SWINT_1) { /* If so, check system call restarting.. */ @@ -363,3 +368,118 @@ done: /* Avoid double syscall restart if there are nested signals. */ regs->faultnum = INT_SWINT_1_SIGRETURN; } + +int show_unhandled_signals = 1; + +static int __init crashinfo(char *str) +{ + unsigned long val; + const char *word; + + if (*str == '\0') + val = 2; + else if (*str != '=' || strict_strtoul(++str, 0, &val) != 0) + return 0; + show_unhandled_signals = val; + switch (show_unhandled_signals) { + case 0: + word = "No"; + break; + case 1: + word = "One-line"; + break; + default: + word = "Detailed"; + break; + } + pr_info("%s crash reports will be generated on the console\n", word); + return 1; +} +__setup("crashinfo", crashinfo); + +static void dump_mem(void __user *address) +{ + void __user *addr; + enum { region_size = 256, bytes_per_line = 16 }; + int i, j, k; + int found_readable_mem = 0; + + pr_err("\n"); + if (!access_ok(VERIFY_READ, address, 1)) { + pr_err("Not dumping at address 0x%lx (kernel address)\n", + (unsigned long)address); + return; + } + + addr = (void __user *) + (((unsigned long)address & -bytes_per_line) - region_size/2); + if (addr > address) + addr = NULL; + for (i = 0; i < region_size; + addr += bytes_per_line, i += bytes_per_line) { + unsigned char buf[bytes_per_line]; + char line[100]; + if (copy_from_user(buf, addr, bytes_per_line)) + continue; + if (!found_readable_mem) { + pr_err("Dumping memory around address 0x%lx:\n", + (unsigned long)address); + found_readable_mem = 1; + } + j = sprintf(line, REGFMT":", (unsigned long)addr); + for (k = 0; k < bytes_per_line; ++k) + j += sprintf(&line[j], " %02x", buf[k]); + pr_err("%s\n", line); + } + if (!found_readable_mem) + pr_err("No readable memory around address 0x%lx\n", + (unsigned long)address); +} + +void trace_unhandled_signal(const char *type, struct pt_regs *regs, + unsigned long address, int sig) +{ + struct task_struct *tsk = current; + + if (show_unhandled_signals == 0) + return; + + /* If the signal is handled, don't show it here. */ + if (!is_global_init(tsk)) { + void __user *handler = + tsk->sighand->action[sig-1].sa.sa_handler; + if (handler != SIG_IGN && handler != SIG_DFL) + return; + } + + /* Rate-limit the one-line output, not the detailed output. */ + if (show_unhandled_signals <= 1 && !printk_ratelimit()) + return; + + printk("%s%s[%d]: %s at %lx pc "REGFMT" signal %d", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), type, address, regs->pc, sig); + + print_vma_addr(KERN_CONT " in ", regs->pc); + + printk(KERN_CONT "\n"); + + if (show_unhandled_signals > 1) { + switch (sig) { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + pr_err("User crash: signal %d," + " trap %ld, address 0x%lx\n", + sig, regs->faultnum, address); + show_regs(regs); + dump_mem((void __user *)address); + break; + default: + pr_err("User crash: signal %d, trap %ld\n", + sig, regs->faultnum); + break; + } + } +} diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index 84a729e06ec..4032ca8e51b 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c @@ -186,6 +186,8 @@ static tile_bundle_bits rewrite_load_store_unaligned( .si_code = SEGV_MAPERR, .si_addr = addr }; + trace_unhandled_signal("segfault", regs, + (unsigned long)addr, SIGSEGV); force_sig_info(info.si_signo, &info, current); return (tile_bundle_bits) 0; } @@ -196,6 +198,8 @@ static tile_bundle_bits rewrite_load_store_unaligned( .si_code = BUS_ADRALN, .si_addr = addr }; + trace_unhandled_signal("unaligned trap", regs, + (unsigned long)addr, SIGBUS); force_sig_info(info.si_signo, &info, current); return (tile_bundle_bits) 0; } @@ -318,6 +322,14 @@ void single_step_once(struct pt_regs *regs) " .popsection\n" ); + /* + * Enable interrupts here to allow touching userspace and the like. + * The callers expect this: do_trap() already has interrupts + * enabled, and do_work_pending() handles functions that enable + * interrupts internally. + */ + local_irq_enable(); + if (state == NULL) { /* allocate a page of writable, executable memory */ state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index dd81713a90d..37ee4d037e0 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -36,7 +36,7 @@ #define KBT_LOOP 3 /* Backtrace entered a loop */ /* Is address on the specified kernel stack? */ -static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) +static int in_kernel_stack(struct KBacktraceIterator *kbt, unsigned long sp) { ulong kstack_base = (ulong) kbt->task->stack; if (kstack_base == 0) /* corrupt task pointer; just follow stack... */ @@ -45,7 +45,7 @@ static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) } /* Is address valid for reading? */ -static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) +static int valid_address(struct KBacktraceIterator *kbt, unsigned long address) { HV_PTE *l1_pgtable = kbt->pgtable; HV_PTE *l2_pgtable; @@ -97,7 +97,7 @@ static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) } /* Callback for backtracer; basically a glorified memcpy */ -static bool read_memory_func(void *result, VirtualAddress address, +static bool read_memory_func(void *result, unsigned long address, unsigned int size, void *vkbt) { int retval; @@ -124,7 +124,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) { const char *fault = NULL; /* happy compiler */ char fault_buf[64]; - VirtualAddress sp = kbt->it.sp; + unsigned long sp = kbt->it.sp; struct pt_regs *p; if (!in_kernel_stack(kbt, sp)) @@ -163,7 +163,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) } /* Is the pc pointing to a sigreturn trampoline? */ -static int is_sigreturn(VirtualAddress pc) +static int is_sigreturn(unsigned long pc) { return (pc == VDSO_BASE); } @@ -260,7 +260,7 @@ static void validate_stack(struct pt_regs *regs) void KBacktraceIterator_init(struct KBacktraceIterator *kbt, struct task_struct *t, struct pt_regs *regs) { - VirtualAddress pc, lr, sp, r52; + unsigned long pc, lr, sp, r52; int is_current; /* @@ -331,7 +331,7 @@ EXPORT_SYMBOL(KBacktraceIterator_end); void KBacktraceIterator_next(struct KBacktraceIterator *kbt) { - VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp; + unsigned long old_pc = kbt->it.pc, old_sp = kbt->it.sp; kbt->new_context = 0; if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) { kbt->end = KBT_DONE; diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c index e2187d24a9b..cb44ba7ccd2 100644 --- a/arch/tile/kernel/sys.c +++ b/arch/tile/kernel/sys.c @@ -56,13 +56,6 @@ ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count) return sys_readahead(fd, ((loff_t)offset_hi << 32) | offset_lo, count); } -long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi, - u32 len, int advice) -{ - return sys_fadvise64_64(fd, ((loff_t)offset_hi << 32) | offset_lo, - len, advice); -} - int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, u32 len_lo, u32 len_hi, int advice) { @@ -103,10 +96,8 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, #ifndef __tilegx__ /* See comments at the top of the file. */ -#define sys_fadvise64 sys32_fadvise64 #define sys_fadvise64_64 sys32_fadvise64_64 #define sys_readahead sys32_readahead -#define sys_sync_file_range sys_sync_file_range2 #endif /* Call the trampolines to manage pt_regs where necessary. */ diff --git a/arch/tile/kernel/tile-desc_32.c b/arch/tile/kernel/tile-desc_32.c index 69af0e150f7..7e31a128578 100644 --- a/arch/tile/kernel/tile-desc_32.c +++ b/arch/tile/kernel/tile-desc_32.c @@ -2413,12 +2413,13 @@ const struct tile_operand tile_operands[43] = -/* Given a set of bundle bits and the lookup FSM for a specific pipe, - * returns which instruction the bundle contains in that pipe. +/* Given a set of bundle bits and a specific pipe, returns which + * instruction the bundle contains in that pipe. */ -static const struct tile_opcode * -find_opcode(tile_bundle_bits bits, const unsigned short *table) +const struct tile_opcode * +find_opcode(tile_bundle_bits bits, tile_pipeline pipe) { + const unsigned short *table = tile_bundle_decoder_fsms[pipe]; int index = 0; while (1) @@ -2465,7 +2466,7 @@ parse_insn_tile(tile_bundle_bits bits, int i; d = &decoded[num_instructions++]; - opc = find_opcode (bits, tile_bundle_decoder_fsms[pipe]); + opc = find_opcode (bits, (tile_pipeline)pipe); d->opcode = opc; /* Decode each operand, sign extending, etc. as appropriate. */ diff --git a/arch/tile/kernel/tile-desc_64.c b/arch/tile/kernel/tile-desc_64.c new file mode 100644 index 00000000000..d57007bed77 --- /dev/null +++ b/arch/tile/kernel/tile-desc_64.c @@ -0,0 +1,2200 @@ +/* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */ +#define BFD_RELOC(x) -1 + +/* Special registers. */ +#define TREG_LR 55 +#define TREG_SN 56 +#define TREG_ZERO 63 + +/* FIXME: Rename this. */ +#include <asm/opcode-tile_64.h> + +#include <linux/stddef.h> + +const struct tilegx_opcode tilegx_opcodes[334] = +{ + { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1, + { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } }, + }, + { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1, + { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } }, + }, + { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1, + { { 6, 7 }, { 8, 9 }, { 10, 11 }, { 12, 13 }, { 0, } }, + }, + { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1, + { { 6, 0 }, { 8, 1 }, { 10, 2 }, { 12, 3 }, { 0, } }, + }, + { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1, + { { 6, 4 }, { 8, 5 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, + }, + { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, + }, + { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, + }, + { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, + }, + { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, + }, + { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, + }, + { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1, + { { 6, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1, + { { 6, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1, + { { 23, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, + }, + { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, + }, + { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, + }, + { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1, + { { }, { }, { }, { }, { 0, } }, + }, + { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1, + { { 0, }, { }, { 0, }, { }, { 0, } }, + }, + { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, + }, + { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1, + { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, + }, + { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1, + { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, + }, + { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1, + { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, + }, + { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, + }, + { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, + }, + { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, + }, + { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1, + { { 0, }, { 8 }, { 0, }, { 12 }, { 0, } }, + }, + { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 8, 27 }, { 0, }, { 0, }, { 0, } }, + }, + { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1, + { { 23, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 28, 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, + }, + { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, + }, + { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, + }, + { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, + }, + { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, + }, + { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, + }, + { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1, + { { }, { }, { }, { }, { 0, } }, + }, + { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1, + { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, + }, + { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, + }, + { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, + }, + { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, + }, + { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, + }, + { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, + }, + { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, + }, + { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, + }, + { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, + }, + { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, + }, + { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1, + { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1, + { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, + }, + { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0, + { { 0, }, { }, { 0, }, { 0, }, { 0, } }, + }, + { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1, + { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, + }, + { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1, + { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, + }, + { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1, + { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, + }, + { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1, + { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, + }, + { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1, + { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, + }, + { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1, + { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, + }, + { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1, + { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, + }, + { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1, + { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, + }, + { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } }, + } +}; +#define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6)) +#define CHILD(array_index) (TILEGX_OPC_NONE + (array_index)) + +static const unsigned short decode_X0_fsm[936] = +{ + BITFIELD(22, 9) /* index 0 */, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS, + TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU, + TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS, + TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM, + TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578), + CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671), + CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865), + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), + BITFIELD(6, 2) /* index 513 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), + BITFIELD(8, 2) /* index 518 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), + BITFIELD(10, 2) /* index 523 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, + BITFIELD(20, 2) /* index 528 */, + TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), + BITFIELD(6, 2) /* index 533 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), + BITFIELD(8, 2) /* index 538 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), + BITFIELD(10, 2) /* index 543 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, + BITFIELD(0, 2) /* index 548 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), + BITFIELD(2, 2) /* index 553 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), + BITFIELD(4, 2) /* index 558 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), + BITFIELD(6, 2) /* index 563 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), + BITFIELD(8, 2) /* index 568 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), + BITFIELD(10, 2) /* index 573 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, + BITFIELD(20, 2) /* index 578 */, + TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI, + BITFIELD(20, 2) /* index 583 */, + TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI, + TILEGX_OPC_V1CMPLTUI, + BITFIELD(20, 2) /* index 588 */, + TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI, + TILEGX_OPC_V2CMPEQI, + BITFIELD(20, 2) /* index 593 */, + TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI, + TILEGX_OPC_V2MINSI, + BITFIELD(20, 2) /* index 598 */, + TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(18, 4) /* index 603 */, + TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, + TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ, + TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, + TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR, + BITFIELD(18, 4) /* index 620 */, + TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL, + TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2, + TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN, + TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS, + TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1, + TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS, + BITFIELD(18, 4) /* index 637 */, + TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN, + TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2, + TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2, + TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX, + TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS, + TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS, + BITFIELD(18, 4) /* index 654 */, + TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU, + TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS, + TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU, + TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU, + TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU, + TILEGX_OPC_MZ, + BITFIELD(18, 4) /* index 671 */, + TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, + TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES, + TILEGX_OPC_SUBXSC, + BITFIELD(12, 2) /* index 688 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693), + BITFIELD(14, 2) /* index 693 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698), + BITFIELD(16, 2) /* index 698 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, + BITFIELD(18, 4) /* index 703 */, + TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC, + TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU, + TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, + TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, + TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA, + BITFIELD(12, 4) /* index 720 */, + TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757), + CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787), + CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 737 */, + TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 742 */, + TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 747 */, + TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 752 */, + TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 757 */, + TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 762 */, + TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 767 */, + TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 772 */, + TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 777 */, + TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 782 */, + TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 787 */, + TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(16, 2) /* index 792 */, + TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(18, 4) /* index 797 */, + TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP, + TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU, + TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS, + TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU, + TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, + BITFIELD(18, 4) /* index 814 */, + TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, + TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS, + TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, + TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE, + TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H, + BITFIELD(18, 4) /* index 831 */, + TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, + TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ, + TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, + TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS, + TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC, + BITFIELD(18, 4) /* index 848 */, + TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC, + TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, + TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, + TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, + TILEGX_OPC_V4SUB, + BITFIELD(18, 3) /* index 865 */, + CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(21, 1) /* index 874 */, + TILEGX_OPC_XOR, TILEGX_OPC_NONE, + BITFIELD(21, 1) /* index 877 */, + TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE, + BITFIELD(21, 1) /* index 880 */, + TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE, + BITFIELD(21, 1) /* index 883 */, + TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE, + BITFIELD(21, 1) /* index 886 */, + TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE, + BITFIELD(18, 4) /* index 889 */, + TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, + TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, + TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, + TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, + BITFIELD(0, 2) /* index 906 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(911), + BITFIELD(2, 2) /* index 911 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(916), + BITFIELD(4, 2) /* index 916 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(921), + BITFIELD(6, 2) /* index 921 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(926), + BITFIELD(8, 2) /* index 926 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(931), + BITFIELD(10, 2) /* index 931 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + TILEGX_OPC_INFOL, +}; + +static const unsigned short decode_X1_fsm[1206] = +{ + BITFIELD(53, 9) /* index 0 */, + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), + CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, + TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT, + TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT, + TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT, + TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT, + TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST, + TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT, + TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT, + TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT, + TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578), + CHILD(598), CHILD(663), CHILD(683), CHILD(688), CHILD(693), CHILD(698), + CHILD(703), CHILD(708), CHILD(713), CHILD(718), TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, + TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, + CHILD(723), CHILD(740), CHILD(772), CHILD(789), CHILD(1108), CHILD(1125), + CHILD(1142), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1159), TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), + CHILD(1176), + BITFIELD(37, 2) /* index 513 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), + BITFIELD(39, 2) /* index 518 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), + BITFIELD(41, 2) /* index 523 */, + TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, + BITFIELD(51, 2) /* index 528 */, + TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), + BITFIELD(37, 2) /* index 533 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), + BITFIELD(39, 2) /* index 538 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), + BITFIELD(41, 2) /* index 543 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, + BITFIELD(31, 2) /* index 548 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), + BITFIELD(33, 2) /* index 553 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), + BITFIELD(35, 2) /* index 558 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), + BITFIELD(37, 2) /* index 563 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), + BITFIELD(39, 2) /* index 568 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), + BITFIELD(41, 2) /* index 573 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, + BITFIELD(51, 2) /* index 578 */, + TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583), + BITFIELD(31, 2) /* index 583 */, + TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588), + BITFIELD(33, 2) /* index 588 */, + TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593), + BITFIELD(35, 2) /* index 593 */, + TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, + TILEGX_OPC_PREFETCH_ADD_L1_FAULT, + BITFIELD(51, 2) /* index 598 */, + CHILD(603), CHILD(618), CHILD(633), CHILD(648), + BITFIELD(31, 2) /* index 603 */, + TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608), + BITFIELD(33, 2) /* index 608 */, + TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613), + BITFIELD(35, 2) /* index 613 */, + TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, + TILEGX_OPC_PREFETCH_ADD_L1, + BITFIELD(31, 2) /* index 618 */, + TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623), + BITFIELD(33, 2) /* index 623 */, + TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628), + BITFIELD(35, 2) /* index 628 */, + TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, + TILEGX_OPC_PREFETCH_ADD_L2_FAULT, + BITFIELD(31, 2) /* index 633 */, + TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638), + BITFIELD(33, 2) /* index 638 */, + TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643), + BITFIELD(35, 2) /* index 643 */, + TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, + TILEGX_OPC_PREFETCH_ADD_L2, + BITFIELD(31, 2) /* index 648 */, + TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, CHILD(653), + BITFIELD(33, 2) /* index 653 */, + TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, CHILD(658), + BITFIELD(35, 2) /* index 658 */, + TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, + TILEGX_OPC_PREFETCH_ADD_L3_FAULT, + BITFIELD(51, 2) /* index 663 */, + CHILD(668), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD, + TILEGX_OPC_LDNT2S_ADD, + BITFIELD(31, 2) /* index 668 */, + TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(673), + BITFIELD(33, 2) /* index 673 */, + TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(678), + BITFIELD(35, 2) /* index 678 */, + TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, + TILEGX_OPC_PREFETCH_ADD_L3, + BITFIELD(51, 2) /* index 683 */, + TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD, + TILEGX_OPC_LDNT_ADD, + BITFIELD(51, 2) /* index 688 */, + TILEGX_OPC_LD_ADD, TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR, + BITFIELD(51, 2) /* index 693 */, + TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD, + BITFIELD(51, 2) /* index 698 */, + TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD, + TILEGX_OPC_STNT_ADD, + BITFIELD(51, 2) /* index 703 */, + TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, + TILEGX_OPC_V1CMPLTSI, + BITFIELD(51, 2) /* index 708 */, + TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, + TILEGX_OPC_V2ADDI, + BITFIELD(51, 2) /* index 713 */, + TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, + TILEGX_OPC_V2MAXSI, + BITFIELD(51, 2) /* index 718 */, + TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(49, 4) /* index 723 */, + TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, + TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH, + TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, + TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, + TILEGX_OPC_DBLALIGN6, + BITFIELD(49, 4) /* index 740 */, + TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4, + TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD, + TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4, + TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR, + CHILD(757), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, + BITFIELD(43, 2) /* index 757 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(762), + BITFIELD(45, 2) /* index 762 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(767), + BITFIELD(47, 2) /* index 767 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, + BITFIELD(49, 4) /* index 772 */, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, + TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1, + TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2, + TILEGX_OPC_STNT4, + BITFIELD(46, 7) /* index 789 */, + TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, + TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, + TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, + TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC, + TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, + TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX, + TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, + TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, + TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, + TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(918), CHILD(927), + CHILD(1006), CHILD(1090), CHILD(1099), TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, + TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, + TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, + TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, + TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, + TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, + TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, + TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, + TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, + TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, + TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, + TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, + TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, + TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, + TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, + TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, + TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, + TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, + TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, + TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, + TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, + TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, + TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, + TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, + TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, + TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, + BITFIELD(43, 3) /* index 918 */, + TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV, + TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH, + BITFIELD(43, 3) /* index 927 */, + CHILD(936), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP, + TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(991), + BITFIELD(31, 2) /* index 936 */, + CHILD(941), CHILD(966), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(33, 2) /* index 941 */, + TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(946), + BITFIELD(35, 2) /* index 946 */, + TILEGX_OPC_ILL, CHILD(951), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(37, 2) /* index 951 */, + TILEGX_OPC_ILL, CHILD(956), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(39, 2) /* index 956 */, + TILEGX_OPC_ILL, CHILD(961), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(41, 2) /* index 961 */, + TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL, + BITFIELD(33, 2) /* index 966 */, + TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(971), + BITFIELD(35, 2) /* index 971 */, + TILEGX_OPC_ILL, CHILD(976), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(37, 2) /* index 976 */, + TILEGX_OPC_ILL, CHILD(981), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(39, 2) /* index 981 */, + TILEGX_OPC_ILL, CHILD(986), TILEGX_OPC_ILL, TILEGX_OPC_ILL, + BITFIELD(41, 2) /* index 986 */, + TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL, + BITFIELD(31, 2) /* index 991 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(996), + BITFIELD(33, 2) /* index 996 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1001), + BITFIELD(35, 2) /* index 1001 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, + TILEGX_OPC_PREFETCH_L1_FAULT, + BITFIELD(43, 3) /* index 1006 */, + CHILD(1015), CHILD(1030), CHILD(1045), CHILD(1060), CHILD(1075), + TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U, + BITFIELD(31, 2) /* index 1015 */, + TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1020), + BITFIELD(33, 2) /* index 1020 */, + TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1025), + BITFIELD(35, 2) /* index 1025 */, + TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, + BITFIELD(31, 2) /* index 1030 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1035), + BITFIELD(33, 2) /* index 1035 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1040), + BITFIELD(35, 2) /* index 1040 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, + TILEGX_OPC_PREFETCH_L2_FAULT, + BITFIELD(31, 2) /* index 1045 */, + TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1050), + BITFIELD(33, 2) /* index 1050 */, + TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1055), + BITFIELD(35, 2) /* index 1055 */, + TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, + BITFIELD(31, 2) /* index 1060 */, + TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1065), + BITFIELD(33, 2) /* index 1065 */, + TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1070), + BITFIELD(35, 2) /* index 1070 */, + TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, + TILEGX_OPC_PREFETCH_L3_FAULT, + BITFIELD(31, 2) /* index 1075 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1080), + BITFIELD(33, 2) /* index 1080 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1085), + BITFIELD(35, 2) /* index 1085 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, + BITFIELD(43, 3) /* index 1090 */, + TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U, + TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF, + BITFIELD(43, 3) /* index 1099 */, + TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1, + TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE, + BITFIELD(49, 4) /* index 1108 */, + TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ, + TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, + TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ, + TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, + TILEGX_OPC_V2CMPLTU, + BITFIELD(49, 4) /* index 1125 */, + TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L, + TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ, + TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, + TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, + TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB, + BITFIELD(49, 4) /* index 1142 */, + TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, + TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, + TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, + TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(49, 4) /* index 1159 */, + TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, + TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, + TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, + TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, + BITFIELD(31, 2) /* index 1176 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(1181), + BITFIELD(33, 2) /* index 1181 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(1186), + BITFIELD(35, 2) /* index 1186 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(1191), + BITFIELD(37, 2) /* index 1191 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(1196), + BITFIELD(39, 2) /* index 1196 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + CHILD(1201), + BITFIELD(41, 2) /* index 1201 */, + TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, + TILEGX_OPC_INFOL, +}; + +static const unsigned short decode_Y0_fsm[178] = +{ + BITFIELD(27, 4) /* index 0 */, + CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, + TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123), + CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168), + CHILD(173), + BITFIELD(6, 2) /* index 17 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), + BITFIELD(8, 2) /* index 22 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), + BITFIELD(10, 2) /* index 27 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, + BITFIELD(0, 2) /* index 32 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), + BITFIELD(2, 2) /* index 37 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), + BITFIELD(4, 2) /* index 42 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), + BITFIELD(6, 2) /* index 47 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), + BITFIELD(8, 2) /* index 52 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), + BITFIELD(10, 2) /* index 57 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, + BITFIELD(18, 2) /* index 62 */, + TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, + BITFIELD(15, 5) /* index 67 */, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, + TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, + TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100), + CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(12, 3) /* index 100 */, + TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP, + TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT, + TILEGX_OPC_REVBITS, + BITFIELD(12, 3) /* index 109 */, + TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1, + TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + TILEGX_OPC_NONE, + BITFIELD(18, 2) /* index 118 */, + TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, + BITFIELD(18, 2) /* index 123 */, + TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX, + BITFIELD(18, 2) /* index 128 */, + TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, + BITFIELD(18, 2) /* index 133 */, + TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR, + BITFIELD(12, 2) /* index 138 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143), + BITFIELD(14, 2) /* index 143 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148), + BITFIELD(16, 2) /* index 148 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, + BITFIELD(18, 2) /* index 153 */, + TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, + BITFIELD(18, 2) /* index 158 */, + TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, + TILEGX_OPC_SHL3ADDX, + BITFIELD(18, 2) /* index 163 */, + TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS, + TILEGX_OPC_MUL_LU_LU, + BITFIELD(18, 2) /* index 168 */, + TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS, + TILEGX_OPC_MULA_LU_LU, + BITFIELD(18, 2) /* index 173 */, + TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, +}; + +static const unsigned short decode_Y1_fsm[167] = +{ + BITFIELD(58, 4) /* index 0 */, + TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, + TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122), + CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE, + BITFIELD(37, 2) /* index 17 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), + BITFIELD(39, 2) /* index 22 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), + BITFIELD(41, 2) /* index 27 */, + TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, + BITFIELD(31, 2) /* index 32 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), + BITFIELD(33, 2) /* index 37 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), + BITFIELD(35, 2) /* index 42 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), + BITFIELD(37, 2) /* index 47 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), + BITFIELD(39, 2) /* index 52 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), + BITFIELD(41, 2) /* index 57 */, + TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, + BITFIELD(49, 2) /* index 62 */, + TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, + BITFIELD(47, 4) /* index 67 */, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, + TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, + TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, + TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84), + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, + BITFIELD(43, 3) /* index 84 */, + CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108), + CHILD(111), CHILD(114), + BITFIELD(46, 1) /* index 93 */, + TILEGX_OPC_NONE, TILEGX_OPC_FNOP, + BITFIELD(46, 1) /* index 96 */, + TILEGX_OPC_NONE, TILEGX_OPC_ILL, + BITFIELD(46, 1) /* index 99 */, + TILEGX_OPC_NONE, TILEGX_OPC_JALRP, + BITFIELD(46, 1) /* index 102 */, + TILEGX_OPC_NONE, TILEGX_OPC_JALR, + BITFIELD(46, 1) /* index 105 */, + TILEGX_OPC_NONE, TILEGX_OPC_JRP, + BITFIELD(46, 1) /* index 108 */, + TILEGX_OPC_NONE, TILEGX_OPC_JR, + BITFIELD(46, 1) /* index 111 */, + TILEGX_OPC_NONE, TILEGX_OPC_LNK, + BITFIELD(46, 1) /* index 114 */, + TILEGX_OPC_NONE, TILEGX_OPC_NOP, + BITFIELD(49, 2) /* index 117 */, + TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, + BITFIELD(49, 2) /* index 122 */, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, + BITFIELD(49, 2) /* index 127 */, + TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, + BITFIELD(49, 2) /* index 132 */, + TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR, + BITFIELD(43, 2) /* index 137 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142), + BITFIELD(45, 2) /* index 142 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147), + BITFIELD(47, 2) /* index 147 */, + TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, + BITFIELD(49, 2) /* index 152 */, + TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, + BITFIELD(49, 2) /* index 157 */, + TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, + TILEGX_OPC_SHL3ADDX, + BITFIELD(49, 2) /* index 162 */, + TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, +}; + +static const unsigned short decode_Y2_fsm[118] = +{ + BITFIELD(62, 2) /* index 0 */, + TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109), + BITFIELD(55, 3) /* index 5 */, + CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40), + CHILD(43), + BITFIELD(26, 1) /* index 14 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1U, + BITFIELD(26, 1) /* index 17 */, + CHILD(20), CHILD(30), + BITFIELD(51, 2) /* index 20 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25), + BITFIELD(53, 2) /* index 25 */, + TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, + TILEGX_OPC_PREFETCH_L1_FAULT, + BITFIELD(51, 2) /* index 30 */, + TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35), + BITFIELD(53, 2) /* index 35 */, + TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, + BITFIELD(26, 1) /* index 40 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2U, + BITFIELD(26, 1) /* index 43 */, + CHILD(46), CHILD(56), + BITFIELD(51, 2) /* index 46 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51), + BITFIELD(53, 2) /* index 51 */, + TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, + TILEGX_OPC_PREFETCH_L2_FAULT, + BITFIELD(51, 2) /* index 56 */, + TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61), + BITFIELD(53, 2) /* index 61 */, + TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, + BITFIELD(56, 2) /* index 66 */, + CHILD(71), CHILD(74), CHILD(90), CHILD(93), + BITFIELD(26, 1) /* index 71 */, + TILEGX_OPC_NONE, TILEGX_OPC_LD4S, + BITFIELD(26, 1) /* index 74 */, + TILEGX_OPC_NONE, CHILD(77), + BITFIELD(51, 2) /* index 77 */, + TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82), + BITFIELD(53, 2) /* index 82 */, + TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87), + BITFIELD(55, 1) /* index 87 */, + TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT, + BITFIELD(26, 1) /* index 90 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD, + BITFIELD(26, 1) /* index 93 */, + CHILD(96), TILEGX_OPC_LD, + BITFIELD(51, 2) /* index 96 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101), + BITFIELD(53, 2) /* index 101 */, + TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106), + BITFIELD(55, 1) /* index 106 */, + TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, + BITFIELD(26, 1) /* index 109 */, + CHILD(112), CHILD(115), + BITFIELD(57, 1) /* index 112 */, + TILEGX_OPC_ST1, TILEGX_OPC_ST4, + BITFIELD(57, 1) /* index 115 */, + TILEGX_OPC_ST2, TILEGX_OPC_ST, +}; + +#undef BITFIELD +#undef CHILD +const unsigned short * const +tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] = +{ + decode_X0_fsm, + decode_X1_fsm, + decode_Y0_fsm, + decode_Y1_fsm, + decode_Y2_fsm +}; +const struct tilegx_operand tilegx_operands[35] = +{ + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0), + 8, 1, 0, 0, 0, 0, + create_Imm8_X0, get_Imm8_X0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1), + 8, 1, 0, 0, 0, 0, + create_Imm8_X1, get_Imm8_X1 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0), + 8, 1, 0, 0, 0, 0, + create_Imm8_Y0, get_Imm8_Y0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1), + 8, 1, 0, 0, 0, 0, + create_Imm8_Y1, get_Imm8_Y1 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST), + 16, 1, 0, 0, 0, 0, + create_Imm16_X0, get_Imm16_X0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST), + 16, 1, 0, 0, 0, 0, + create_Imm16_X1, get_Imm16_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 0, 1, 0, 0, + create_Dest_X0, get_Dest_X0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcA_X0, get_SrcA_X0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 0, 1, 0, 0, + create_Dest_X1, get_Dest_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcA_X1, get_SrcA_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 0, 1, 0, 0, + create_Dest_Y0, get_Dest_Y0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcA_Y0, get_SrcA_Y0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 0, 1, 0, 0, + create_Dest_Y1, get_Dest_Y1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcA_Y1, get_SrcA_Y1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcA_Y2, get_SrcA_Y2 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 1, 0, 0, + create_SrcA_X1, get_SrcA_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcB_X0, get_SrcB_X0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcB_X1, get_SrcB_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcB_Y0, get_SrcB_Y0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcB_Y1, get_SrcB_Y1 + }, + { + TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1), + 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, + create_BrOff_X1, get_BrOff_X1 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE), + 6, 0, 0, 0, 0, 0, + create_BFStart_X0, get_BFStart_X0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE), + 6, 0, 0, 0, 0, 0, + create_BFEnd_X0, get_BFEnd_X0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 1, 0, 0, + create_Dest_X0, get_Dest_X0 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 1, 0, 0, + create_Dest_Y0, get_Dest_Y0 + }, + { + TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1), + 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, + create_JumpOff_X1, get_JumpOff_X1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 0, 1, 0, 0, + create_SrcBDest_Y2, get_SrcBDest_Y2 + }, + { + TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1), + 14, 0, 0, 0, 0, 0, + create_MF_Imm14_X1, get_MF_Imm14_X1 + }, + { + TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1), + 14, 0, 0, 0, 0, 0, + create_MT_Imm14_X1, get_MT_Imm14_X1 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0), + 6, 0, 0, 0, 0, 0, + create_ShAmt_X0, get_ShAmt_X0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1), + 6, 0, 0, 0, 0, 0, + create_ShAmt_X1, get_ShAmt_X1 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0), + 6, 0, 0, 0, 0, 0, + create_ShAmt_Y0, get_ShAmt_Y0 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1), + 6, 0, 0, 0, 0, 0, + create_ShAmt_Y1, get_ShAmt_Y1 + }, + { + TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), + 6, 0, 1, 0, 0, 0, + create_SrcBDest_Y2, get_SrcBDest_Y2 + }, + { + TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1), + 8, 1, 0, 0, 0, 0, + create_Dest_Imm8_X1, get_Dest_Imm8_X1 + } +}; + + + + +/* Given a set of bundle bits and the lookup FSM for a specific pipe, + * returns which instruction the bundle contains in that pipe. + */ +static const struct tilegx_opcode * +find_opcode(tilegx_bundle_bits bits, const unsigned short *table) +{ + int index = 0; + + while (1) + { + unsigned short bitspec = table[index]; + unsigned int bitfield = + ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6); + + unsigned short next = table[index + 1 + bitfield]; + if (next <= TILEGX_OPC_NONE) + return &tilegx_opcodes[next]; + + index = next - TILEGX_OPC_NONE; + } +} + + +int +parse_insn_tilegx(tilegx_bundle_bits bits, + unsigned long long pc, + struct tilegx_decoded_instruction + decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]) +{ + int num_instructions = 0; + int pipe; + + int min_pipe, max_pipe; + if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0) + { + min_pipe = TILEGX_PIPELINE_X0; + max_pipe = TILEGX_PIPELINE_X1; + } + else + { + min_pipe = TILEGX_PIPELINE_Y0; + max_pipe = TILEGX_PIPELINE_Y2; + } + + /* For each pipe, find an instruction that fits. */ + for (pipe = min_pipe; pipe <= max_pipe; pipe++) + { + const struct tilegx_opcode *opc; + struct tilegx_decoded_instruction *d; + int i; + + d = &decoded[num_instructions++]; + opc = find_opcode (bits, tilegx_bundle_decoder_fsms[pipe]); + d->opcode = opc; + + /* Decode each operand, sign extending, etc. as appropriate. */ + for (i = 0; i < opc->num_operands; i++) + { + const struct tilegx_operand *op = + &tilegx_operands[opc->operands[pipe][i]]; + int raw_opval = op->extract (bits); + long long opval; + + if (op->is_signed) + { + /* Sign-extend the operand. */ + int shift = (int)((sizeof(int) * 8) - op->num_bits); + raw_opval = (raw_opval << shift) >> shift; + } + + /* Adjust PC-relative scaled branch offsets. */ + if (op->type == TILEGX_OP_TYPE_ADDRESS) + opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc; + else + opval = raw_opval; + + /* Record the final value. */ + d->operands[i] = op; + d->operand_values[i] = opval; + } + } + + return num_instructions; +} diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 49a605be94c..c4be58cc5d5 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -22,6 +22,7 @@ #include <linux/sched.h> #include <linux/smp.h> #include <linux/delay.h> +#include <linux/module.h> #include <asm/irq_regs.h> #include <asm/traps.h> #include <hv/hypervisor.h> @@ -56,6 +57,7 @@ cycles_t get_cycles(void) return (((cycles_t)high) << 32) | low; } +EXPORT_SYMBOL(get_cycles); #endif /* diff --git a/arch/tile/kernel/tlb.c b/arch/tile/kernel/tlb.c index 2dffc1044d8..a5f241c24ca 100644 --- a/arch/tile/kernel/tlb.c +++ b/arch/tile/kernel/tlb.c @@ -34,13 +34,13 @@ void flush_tlb_mm(struct mm_struct *mm) { HV_Remote_ASID asids[NR_CPUS]; int i = 0, cpu; - for_each_cpu(cpu, &mm->cpu_vm_mask) { + for_each_cpu(cpu, mm_cpumask(mm)) { HV_Remote_ASID *asid = &asids[i++]; asid->y = cpu / smp_topology.width; asid->x = cpu % smp_topology.width; asid->asid = per_cpu(current_asid, cpu); } - flush_remote(0, HV_FLUSH_EVICT_L1I, &mm->cpu_vm_mask, + flush_remote(0, HV_FLUSH_EVICT_L1I, mm_cpumask(mm), 0, 0, 0, NULL, asids, i); } @@ -54,8 +54,8 @@ void flush_tlb_page_mm(const struct vm_area_struct *vma, struct mm_struct *mm, { unsigned long size = hv_page_size(vma); int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; - flush_remote(0, cache, &mm->cpu_vm_mask, - va, size, size, &mm->cpu_vm_mask, NULL, 0); + flush_remote(0, cache, mm_cpumask(mm), + va, size, size, mm_cpumask(mm), NULL, 0); } void flush_tlb_page(const struct vm_area_struct *vma, unsigned long va) @@ -70,8 +70,8 @@ void flush_tlb_range(const struct vm_area_struct *vma, unsigned long size = hv_page_size(vma); struct mm_struct *mm = vma->vm_mm; int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; - flush_remote(0, cache, &mm->cpu_vm_mask, start, end - start, size, - &mm->cpu_vm_mask, NULL, 0); + flush_remote(0, cache, mm_cpumask(mm), start, end - start, size, + mm_cpumask(mm), NULL, 0); } void flush_tlb_all(void) diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 5474fc2e77e..f9803dfa735 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -308,6 +308,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, info.si_addr = (void __user *)address; if (signo == SIGILL) info.si_trapno = fault_num; + trace_unhandled_signal("trap", regs, address, signo); force_sig_info(signo, &info, current); } diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S index 82f64cc6365..24448734f6f 100644 --- a/arch/tile/lib/atomic_asm_32.S +++ b/arch/tile/lib/atomic_asm_32.S @@ -59,7 +59,7 @@ * bad kernel addresses). * * Note that if the value we would store is the same as what we - * loaded, we bypass the load. Other platforms with true atomics can + * loaded, we bypass the store. Other platforms with true atomics can * make the guarantee that a non-atomic __clear_bit(), for example, * can safely race with an atomic test_and_set_bit(); this example is * from bit_spinlock.h in slub_lock() / slub_unlock(). We can't do diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c index 35c1d8ca5f3..8928aace7a6 100644 --- a/arch/tile/lib/cacheflush.c +++ b/arch/tile/lib/cacheflush.c @@ -15,6 +15,7 @@ #include <asm/page.h> #include <asm/cacheflush.h> #include <arch/icache.h> +#include <arch/spr_def.h> void __flush_icache_range(unsigned long start, unsigned long end) @@ -39,6 +40,18 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) char *p, *base; size_t step_size, load_count; const unsigned long STRIPE_WIDTH = 8192; +#ifdef __tilegx__ + /* + * On TILE-Gx, we must disable the dstream prefetcher before doing + * a cache flush; otherwise, we could end up with data in the cache + * that we don't want there. Note that normally we'd do an mf + * after the SPR write to disabling the prefetcher, but we do one + * below, before any further loads, so there's no need to do it + * here. + */ + uint_reg_t old_dstream_pf = __insn_mfspr(SPR_DSTREAM_PF); + __insn_mtspr(SPR_DSTREAM_PF, 0); +#endif /* * Flush and invalidate the buffer out of the local L1/L2 @@ -122,4 +135,9 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) /* Wait for the load+inv's (and thus finvs) to have completed. */ __insn_mf(); + +#ifdef __tilegx__ + /* Reenable the prefetcher. */ + __insn_mtspr(SPR_DSTREAM_PF, old_dstream_pf); +#endif } diff --git a/arch/tile/lib/memchr_64.c b/arch/tile/lib/memchr_64.c new file mode 100644 index 00000000000..84fdc8d8e73 --- /dev/null +++ b/arch/tile/lib/memchr_64.c @@ -0,0 +1,71 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/module.h> + +void *memchr(const void *s, int c, size_t n) +{ + const uint64_t *last_word_ptr; + const uint64_t *p; + const char *last_byte_ptr; + uintptr_t s_int; + uint64_t goal, before_mask, v, bits; + char *ret; + + if (__builtin_expect(n == 0, 0)) { + /* Don't dereference any memory if the array is empty. */ + return NULL; + } + + /* Get an aligned pointer. */ + s_int = (uintptr_t) s; + p = (const uint64_t *)(s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + * will not match goal. + * + * Note that this shift count expression works because we know + * shift counts are taken mod 64. + */ + before_mask = (1ULL << (s_int << 3)) - 1; + v = (*p | before_mask) ^ (goal & before_mask); + + /* Compute the address of the last byte. */ + last_byte_ptr = (const char *)s + n - 1; + + /* Compute the address of the word containing the last byte. */ + last_word_ptr = (const uint64_t *)((uintptr_t) last_byte_ptr & -8); + + while ((bits = __insn_v1cmpeq(v, goal)) == 0) { + if (__builtin_expect(p == last_word_ptr, 0)) { + /* We already read the last word in the array, + * so give up. + */ + return NULL; + } + v = *++p; + } + + /* We found a match, but it might be in a byte past the end + * of the array. + */ + ret = ((char *)p) + (__insn_ctz(bits) >> 3); + return (ret <= last_byte_ptr) ? ret : NULL; +} +EXPORT_SYMBOL(memchr); diff --git a/arch/tile/lib/memcpy_64.c b/arch/tile/lib/memcpy_64.c new file mode 100644 index 00000000000..3fab9a6a2bb --- /dev/null +++ b/arch/tile/lib/memcpy_64.c @@ -0,0 +1,220 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/module.h> +#define __memcpy memcpy +/* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */ + +/* Must be 8 bytes in size. */ +#define word_t uint64_t + +#if CHIP_L2_LINE_SIZE() != 64 && CHIP_L2_LINE_SIZE() != 128 +#error "Assumes 64 or 128 byte line size" +#endif + +/* How many cache lines ahead should we prefetch? */ +#define PREFETCH_LINES_AHEAD 3 + +/* + * Provide "base versions" of load and store for the normal code path. + * The kernel provides other versions for userspace copies. + */ +#define ST(p, v) (*(p) = (v)) +#define LD(p) (*(p)) + +#ifndef USERCOPY_FUNC +#define ST1 ST +#define ST2 ST +#define ST4 ST +#define ST8 ST +#define LD1 LD +#define LD2 LD +#define LD4 LD +#define LD8 LD +#define RETVAL dstv +void *memcpy(void *__restrict dstv, const void *__restrict srcv, size_t n) +#else +/* + * Special kernel version will provide implementation of the LDn/STn + * macros to return a count of uncopied bytes due to mm fault. + */ +#define RETVAL 0 +int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n) +#endif +{ + char *__restrict dst1 = (char *)dstv; + const char *__restrict src1 = (const char *)srcv; + const char *__restrict src1_end; + const char *__restrict prefetch; + word_t *__restrict dst8; /* 8-byte pointer to destination memory. */ + word_t final; /* Final bytes to write to trailing word, if any */ + long i; + + if (n < 16) { + for (; n; n--) + ST1(dst1++, LD1(src1++)); + return RETVAL; + } + + /* + * Locate the end of source memory we will copy. Don't + * prefetch past this. + */ + src1_end = src1 + n - 1; + + /* Prefetch ahead a few cache lines, but not past the end. */ + prefetch = src1; + for (i = 0; i < PREFETCH_LINES_AHEAD; i++) { + __insn_prefetch(prefetch); + prefetch += CHIP_L2_LINE_SIZE(); + prefetch = (prefetch > src1_end) ? prefetch : src1; + } + + /* Copy bytes until dst is word-aligned. */ + for (; (uintptr_t)dst1 & (sizeof(word_t) - 1); n--) + ST1(dst1++, LD1(src1++)); + + /* 8-byte pointer to destination memory. */ + dst8 = (word_t *)dst1; + + if (__builtin_expect((uintptr_t)src1 & (sizeof(word_t) - 1), 0)) { + /* + * Misaligned copy. Copy 8 bytes at a time, but don't + * bother with other fanciness. + * + * TODO: Consider prefetching and using wh64 as well. + */ + + /* Create an aligned src8. */ + const word_t *__restrict src8 = + (const word_t *)((uintptr_t)src1 & -sizeof(word_t)); + word_t b; + + word_t a = LD8(src8++); + for (; n >= sizeof(word_t); n -= sizeof(word_t)) { + b = LD8(src8++); + a = __insn_dblalign(a, b, src1); + ST8(dst8++, a); + a = b; + } + + if (n == 0) + return RETVAL; + + b = ((const char *)src8 <= src1_end) ? *src8 : 0; + + /* + * Final source bytes to write to trailing partial + * word, if any. + */ + final = __insn_dblalign(a, b, src1); + } else { + /* Aligned copy. */ + + const word_t* __restrict src8 = (const word_t *)src1; + + /* src8 and dst8 are both word-aligned. */ + if (n >= CHIP_L2_LINE_SIZE()) { + /* Copy until 'dst' is cache-line-aligned. */ + for (; (uintptr_t)dst8 & (CHIP_L2_LINE_SIZE() - 1); + n -= sizeof(word_t)) + ST8(dst8++, LD8(src8++)); + + for (; n >= CHIP_L2_LINE_SIZE(); ) { + __insn_wh64(dst8); + + /* + * Prefetch and advance to next line + * to prefetch, but don't go past the end + */ + __insn_prefetch(prefetch); + prefetch += CHIP_L2_LINE_SIZE(); + prefetch = (prefetch > src1_end) ? prefetch : + (const char *)src8; + + /* + * Copy an entire cache line. Manually + * unrolled to avoid idiosyncracies of + * compiler unrolling. + */ +#define COPY_WORD(offset) ({ ST8(dst8+offset, LD8(src8+offset)); n -= 8; }) + COPY_WORD(0); + COPY_WORD(1); + COPY_WORD(2); + COPY_WORD(3); + COPY_WORD(4); + COPY_WORD(5); + COPY_WORD(6); + COPY_WORD(7); +#if CHIP_L2_LINE_SIZE() == 128 + COPY_WORD(8); + COPY_WORD(9); + COPY_WORD(10); + COPY_WORD(11); + COPY_WORD(12); + COPY_WORD(13); + COPY_WORD(14); + COPY_WORD(15); +#elif CHIP_L2_LINE_SIZE() != 64 +# error Fix code that assumes particular L2 cache line sizes +#endif + + dst8 += CHIP_L2_LINE_SIZE() / sizeof(word_t); + src8 += CHIP_L2_LINE_SIZE() / sizeof(word_t); + } + } + + for (; n >= sizeof(word_t); n -= sizeof(word_t)) + ST8(dst8++, LD8(src8++)); + + if (__builtin_expect(n == 0, 1)) + return RETVAL; + + final = LD8(src8); + } + + /* n != 0 if we get here. Write out any trailing bytes. */ + dst1 = (char *)dst8; + if (n & 4) { + ST4((uint32_t *)dst1, final); + dst1 += 4; + final >>= 32; + n &= 3; + } + if (n & 2) { + ST2((uint16_t *)dst1, final); + dst1 += 2; + final >>= 16; + n &= 1; + } + if (n) + ST1((uint8_t *)dst1, final); + + return RETVAL; +} + + +#ifdef USERCOPY_FUNC +#undef ST1 +#undef ST2 +#undef ST4 +#undef ST8 +#undef LD1 +#undef LD2 +#undef LD4 +#undef LD8 +#undef USERCOPY_FUNC +#endif diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c new file mode 100644 index 00000000000..4763b3aff1c --- /dev/null +++ b/arch/tile/lib/memcpy_user_64.c @@ -0,0 +1,86 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Do memcpy(), but trap and return "n" when a load or store faults. + * + * Note: this idiom only works when memcpy() compiles to a leaf function. + * If "sp" is updated during memcpy, the "jrp lr" will be incorrect. + * + * Also note that we are capturing "n" from the containing scope here. + */ + +#define _ST(p, inst, v) \ + ({ \ + asm("1: " #inst " %0, %1;" \ + ".pushsection .coldtext.memcpy,\"ax\";" \ + "2: { move r0, %2; jrp lr };" \ + ".section __ex_table,\"a\";" \ + ".quad 1b, 2b;" \ + ".popsection" \ + : "=m" (*(p)) : "r" (v), "r" (n)); \ + }) + +#define _LD(p, inst) \ + ({ \ + unsigned long __v; \ + asm("1: " #inst " %0, %1;" \ + ".pushsection .coldtext.memcpy,\"ax\";" \ + "2: { move r0, %2; jrp lr };" \ + ".section __ex_table,\"a\";" \ + ".quad 1b, 2b;" \ + ".popsection" \ + : "=r" (__v) : "m" (*(p)), "r" (n)); \ + __v; \ + }) + +#define USERCOPY_FUNC __copy_to_user_inatomic +#define ST1(p, v) _ST((p), st1, (v)) +#define ST2(p, v) _ST((p), st2, (v)) +#define ST4(p, v) _ST((p), st4, (v)) +#define ST8(p, v) _ST((p), st, (v)) +#define LD1 LD +#define LD2 LD +#define LD4 LD +#define LD8 LD +#include "memcpy_64.c" + +#define USERCOPY_FUNC __copy_from_user_inatomic +#define ST1 ST +#define ST2 ST +#define ST4 ST +#define ST8 ST +#define LD1(p) _LD((p), ld1u) +#define LD2(p) _LD((p), ld2u) +#define LD4(p) _LD((p), ld4u) +#define LD8(p) _LD((p), ld) +#include "memcpy_64.c" + +#define USERCOPY_FUNC __copy_in_user_inatomic +#define ST1(p, v) _ST((p), st1, (v)) +#define ST2(p, v) _ST((p), st2, (v)) +#define ST4(p, v) _ST((p), st4, (v)) +#define ST8(p, v) _ST((p), st, (v)) +#define LD1(p) _LD((p), ld1u) +#define LD2(p) _LD((p), ld2u) +#define LD4(p) _LD((p), ld4u) +#define LD8(p) _LD((p), ld) +#include "memcpy_64.c" + +unsigned long __copy_from_user_zeroing(void *to, const void __user *from, + unsigned long n) +{ + unsigned long rc = __copy_from_user_inatomic(to, from, n); + if (unlikely(rc)) + memset(to + n - rc, 0, rc); + return rc; +} diff --git a/arch/tile/lib/memset_64.c b/arch/tile/lib/memset_64.c new file mode 100644 index 00000000000..3873085711d --- /dev/null +++ b/arch/tile/lib/memset_64.c @@ -0,0 +1,145 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <arch/chip.h> + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/module.h> + +#undef memset + +void *memset(void *s, int c, size_t n) +{ + uint64_t *out64; + int n64, to_align64; + uint64_t v64; + uint8_t *out8 = s; + + /* Experimentation shows that a trivial tight loop is a win up until + * around a size of 20, where writing a word at a time starts to win. + */ +#define BYTE_CUTOFF 20 + +#if BYTE_CUTOFF < 7 + /* This must be at least at least this big, or some code later + * on doesn't work. + */ +#error "BYTE_CUTOFF is too small" +#endif + + if (n < BYTE_CUTOFF) { + /* Strangely, this turns out to be the tightest way to + * write this loop. + */ + if (n != 0) { + do { + /* Strangely, combining these into one line + * performs worse. + */ + *out8 = c; + out8++; + } while (--n != 0); + } + + return s; + } + + /* Align 'out8'. We know n >= 7 so this won't write past the end. */ + while (((uintptr_t) out8 & 7) != 0) { + *out8++ = c; + --n; + } + + /* Align 'n'. */ + while (n & 7) + out8[--n] = c; + + out64 = (uint64_t *) out8; + n64 = n >> 3; + + /* Tile input byte out to 64 bits. */ + /* KLUDGE */ + v64 = 0x0101010101010101ULL * (uint8_t)c; + + /* This must be at least 8 or the following loop doesn't work. */ +#define CACHE_LINE_SIZE_IN_DOUBLEWORDS (CHIP_L2_LINE_SIZE() / 8) + + /* Determine how many words we need to emit before the 'out32' + * pointer becomes aligned modulo the cache line size. + */ + to_align64 = (-((uintptr_t)out64 >> 3)) & + (CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1); + + /* Only bother aligning and using wh64 if there is at least + * one full cache line to process. This check also prevents + * overrunning the end of the buffer with alignment words. + */ + if (to_align64 <= n64 - CACHE_LINE_SIZE_IN_DOUBLEWORDS) { + int lines_left; + + /* Align out64 mod the cache line size so we can use wh64. */ + n64 -= to_align64; + for (; to_align64 != 0; to_align64--) { + *out64 = v64; + out64++; + } + + /* Use unsigned divide to turn this into a right shift. */ + lines_left = (unsigned)n64 / CACHE_LINE_SIZE_IN_DOUBLEWORDS; + + do { + /* Only wh64 a few lines at a time, so we don't + * exceed the maximum number of victim lines. + */ + int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS()) + ? lines_left + : CHIP_MAX_OUTSTANDING_VICTIMS()); + uint64_t *wh = out64; + int i = x; + int j; + + lines_left -= x; + + do { + __insn_wh64(wh); + wh += CACHE_LINE_SIZE_IN_DOUBLEWORDS; + } while (--i); + + for (j = x * (CACHE_LINE_SIZE_IN_DOUBLEWORDS / 4); + j != 0; j--) { + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + } + } while (lines_left != 0); + + /* We processed all full lines above, so only this many + * words remain to be processed. + */ + n64 &= CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1; + } + + /* Now handle any leftover values. */ + if (n64 != 0) { + do { + *out64 = v64; + out64++; + } while (--n64 != 0); + } + + return s; +} +EXPORT_SYMBOL(memset); diff --git a/arch/tile/lib/spinlock_64.c b/arch/tile/lib/spinlock_64.c new file mode 100644 index 00000000000..d6fb9581e98 --- /dev/null +++ b/arch/tile/lib/spinlock_64.c @@ -0,0 +1,104 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/spinlock.h> +#include <linux/module.h> +#include <asm/processor.h> + +#include "spinlock_common.h" + +/* + * Read the spinlock value without allocating in our cache and without + * causing an invalidation to another cpu with a copy of the cacheline. + * This is important when we are spinning waiting for the lock. + */ +static inline u32 arch_spin_read_noalloc(void *lock) +{ + return atomic_cmpxchg((atomic_t *)lock, -1, -1); +} + +/* + * Wait until the high bits (current) match my ticket. + * If we notice the overflow bit set on entry, we clear it. + */ +void arch_spin_lock_slow(arch_spinlock_t *lock, u32 my_ticket) +{ + if (unlikely(my_ticket & __ARCH_SPIN_NEXT_OVERFLOW)) { + __insn_fetchand4(&lock->lock, ~__ARCH_SPIN_NEXT_OVERFLOW); + my_ticket &= ~__ARCH_SPIN_NEXT_OVERFLOW; + } + + for (;;) { + u32 val = arch_spin_read_noalloc(lock); + u32 delta = my_ticket - arch_spin_current(val); + if (delta == 0) + return; + relax((128 / CYCLES_PER_RELAX_LOOP) * delta); + } +} +EXPORT_SYMBOL(arch_spin_lock_slow); + +/* + * Check the lock to see if it is plausible, and try to get it with cmpxchg(). + */ +int arch_spin_trylock(arch_spinlock_t *lock) +{ + u32 val = arch_spin_read_noalloc(lock); + if (unlikely(arch_spin_current(val) != arch_spin_next(val))) + return 0; + return cmpxchg(&lock->lock, val, (val + 1) & ~__ARCH_SPIN_NEXT_OVERFLOW) + == val; +} +EXPORT_SYMBOL(arch_spin_trylock); + +void arch_spin_unlock_wait(arch_spinlock_t *lock) +{ + u32 iterations = 0; + while (arch_spin_is_locked(lock)) + delay_backoff(iterations++); +} +EXPORT_SYMBOL(arch_spin_unlock_wait); + +/* + * If the read lock fails due to a writer, we retry periodically + * until the value is positive and we write our incremented reader count. + */ +void __read_lock_failed(arch_rwlock_t *rw) +{ + u32 val; + int iterations = 0; + do { + delay_backoff(iterations++); + val = __insn_fetchaddgez4(&rw->lock, 1); + } while (unlikely(arch_write_val_locked(val))); +} +EXPORT_SYMBOL(__read_lock_failed); + +/* + * If we failed because there were readers, clear the "writer" bit + * so we don't block additional readers. Otherwise, there was another + * writer anyway, so our "fetchor" made no difference. Then wait, + * issuing periodic fetchor instructions, till we get the lock. + */ +void __write_lock_failed(arch_rwlock_t *rw, u32 val) +{ + int iterations = 0; + do { + if (!arch_write_val_locked(val)) + val = __insn_fetchand4(&rw->lock, ~__WRITE_LOCK_BIT); + delay_backoff(iterations++); + val = __insn_fetchor4(&rw->lock, __WRITE_LOCK_BIT); + } while (val != 0); +} +EXPORT_SYMBOL(__write_lock_failed); diff --git a/arch/tile/lib/strchr_64.c b/arch/tile/lib/strchr_64.c new file mode 100644 index 00000000000..617a9273aaa --- /dev/null +++ b/arch/tile/lib/strchr_64.c @@ -0,0 +1,67 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/module.h> + +#undef strchr + +char *strchr(const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *)(s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + * match neither zero nor goal (we make sure the high bit of each + * byte is 1, and the low 7 bits are all the opposite of the goal + * byte). + * + * Note that this shift count expression works because we know shift + * counts are taken mod 64. + */ + const uint64_t before_mask = (1ULL << (s_int << 3)) - 1; + uint64_t v = (*p | before_mask) ^ + (goal & __insn_v1shrsi(before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi(v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq(v, goal); + + if (__builtin_expect((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = __insn_ctz(zero_matches); + g = __insn_ctz(goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + * then g == z, and we correctly return the address of the '\0' + * rather than NULL. + */ + return (g <= z) ? ((char *)p) + (g >> 3) : NULL; +} +EXPORT_SYMBOL(strchr); diff --git a/arch/tile/lib/strlen_64.c b/arch/tile/lib/strlen_64.c new file mode 100644 index 00000000000..1c92d46202a --- /dev/null +++ b/arch/tile/lib/strlen_64.c @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/module.h> + +#undef strlen + +size_t strlen(const char *s) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *)(s_int & -8); + + /* Read the first word, but force bytes before the string to be nonzero. + * This expression works because we know shift counts are taken mod 64. + */ + uint64_t v = *p | ((1ULL << (s_int << 3)) - 1); + + uint64_t bits; + while ((bits = __insn_v1cmpeqi(v, 0)) == 0) + v = *++p; + + return ((const char *)p) + (__insn_ctz(bits) >> 3) - s; +} +EXPORT_SYMBOL(strlen); diff --git a/arch/tile/lib/usercopy_64.S b/arch/tile/lib/usercopy_64.S new file mode 100644 index 00000000000..2ff44f87b78 --- /dev/null +++ b/arch/tile/lib/usercopy_64.S @@ -0,0 +1,196 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include <linux/linkage.h> +#include <asm/errno.h> +#include <asm/cache.h> +#include <arch/chip.h> + +/* Access user memory, but use MMU to avoid propagating kernel exceptions. */ + + .pushsection .fixup,"ax" + +get_user_fault: + { movei r1, -EFAULT; move r0, zero } + jrp lr + ENDPROC(get_user_fault) + +put_user_fault: + { movei r0, -EFAULT; jrp lr } + ENDPROC(put_user_fault) + + .popsection + +/* + * __get_user_N functions take a pointer in r0, and return 0 in r1 + * on success, with the value in r0; or else -EFAULT in r1. + */ +#define __get_user_N(bytes, LOAD) \ + STD_ENTRY(__get_user_##bytes); \ +1: { LOAD r0, r0; move r1, zero }; \ + jrp lr; \ + STD_ENDPROC(__get_user_##bytes); \ + .pushsection __ex_table,"a"; \ + .quad 1b, get_user_fault; \ + .popsection + +__get_user_N(1, ld1u) +__get_user_N(2, ld2u) +__get_user_N(4, ld4u) +__get_user_N(8, ld) + +/* + * __put_user_N functions take a value in r0 and a pointer in r1, + * and return 0 in r0 on success or -EFAULT on failure. + */ +#define __put_user_N(bytes, STORE) \ + STD_ENTRY(__put_user_##bytes); \ +1: { STORE r1, r0; move r0, zero }; \ + jrp lr; \ + STD_ENDPROC(__put_user_##bytes); \ + .pushsection __ex_table,"a"; \ + .quad 1b, put_user_fault; \ + .popsection + +__put_user_N(1, st1) +__put_user_N(2, st2) +__put_user_N(4, st4) +__put_user_N(8, st) + +/* + * strnlen_user_asm takes the pointer in r0, and the length bound in r1. + * It returns the length, including the terminating NUL, or zero on exception. + * If length is greater than the bound, returns one plus the bound. + */ +STD_ENTRY(strnlen_user_asm) + { beqz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ +1: { ld1u r4, r0; addi r1, r1, -1 } + beqz r4, 2f + { bnezt r1, 1b; addi r0, r0, 1 } +2: { sub r0, r0, r3; jrp lr } + STD_ENDPROC(strnlen_user_asm) + .pushsection .fixup,"ax" +strnlen_user_fault: + { move r0, zero; jrp lr } + ENDPROC(strnlen_user_fault) + .section __ex_table,"a" + .quad 1b, strnlen_user_fault + .popsection + +/* + * strncpy_from_user_asm takes the kernel target pointer in r0, + * the userspace source pointer in r1, and the length bound (including + * the trailing NUL) in r2. On success, it returns the string length + * (not including the trailing NUL), or -EFAULT on failure. + */ +STD_ENTRY(strncpy_from_user_asm) + { beqz r2, 2f; move r3, r0 } +1: { ld1u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } + { st1 r0, r4; addi r0, r0, 1 } + beqz r2, 2f + bnezt r4, 1b + addi r0, r0, -1 /* don't count the trailing NUL */ +2: { sub r0, r0, r3; jrp lr } + STD_ENDPROC(strncpy_from_user_asm) + .pushsection .fixup,"ax" +strncpy_from_user_fault: + { movei r0, -EFAULT; jrp lr } + ENDPROC(strncpy_from_user_fault) + .section __ex_table,"a" + .quad 1b, strncpy_from_user_fault + .popsection + +/* + * clear_user_asm takes the user target address in r0 and the + * number of bytes to zero in r1. + * It returns the number of uncopiable bytes (hopefully zero) in r0. + * Note that we don't use a separate .fixup section here since we fall + * through into the "fixup" code as the last straight-line bundle anyway. + */ +STD_ENTRY(clear_user_asm) + { beqz r1, 2f; or r2, r0, r1 } + andi r2, r2, 7 + beqzt r2, .Lclear_aligned_user_asm +1: { st1 r0, zero; addi r0, r0, 1; addi r1, r1, -1 } + bnezt r1, 1b +2: { move r0, r1; jrp lr } + .pushsection __ex_table,"a" + .quad 1b, 2b + .popsection + +.Lclear_aligned_user_asm: +1: { st r0, zero; addi r0, r0, 8; addi r1, r1, -8 } + bnezt r1, 1b +2: { move r0, r1; jrp lr } + STD_ENDPROC(clear_user_asm) + .pushsection __ex_table,"a" + .quad 1b, 2b + .popsection + +/* + * flush_user_asm takes the user target address in r0 and the + * number of bytes to flush in r1. + * It returns the number of unflushable bytes (hopefully zero) in r0. + */ +STD_ENTRY(flush_user_asm) + beqz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } + { addi r0, r0, CHIP_FLUSH_STRIDE(); bnezt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(flush_user_asm) + .pushsection __ex_table,"a" + .quad 1b, 2b + .popsection + +/* + * inv_user_asm takes the user target address in r0 and the + * number of bytes to invalidate in r1. + * It returns the number of not inv'able bytes (hopefully zero) in r0. + */ +STD_ENTRY(inv_user_asm) + beqz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } + { addi r0, r0, CHIP_INV_STRIDE(); bnezt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(inv_user_asm) + .pushsection __ex_table,"a" + .quad 1b, 2b + .popsection + +/* + * finv_user_asm takes the user target address in r0 and the + * number of bytes to flush-invalidate in r1. + * It returns the number of not finv'able bytes (hopefully zero) in r0. + */ +STD_ENTRY(finv_user_asm) + beqz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } + { addi r0, r0, CHIP_FINV_STRIDE(); bnezt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(finv_user_asm) + .pushsection __ex_table,"a" + .quad 1b, 2b + .popsection diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 51f8663bf07..25b7b90fd62 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -43,8 +43,11 @@ #include <arch/interrupts.h> -static noinline void force_sig_info_fault(int si_signo, int si_code, - unsigned long address, int fault_num, struct task_struct *tsk) +static noinline void force_sig_info_fault(const char *type, int si_signo, + int si_code, unsigned long address, + int fault_num, + struct task_struct *tsk, + struct pt_regs *regs) { siginfo_t info; @@ -59,6 +62,7 @@ static noinline void force_sig_info_fault(int si_signo, int si_code, info.si_code = si_code; info.si_addr = (void __user *)address; info.si_trapno = fault_num; + trace_unhandled_signal(type, regs, address, si_signo); force_sig_info(si_signo, &info, tsk); } @@ -71,11 +75,12 @@ SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, struct pt_regs *, regs) { if (address >= PAGE_OFFSET) - force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address, - INT_DTLB_MISS, current); + force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, + address, INT_DTLB_MISS, current, regs); else - force_sig_info_fault(SIGBUS, BUS_ADRALN, address, - INT_UNALIGN_DATA, current); + force_sig_info_fault("atomic alignment fault", SIGBUS, + BUS_ADRALN, address, + INT_UNALIGN_DATA, current, regs); /* * Adjust pc to point at the actual instruction, which is unusual @@ -471,8 +476,8 @@ bad_area_nosemaphore: */ local_irq_enable(); - force_sig_info_fault(SIGSEGV, si_code, address, - fault_num, tsk); + force_sig_info_fault("segfault", SIGSEGV, si_code, address, + fault_num, tsk, regs); return 0; } @@ -547,7 +552,8 @@ do_sigbus: if (is_kernel_mode) goto no_context; - force_sig_info_fault(SIGBUS, BUS_ADRERR, address, fault_num, tsk); + force_sig_info_fault("bus error", SIGBUS, BUS_ADRERR, address, + fault_num, tsk, regs); return 0; } @@ -732,6 +738,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, panic("Bad fault number %d in do_page_fault", fault_num); } +#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() if (EX1_PL(regs->ex1) != USER_PL) { struct async_tlb *async; switch (fault_num) { @@ -775,6 +782,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, return; } } +#endif handle_page_fault(regs, fault_num, is_page_fault, address, write); } @@ -801,8 +809,6 @@ static void handle_async_page_fault(struct pt_regs *regs, async->address, async->is_write); } } -#endif /* CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() */ - /* * This routine effectively re-issues asynchronous page faults @@ -824,6 +830,8 @@ void do_async_page_fault(struct pt_regs *regs) handle_async_page_fault(regs, ¤t->thread.sn_async_tlb); #endif } +#endif /* CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() */ + void vmalloc_sync_all(void) { diff --git a/arch/tile/mm/migrate_64.S b/arch/tile/mm/migrate_64.S new file mode 100644 index 00000000000..e76fea688be --- /dev/null +++ b/arch/tile/mm/migrate_64.S @@ -0,0 +1,187 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This routine is a helper for migrating the home of a set of pages to + * a new cpu. See the documentation in homecache.c for more information. + */ + +#include <linux/linkage.h> +#include <linux/threads.h> +#include <asm/page.h> +#include <asm/thread_info.h> +#include <asm/types.h> +#include <asm/asm-offsets.h> +#include <hv/hypervisor.h> + + .text + +/* + * First, some definitions that apply to all the code in the file. + */ + +/* Locals (caller-save) */ +#define r_tmp r10 +#define r_save_sp r11 + +/* What we save where in the stack frame; must include all callee-saves. */ +#define FRAME_SP 8 +#define FRAME_R30 16 +#define FRAME_R31 24 +#define FRAME_R32 32 +#define FRAME_R33 40 +#define FRAME_SIZE 48 + + + + +/* + * On entry: + * + * r0 the new context PA to install (moved to r_context) + * r1 PTE to use for context access (moved to r_access) + * r2 ASID to use for new context (moved to r_asid) + * r3 pointer to cpumask with just this cpu set in it (r_my_cpumask) + */ + +/* Arguments (caller-save) */ +#define r_context_in r0 +#define r_access_in r1 +#define r_asid_in r2 +#define r_my_cpumask r3 + +/* Locals (callee-save); must not be more than FRAME_xxx above. */ +#define r_save_ics r30 +#define r_context r31 +#define r_access r32 +#define r_asid r33 + +/* + * Caller-save locals and frame constants are the same as + * for homecache_migrate_stack_and_flush. + */ + +STD_ENTRY(flush_and_install_context) + /* + * Create a stack frame; we can't touch it once we flush the + * cache until we install the new page table and flush the TLB. + */ + { + move r_save_sp, sp + st sp, lr + addi sp, sp, -FRAME_SIZE + } + addi r_tmp, sp, FRAME_SP + { + st r_tmp, r_save_sp + addi r_tmp, sp, FRAME_R30 + } + { + st r_tmp, r30 + addi r_tmp, sp, FRAME_R31 + } + { + st r_tmp, r31 + addi r_tmp, sp, FRAME_R32 + } + { + st r_tmp, r32 + addi r_tmp, sp, FRAME_R33 + } + st r_tmp, r33 + + /* Move some arguments to callee-save registers. */ + { + move r_context, r_context_in + move r_access, r_access_in + } + move r_asid, r_asid_in + + /* Disable interrupts, since we can't use our stack. */ + { + mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION + movei r_tmp, 1 + } + mtspr INTERRUPT_CRITICAL_SECTION, r_tmp + + /* First, flush our L2 cache. */ + { + move r0, zero /* cache_pa */ + moveli r1, hw2_last(HV_FLUSH_EVICT_L2) /* cache_control */ + } + { + shl16insli r1, r1, hw1(HV_FLUSH_EVICT_L2) + move r2, r_my_cpumask /* cache_cpumask */ + } + { + shl16insli r1, r1, hw0(HV_FLUSH_EVICT_L2) + move r3, zero /* tlb_va */ + } + { + move r4, zero /* tlb_length */ + move r5, zero /* tlb_pgsize */ + } + { + move r6, zero /* tlb_cpumask */ + move r7, zero /* asids */ + } + { + move r8, zero /* asidcount */ + jal hv_flush_remote + } + bnez r0, 1f + + /* Now install the new page table. */ + { + move r0, r_context + move r1, r_access + } + { + move r2, r_asid + movei r3, HV_CTX_DIRECTIO + } + jal hv_install_context + bnez r0, 1f + + /* Finally, flush the TLB. */ + { + movei r0, 0 /* preserve_global */ + jal hv_flush_all + } + +1: /* Reset interrupts back how they were before. */ + mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics + + /* Restore the callee-saved registers and return. */ + addli lr, sp, FRAME_SIZE + { + ld lr, lr + addli r_tmp, sp, FRAME_R30 + } + { + ld r30, r_tmp + addli r_tmp, sp, FRAME_R31 + } + { + ld r31, r_tmp + addli r_tmp, sp, FRAME_R32 + } + { + ld r32, r_tmp + addli r_tmp, sp, FRAME_R33 + } + { + ld r33, r_tmp + addi sp, sp, FRAME_SIZE + } + jrp lr + STD_ENDPROC(flush_and_install_context) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fa2cc8c5d01..483775f42d2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -915,6 +915,7 @@ config TOSHIBA config I8K tristate "Dell laptop support" + select HWMON ---help--- This adds a driver to safely access the System Management Mode of the CPU on the Dell Inspiron 8000. The System Management Mode diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 471fdcc5df8..07371cfdfae 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -385,25 +385,40 @@ void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time, spin_lock_irqsave(&blkg->stats_lock, flags); blkg->stats.time += time; +#ifdef CONFIG_DEBUG_BLK_CGROUP blkg->stats.unaccounted_time += unaccounted_time; +#endif spin_unlock_irqrestore(&blkg->stats_lock, flags); } EXPORT_SYMBOL_GPL(blkiocg_update_timeslice_used); +/* + * should be called under rcu read lock or queue lock to make sure blkg pointer + * is valid. + */ void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, bool direction, bool sync) { - struct blkio_group_stats *stats; + struct blkio_group_stats_cpu *stats_cpu; unsigned long flags; - spin_lock_irqsave(&blkg->stats_lock, flags); - stats = &blkg->stats; - stats->sectors += bytes >> 9; - blkio_add_stat(stats->stat_arr[BLKIO_STAT_SERVICED], 1, direction, - sync); - blkio_add_stat(stats->stat_arr[BLKIO_STAT_SERVICE_BYTES], bytes, - direction, sync); - spin_unlock_irqrestore(&blkg->stats_lock, flags); + /* + * Disabling interrupts to provide mutual exclusion between two + * writes on same cpu. It probably is not needed for 64bit. Not + * optimizing that case yet. + */ + local_irq_save(flags); + + stats_cpu = this_cpu_ptr(blkg->stats_cpu); + + u64_stats_update_begin(&stats_cpu->syncp); + stats_cpu->sectors += bytes >> 9; + blkio_add_stat(stats_cpu->stat_arr_cpu[BLKIO_STAT_CPU_SERVICED], + 1, direction, sync); + blkio_add_stat(stats_cpu->stat_arr_cpu[BLKIO_STAT_CPU_SERVICE_BYTES], + bytes, direction, sync); + u64_stats_update_end(&stats_cpu->syncp); + local_irq_restore(flags); } EXPORT_SYMBOL_GPL(blkiocg_update_dispatch_stats); @@ -426,18 +441,44 @@ void blkiocg_update_completion_stats(struct blkio_group *blkg, } EXPORT_SYMBOL_GPL(blkiocg_update_completion_stats); +/* Merged stats are per cpu. */ void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction, bool sync) { + struct blkio_group_stats_cpu *stats_cpu; unsigned long flags; - spin_lock_irqsave(&blkg->stats_lock, flags); - blkio_add_stat(blkg->stats.stat_arr[BLKIO_STAT_MERGED], 1, direction, - sync); - spin_unlock_irqrestore(&blkg->stats_lock, flags); + /* + * Disabling interrupts to provide mutual exclusion between two + * writes on same cpu. It probably is not needed for 64bit. Not + * optimizing that case yet. + */ + local_irq_save(flags); + + stats_cpu = this_cpu_ptr(blkg->stats_cpu); + + u64_stats_update_begin(&stats_cpu->syncp); + blkio_add_stat(stats_cpu->stat_arr_cpu[BLKIO_STAT_CPU_MERGED], 1, + direction, sync); + u64_stats_update_end(&stats_cpu->syncp); + local_irq_restore(flags); } EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats); +/* + * This function allocates the per cpu stats for blkio_group. Should be called + * from sleepable context as alloc_per_cpu() requires that. + */ +int blkio_alloc_blkg_stats(struct blkio_group *blkg) +{ + /* Allocate memory for per cpu stats */ + blkg->stats_cpu = alloc_percpu(struct blkio_group_stats_cpu); + if (!blkg->stats_cpu) + return -ENOMEM; + return 0; +} +EXPORT_SYMBOL_GPL(blkio_alloc_blkg_stats); + void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, struct blkio_group *blkg, void *key, dev_t dev, enum blkio_policy_id plid) @@ -508,6 +549,30 @@ struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) } EXPORT_SYMBOL_GPL(blkiocg_lookup_group); +static void blkio_reset_stats_cpu(struct blkio_group *blkg) +{ + struct blkio_group_stats_cpu *stats_cpu; + int i, j, k; + /* + * Note: On 64 bit arch this should not be an issue. This has the + * possibility of returning some inconsistent value on 32bit arch + * as 64bit update on 32bit is non atomic. Taking care of this + * corner case makes code very complicated, like sending IPIs to + * cpus, taking care of stats of offline cpus etc. + * + * reset stats is anyway more of a debug feature and this sounds a + * corner case. So I am not complicating the code yet until and + * unless this becomes a real issue. + */ + for_each_possible_cpu(i) { + stats_cpu = per_cpu_ptr(blkg->stats_cpu, i); + stats_cpu->sectors = 0; + for(j = 0; j < BLKIO_STAT_CPU_NR; j++) + for (k = 0; k < BLKIO_STAT_TOTAL; k++) + stats_cpu->stat_arr_cpu[j][k] = 0; + } +} + static int blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val) { @@ -552,7 +617,11 @@ blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val) } #endif spin_unlock(&blkg->stats_lock); + + /* Reset Per cpu stats which don't take blkg->stats_lock */ + blkio_reset_stats_cpu(blkg); } + spin_unlock_irq(&blkcg->lock); return 0; } @@ -598,6 +667,59 @@ static uint64_t blkio_fill_stat(char *str, int chars_left, uint64_t val, return val; } + +static uint64_t blkio_read_stat_cpu(struct blkio_group *blkg, + enum stat_type_cpu type, enum stat_sub_type sub_type) +{ + int cpu; + struct blkio_group_stats_cpu *stats_cpu; + u64 val = 0, tval; + + for_each_possible_cpu(cpu) { + unsigned int start; + stats_cpu = per_cpu_ptr(blkg->stats_cpu, cpu); + + do { + start = u64_stats_fetch_begin(&stats_cpu->syncp); + if (type == BLKIO_STAT_CPU_SECTORS) + tval = stats_cpu->sectors; + else + tval = stats_cpu->stat_arr_cpu[type][sub_type]; + } while(u64_stats_fetch_retry(&stats_cpu->syncp, start)); + + val += tval; + } + + return val; +} + +static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg, + struct cgroup_map_cb *cb, dev_t dev, enum stat_type_cpu type) +{ + uint64_t disk_total, val; + char key_str[MAX_KEY_LEN]; + enum stat_sub_type sub_type; + + if (type == BLKIO_STAT_CPU_SECTORS) { + val = blkio_read_stat_cpu(blkg, type, 0); + return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, val, cb, dev); + } + + for (sub_type = BLKIO_STAT_READ; sub_type < BLKIO_STAT_TOTAL; + sub_type++) { + blkio_get_key_name(sub_type, dev, key_str, MAX_KEY_LEN, false); + val = blkio_read_stat_cpu(blkg, type, sub_type); + cb->fill(cb, key_str, val); + } + + disk_total = blkio_read_stat_cpu(blkg, type, BLKIO_STAT_READ) + + blkio_read_stat_cpu(blkg, type, BLKIO_STAT_WRITE); + + blkio_get_key_name(BLKIO_STAT_TOTAL, dev, key_str, MAX_KEY_LEN, false); + cb->fill(cb, key_str, disk_total); + return disk_total; +} + /* This should be called with blkg->stats_lock held */ static uint64_t blkio_get_stat(struct blkio_group *blkg, struct cgroup_map_cb *cb, dev_t dev, enum stat_type type) @@ -609,9 +731,6 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, if (type == BLKIO_STAT_TIME) return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, blkg->stats.time, cb, dev); - if (type == BLKIO_STAT_SECTORS) - return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, - blkg->stats.sectors, cb, dev); #ifdef CONFIG_DEBUG_BLK_CGROUP if (type == BLKIO_STAT_UNACCOUNTED_TIME) return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, @@ -1075,8 +1194,8 @@ static int blkiocg_file_read(struct cgroup *cgrp, struct cftype *cft, } static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg, - struct cftype *cft, struct cgroup_map_cb *cb, enum stat_type type, - bool show_total) + struct cftype *cft, struct cgroup_map_cb *cb, + enum stat_type type, bool show_total, bool pcpu) { struct blkio_group *blkg; struct hlist_node *n; @@ -1087,10 +1206,15 @@ static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg, if (blkg->dev) { if (!cftype_blkg_same_policy(cft, blkg)) continue; - spin_lock_irq(&blkg->stats_lock); - cgroup_total += blkio_get_stat(blkg, cb, blkg->dev, - type); - spin_unlock_irq(&blkg->stats_lock); + if (pcpu) + cgroup_total += blkio_get_stat_cpu(blkg, cb, + blkg->dev, type); + else { + spin_lock_irq(&blkg->stats_lock); + cgroup_total += blkio_get_stat(blkg, cb, + blkg->dev, type); + spin_unlock_irq(&blkg->stats_lock); + } } } if (show_total) @@ -1114,47 +1238,47 @@ static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft, switch(name) { case BLKIO_PROP_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_TIME, 0); + BLKIO_STAT_TIME, 0, 0); case BLKIO_PROP_sectors: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SECTORS, 0); + BLKIO_STAT_CPU_SECTORS, 0, 1); case BLKIO_PROP_io_service_bytes: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SERVICE_BYTES, 1); + BLKIO_STAT_CPU_SERVICE_BYTES, 1, 1); case BLKIO_PROP_io_serviced: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SERVICED, 1); + BLKIO_STAT_CPU_SERVICED, 1, 1); case BLKIO_PROP_io_service_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SERVICE_TIME, 1); + BLKIO_STAT_SERVICE_TIME, 1, 0); case BLKIO_PROP_io_wait_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_WAIT_TIME, 1); + BLKIO_STAT_WAIT_TIME, 1, 0); case BLKIO_PROP_io_merged: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_MERGED, 1); + BLKIO_STAT_CPU_MERGED, 1, 1); case BLKIO_PROP_io_queued: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_QUEUED, 1); + BLKIO_STAT_QUEUED, 1, 0); #ifdef CONFIG_DEBUG_BLK_CGROUP case BLKIO_PROP_unaccounted_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_UNACCOUNTED_TIME, 0); + BLKIO_STAT_UNACCOUNTED_TIME, 0, 0); case BLKIO_PROP_dequeue: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_DEQUEUE, 0); + BLKIO_STAT_DEQUEUE, 0, 0); case BLKIO_PROP_avg_queue_size: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_AVG_QUEUE_SIZE, 0); + BLKIO_STAT_AVG_QUEUE_SIZE, 0, 0); case BLKIO_PROP_group_wait_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_GROUP_WAIT_TIME, 0); + BLKIO_STAT_GROUP_WAIT_TIME, 0, 0); case BLKIO_PROP_idle_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_IDLE_TIME, 0); + BLKIO_STAT_IDLE_TIME, 0, 0); case BLKIO_PROP_empty_time: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_EMPTY_TIME, 0); + BLKIO_STAT_EMPTY_TIME, 0, 0); #endif default: BUG(); @@ -1164,10 +1288,10 @@ static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft, switch(name){ case BLKIO_THROTL_io_service_bytes: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SERVICE_BYTES, 1); + BLKIO_STAT_CPU_SERVICE_BYTES, 1, 1); case BLKIO_THROTL_io_serviced: return blkio_read_blkg_stats(blkcg, cft, cb, - BLKIO_STAT_SERVICED, 1); + BLKIO_STAT_CPU_SERVICED, 1, 1); default: BUG(); } diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index c774930cc20..a71d2904ffb 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -14,6 +14,7 @@ */ #include <linux/cgroup.h> +#include <linux/u64_stats_sync.h> enum blkio_policy_id { BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */ @@ -36,22 +37,15 @@ enum stat_type { * request completion for IOs doen by this cgroup. This may not be * accurate when NCQ is turned on. */ BLKIO_STAT_SERVICE_TIME = 0, - /* Total bytes transferred */ - BLKIO_STAT_SERVICE_BYTES, - /* Total IOs serviced, post merge */ - BLKIO_STAT_SERVICED, /* Total time spent waiting in scheduler queue in ns */ BLKIO_STAT_WAIT_TIME, - /* Number of IOs merged */ - BLKIO_STAT_MERGED, /* Number of IOs queued up */ BLKIO_STAT_QUEUED, /* All the single valued stats go below this */ BLKIO_STAT_TIME, - BLKIO_STAT_SECTORS, +#ifdef CONFIG_DEBUG_BLK_CGROUP /* Time not charged to this cgroup */ BLKIO_STAT_UNACCOUNTED_TIME, -#ifdef CONFIG_DEBUG_BLK_CGROUP BLKIO_STAT_AVG_QUEUE_SIZE, BLKIO_STAT_IDLE_TIME, BLKIO_STAT_EMPTY_TIME, @@ -60,6 +54,18 @@ enum stat_type { #endif }; +/* Per cpu stats */ +enum stat_type_cpu { + BLKIO_STAT_CPU_SECTORS, + /* Total bytes transferred */ + BLKIO_STAT_CPU_SERVICE_BYTES, + /* Total IOs serviced, post merge */ + BLKIO_STAT_CPU_SERVICED, + /* Number of IOs merged */ + BLKIO_STAT_CPU_MERGED, + BLKIO_STAT_CPU_NR +}; + enum stat_sub_type { BLKIO_STAT_READ = 0, BLKIO_STAT_WRITE, @@ -116,11 +122,11 @@ struct blkio_cgroup { struct blkio_group_stats { /* total disk time and nr sectors dispatched by this group */ uint64_t time; - uint64_t sectors; - /* Time not charged to this cgroup */ - uint64_t unaccounted_time; uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL]; #ifdef CONFIG_DEBUG_BLK_CGROUP + /* Time not charged to this cgroup */ + uint64_t unaccounted_time; + /* Sum of number of IOs queued across all samples */ uint64_t avg_queue_size_sum; /* Count of samples taken for average */ @@ -145,6 +151,13 @@ struct blkio_group_stats { #endif }; +/* Per cpu blkio group stats */ +struct blkio_group_stats_cpu { + uint64_t sectors; + uint64_t stat_arr_cpu[BLKIO_STAT_CPU_NR][BLKIO_STAT_TOTAL]; + struct u64_stats_sync syncp; +}; + struct blkio_group { /* An rcu protected unique identifier for the group */ void *key; @@ -160,6 +173,8 @@ struct blkio_group { /* Need to serialize the stats in the case of reset/update */ spinlock_t stats_lock; struct blkio_group_stats stats; + /* Per cpu stats pointer */ + struct blkio_group_stats_cpu __percpu *stats_cpu; }; struct blkio_policy_node { @@ -295,6 +310,7 @@ extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk); extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, struct blkio_group *blkg, void *key, dev_t dev, enum blkio_policy_id plid); +extern int blkio_alloc_blkg_stats(struct blkio_group *blkg); extern int blkiocg_del_blkio_group(struct blkio_group *blkg); extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key); @@ -322,6 +338,8 @@ static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, struct blkio_group *blkg, void *key, dev_t dev, enum blkio_policy_id plid) {} +static inline int blkio_alloc_blkg_stats(struct blkio_group *blkg) { return 0; } + static inline int blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; } diff --git a/block/blk-core.c b/block/blk-core.c index 3fe00a14822..c8303e9d919 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -569,8 +569,6 @@ int blk_get_queue(struct request_queue *q) static inline void blk_free_request(struct request_queue *q, struct request *rq) { - BUG_ON(rq->cmd_flags & REQ_ON_PLUG); - if (rq->cmd_flags & REQ_ELVPRIV) elv_put_request(q, rq); mempool_free(rq, q->rq.rq_pool); @@ -1110,14 +1108,6 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req, { const int ff = bio->bi_rw & REQ_FAILFAST_MASK; - /* - * Debug stuff, kill later - */ - if (!rq_mergeable(req)) { - blk_dump_rq_flags(req, "back"); - return false; - } - if (!ll_back_merge_fn(q, req, bio)) return false; @@ -1132,6 +1122,7 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req, req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); drive_stat_acct(req, 0); + elv_bio_merged(q, req, bio); return true; } @@ -1141,14 +1132,6 @@ static bool bio_attempt_front_merge(struct request_queue *q, const int ff = bio->bi_rw & REQ_FAILFAST_MASK; sector_t sector; - /* - * Debug stuff, kill later - */ - if (!rq_mergeable(req)) { - blk_dump_rq_flags(req, "front"); - return false; - } - if (!ll_front_merge_fn(q, req, bio)) return false; @@ -1173,6 +1156,7 @@ static bool bio_attempt_front_merge(struct request_queue *q, req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); drive_stat_acct(req, 0); + elv_bio_merged(q, req, bio); return true; } @@ -1258,14 +1242,12 @@ static int __make_request(struct request_queue *q, struct bio *bio) el_ret = elv_merge(q, &req, bio); if (el_ret == ELEVATOR_BACK_MERGE) { - BUG_ON(req->cmd_flags & REQ_ON_PLUG); if (bio_attempt_back_merge(q, req, bio)) { if (!attempt_back_merge(q, req)) elv_merged_request(q, req, el_ret); goto out_unlock; } } else if (el_ret == ELEVATOR_FRONT_MERGE) { - BUG_ON(req->cmd_flags & REQ_ON_PLUG); if (bio_attempt_front_merge(q, req, bio)) { if (!attempt_front_merge(q, req)) elv_merged_request(q, req, el_ret); @@ -1320,10 +1302,6 @@ get_rq: if (__rq->q != q) plug->should_sort = 1; } - /* - * Debug flag, kill later - */ - req->cmd_flags |= REQ_ON_PLUG; list_add_tail(&req->queuelist, &plug->list); drive_stat_acct(req, 1); } else { @@ -1550,7 +1528,8 @@ static inline void __generic_make_request(struct bio *bio) goto end_io; } - blk_throtl_bio(q, &bio); + if (blk_throtl_bio(q, &bio)) + goto end_io; /* * If bio = NULL, bio has been throttled and will be submitted @@ -2748,7 +2727,6 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) while (!list_empty(&list)) { rq = list_entry_rq(list.next); list_del_init(&rq->queuelist); - BUG_ON(!(rq->cmd_flags & REQ_ON_PLUG)); BUG_ON(!rq->q); if (rq->q != q) { /* @@ -2760,8 +2738,6 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) depth = 0; spin_lock(q->queue_lock); } - rq->cmd_flags &= ~REQ_ON_PLUG; - /* * rq is already accounted, so use raw insert */ diff --git a/block/blk-exec.c b/block/blk-exec.c index 81e31819a59..8a0e7ec056e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -56,7 +56,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, spin_lock_irq(q->queue_lock); __elv_add_request(q, rq, where); __blk_run_queue(q); - /* the queue is stopped so it won't be plugged+unplugged */ + /* the queue is stopped so it won't be run */ if (rq->cmd_type == REQ_TYPE_PM_RESUME) q->request_fn(q); spin_unlock_irq(q->queue_lock); diff --git a/block/blk-flush.c b/block/blk-flush.c index 6c9b5e189e6..bb21e4c36f7 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -212,13 +212,19 @@ static void flush_end_io(struct request *flush_rq, int error) } /* - * Moving a request silently to empty queue_head may stall the - * queue. Kick the queue in those cases. This function is called - * from request completion path and calling directly into - * request_fn may confuse the driver. Always use kblockd. + * Kick the queue to avoid stall for two cases: + * 1. Moving a request silently to empty queue_head may stall the + * queue. + * 2. When flush request is running in non-queueable queue, the + * queue is hold. Restart the queue after flush request is finished + * to avoid stall. + * This function is called from request completion path and calling + * directly into request_fn may confuse the driver. Always use + * kblockd. */ - if (queued) + if (queued || q->flush_queue_delayed) blk_run_queue_async(q); + q->flush_queue_delayed = 0; } /** diff --git a/block/blk-ioc.c b/block/blk-ioc.c index b791022beef..c898049dafd 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -96,6 +96,9 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node) INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH); INIT_HLIST_HEAD(&ret->cic_list); ret->ioc_data = NULL; +#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) + ret->cgroup_changed = 0; +#endif } return ret; diff --git a/block/blk-lib.c b/block/blk-lib.c index 25de73e4759..78e627e2581 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -9,17 +9,20 @@ #include "blk.h" -static void blkdev_discard_end_io(struct bio *bio, int err) -{ - if (err) { - if (err == -EOPNOTSUPP) - set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); - clear_bit(BIO_UPTODATE, &bio->bi_flags); - } +struct bio_batch { + atomic_t done; + unsigned long flags; + struct completion *wait; +}; - if (bio->bi_private) - complete(bio->bi_private); +static void bio_batch_end_io(struct bio *bio, int err) +{ + struct bio_batch *bb = bio->bi_private; + if (err && (err != -EOPNOTSUPP)) + clear_bit(BIO_UPTODATE, &bb->flags); + if (atomic_dec_and_test(&bb->done)) + complete(bb->wait); bio_put(bio); } @@ -41,6 +44,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, struct request_queue *q = bdev_get_queue(bdev); int type = REQ_WRITE | REQ_DISCARD; unsigned int max_discard_sectors; + struct bio_batch bb; struct bio *bio; int ret = 0; @@ -67,7 +71,11 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, type |= REQ_SECURE; } - while (nr_sects && !ret) { + atomic_set(&bb.done, 1); + bb.flags = 1 << BIO_UPTODATE; + bb.wait = &wait; + + while (nr_sects) { bio = bio_alloc(gfp_mask, 1); if (!bio) { ret = -ENOMEM; @@ -75,9 +83,9 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, } bio->bi_sector = sector; - bio->bi_end_io = blkdev_discard_end_io; + bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; - bio->bi_private = &wait; + bio->bi_private = &bb; if (nr_sects > max_discard_sectors) { bio->bi_size = max_discard_sectors << 9; @@ -88,45 +96,21 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, nr_sects = 0; } - bio_get(bio); + atomic_inc(&bb.done); submit_bio(type, bio); + } + /* Wait for bios in-flight */ + if (!atomic_dec_and_test(&bb.done)) wait_for_completion(&wait); - if (bio_flagged(bio, BIO_EOPNOTSUPP)) - ret = -EOPNOTSUPP; - else if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - bio_put(bio); - } + if (!test_bit(BIO_UPTODATE, &bb.flags)) + ret = -EIO; return ret; } EXPORT_SYMBOL(blkdev_issue_discard); -struct bio_batch -{ - atomic_t done; - unsigned long flags; - struct completion *wait; -}; - -static void bio_batch_end_io(struct bio *bio, int err) -{ - struct bio_batch *bb = bio->bi_private; - - if (err) { - if (err == -EOPNOTSUPP) - set_bit(BIO_EOPNOTSUPP, &bb->flags); - else - clear_bit(BIO_UPTODATE, &bb->flags); - } - if (bb) - if (atomic_dec_and_test(&bb->done)) - complete(bb->wait); - bio_put(bio); -} - /** * blkdev_issue_zeroout - generate number of zero filed write bios * @bdev: blockdev to issue @@ -151,7 +135,6 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, bb.flags = 1 << BIO_UPTODATE; bb.wait = &wait; -submit: ret = 0; while (nr_sects != 0) { bio = bio_alloc(gfp_mask, @@ -168,9 +151,6 @@ submit: while (nr_sects != 0) { sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); - if (sz == 0) - /* bio has maximum size possible */ - break; ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0); nr_sects -= ret >> 9; sector += ret >> 9; @@ -190,16 +170,6 @@ submit: /* One of bios in the batch was completed with error.*/ ret = -EIO; - if (ret) - goto out; - - if (test_bit(BIO_EOPNOTSUPP, &bb.flags)) { - ret = -EOPNOTSUPP; - goto out; - } - if (nr_sects != 0) - goto submit; -out: return ret; } EXPORT_SYMBOL(blkdev_issue_zeroout); diff --git a/block/blk-settings.c b/block/blk-settings.c index 1fa76929359..fa1eb0449a0 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -120,7 +120,7 @@ void blk_set_default_limits(struct queue_limits *lim) lim->discard_granularity = 0; lim->discard_alignment = 0; lim->discard_misaligned = 0; - lim->discard_zeroes_data = -1; + lim->discard_zeroes_data = 1; lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); lim->alignment_offset = 0; @@ -166,6 +166,7 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) blk_set_default_limits(&q->limits); blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS); + q->limits.discard_zeroes_data = 0; /* * by default assume old behaviour and bounce for any highmem page @@ -790,6 +791,12 @@ void blk_queue_flush(struct request_queue *q, unsigned int flush) } EXPORT_SYMBOL_GPL(blk_queue_flush); +void blk_queue_flush_queueable(struct request_queue *q, bool queueable) +{ + q->flush_not_queueable = !queueable; +} +EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); + static int __init blk_settings_init(void) { blk_max_low_pfn = max_low_pfn - 1; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index bd236313f35..d935bd859c8 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -152,7 +152,8 @@ static ssize_t queue_discard_granularity_show(struct request_queue *q, char *pag static ssize_t queue_discard_max_show(struct request_queue *q, char *page) { - return queue_var_show(q->limits.max_discard_sectors << 9, page); + return sprintf(page, "%llu\n", + (unsigned long long)q->limits.max_discard_sectors << 9); } static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 252a81a306f..a62be8d0dc1 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -78,6 +78,8 @@ struct throtl_grp { /* Some throttle limits got updated for the group */ int limits_changed; + + struct rcu_head rcu_head; }; struct throtl_data @@ -88,7 +90,7 @@ struct throtl_data /* service tree for active throtl groups */ struct throtl_rb_root tg_service_tree; - struct throtl_grp root_tg; + struct throtl_grp *root_tg; struct request_queue *queue; /* Total Number of queued bios on READ and WRITE lists */ @@ -151,56 +153,44 @@ static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg) return tg; } -static void throtl_put_tg(struct throtl_grp *tg) +static void throtl_free_tg(struct rcu_head *head) { - BUG_ON(atomic_read(&tg->ref) <= 0); - if (!atomic_dec_and_test(&tg->ref)) - return; + struct throtl_grp *tg; + + tg = container_of(head, struct throtl_grp, rcu_head); + free_percpu(tg->blkg.stats_cpu); kfree(tg); } -static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, - struct blkio_cgroup *blkcg) +static void throtl_put_tg(struct throtl_grp *tg) { - struct throtl_grp *tg = NULL; - void *key = td; - struct backing_dev_info *bdi = &td->queue->backing_dev_info; - unsigned int major, minor; + BUG_ON(atomic_read(&tg->ref) <= 0); + if (!atomic_dec_and_test(&tg->ref)) + return; /* - * TODO: Speed up blkiocg_lookup_group() by maintaining a radix - * tree of blkg (instead of traversing through hash list all - * the time. + * A group is freed in rcu manner. But having an rcu lock does not + * mean that one can access all the fields of blkg and assume these + * are valid. For example, don't try to follow throtl_data and + * request queue links. + * + * Having a reference to blkg under an rcu allows acess to only + * values local to groups like group stats and group rate limits */ + call_rcu(&tg->rcu_head, throtl_free_tg); +} - /* - * This is the common case when there are no blkio cgroups. - * Avoid lookup in this case - */ - if (blkcg == &blkio_root_cgroup) - tg = &td->root_tg; - else - tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key)); - - /* Fill in device details for root group */ - if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { - sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); - tg->blkg.dev = MKDEV(major, minor); - goto done; - } - - if (tg) - goto done; - - tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, td->queue->node); - if (!tg) - goto done; - +static void throtl_init_group(struct throtl_grp *tg) +{ INIT_HLIST_NODE(&tg->tg_node); RB_CLEAR_NODE(&tg->rb_node); bio_list_init(&tg->bio_lists[0]); bio_list_init(&tg->bio_lists[1]); - td->limits_changed = false; + tg->limits_changed = false; + + /* Practically unlimited BW */ + tg->bps[0] = tg->bps[1] = -1; + tg->iops[0] = tg->iops[1] = -1; /* * Take the initial reference that will be released on destroy @@ -209,33 +199,181 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, * exit or cgroup deletion path depending on who is exiting first. */ atomic_set(&tg->ref, 1); +} + +/* Should be called with rcu read lock held (needed for blkcg) */ +static void +throtl_add_group_to_td_list(struct throtl_data *td, struct throtl_grp *tg) +{ + hlist_add_head(&tg->tg_node, &td->tg_list); + td->nr_undestroyed_grps++; +} + +static void +__throtl_tg_fill_dev_details(struct throtl_data *td, struct throtl_grp *tg) +{ + struct backing_dev_info *bdi = &td->queue->backing_dev_info; + unsigned int major, minor; + + if (!tg || tg->blkg.dev) + return; + + /* + * Fill in device details for a group which might not have been + * filled at group creation time as queue was being instantiated + * and driver had not attached a device yet + */ + if (bdi->dev && dev_name(bdi->dev)) { + sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); + tg->blkg.dev = MKDEV(major, minor); + } +} + +/* + * Should be called with without queue lock held. Here queue lock will be + * taken rarely. It will be taken only once during life time of a group + * if need be + */ +static void +throtl_tg_fill_dev_details(struct throtl_data *td, struct throtl_grp *tg) +{ + if (!tg || tg->blkg.dev) + return; + + spin_lock_irq(td->queue->queue_lock); + __throtl_tg_fill_dev_details(td, tg); + spin_unlock_irq(td->queue->queue_lock); +} + +static void throtl_init_add_tg_lists(struct throtl_data *td, + struct throtl_grp *tg, struct blkio_cgroup *blkcg) +{ + __throtl_tg_fill_dev_details(td, tg); /* Add group onto cgroup list */ - sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); blkiocg_add_blkio_group(blkcg, &tg->blkg, (void *)td, - MKDEV(major, minor), BLKIO_POLICY_THROTL); + tg->blkg.dev, BLKIO_POLICY_THROTL); tg->bps[READ] = blkcg_get_read_bps(blkcg, tg->blkg.dev); tg->bps[WRITE] = blkcg_get_write_bps(blkcg, tg->blkg.dev); tg->iops[READ] = blkcg_get_read_iops(blkcg, tg->blkg.dev); tg->iops[WRITE] = blkcg_get_write_iops(blkcg, tg->blkg.dev); - hlist_add_head(&tg->tg_node, &td->tg_list); - td->nr_undestroyed_grps++; -done: + throtl_add_group_to_td_list(td, tg); +} + +/* Should be called without queue lock and outside of rcu period */ +static struct throtl_grp *throtl_alloc_tg(struct throtl_data *td) +{ + struct throtl_grp *tg = NULL; + int ret; + + tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, td->queue->node); + if (!tg) + return NULL; + + ret = blkio_alloc_blkg_stats(&tg->blkg); + + if (ret) { + kfree(tg); + return NULL; + } + + throtl_init_group(tg); return tg; } -static struct throtl_grp * throtl_get_tg(struct throtl_data *td) +static struct +throtl_grp *throtl_find_tg(struct throtl_data *td, struct blkio_cgroup *blkcg) { struct throtl_grp *tg = NULL; + void *key = td; + + /* + * This is the common case when there are no blkio cgroups. + * Avoid lookup in this case + */ + if (blkcg == &blkio_root_cgroup) + tg = td->root_tg; + else + tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key)); + + __throtl_tg_fill_dev_details(td, tg); + return tg; +} + +/* + * This function returns with queue lock unlocked in case of error, like + * request queue is no more + */ +static struct throtl_grp * throtl_get_tg(struct throtl_data *td) +{ + struct throtl_grp *tg = NULL, *__tg = NULL; struct blkio_cgroup *blkcg; + struct request_queue *q = td->queue; rcu_read_lock(); blkcg = task_blkio_cgroup(current); - tg = throtl_find_alloc_tg(td, blkcg); - if (!tg) - tg = &td->root_tg; + tg = throtl_find_tg(td, blkcg); + if (tg) { + rcu_read_unlock(); + return tg; + } + + /* + * Need to allocate a group. Allocation of group also needs allocation + * of per cpu stats which in-turn takes a mutex() and can block. Hence + * we need to drop rcu lock and queue_lock before we call alloc + * + * Take the request queue reference to make sure queue does not + * go away once we return from allocation. + */ + blk_get_queue(q); + rcu_read_unlock(); + spin_unlock_irq(q->queue_lock); + + tg = throtl_alloc_tg(td); + /* + * We might have slept in group allocation. Make sure queue is not + * dead + */ + if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { + blk_put_queue(q); + if (tg) + kfree(tg); + + return ERR_PTR(-ENODEV); + } + blk_put_queue(q); + + /* Group allocated and queue is still alive. take the lock */ + spin_lock_irq(q->queue_lock); + + /* + * Initialize the new group. After sleeping, read the blkcg again. + */ + rcu_read_lock(); + blkcg = task_blkio_cgroup(current); + + /* + * If some other thread already allocated the group while we were + * not holding queue lock, free up the group + */ + __tg = throtl_find_tg(td, blkcg); + + if (__tg) { + kfree(tg); + rcu_read_unlock(); + return __tg; + } + + /* Group allocation failed. Account the IO to root group */ + if (!tg) { + tg = td->root_tg; + return tg; + } + + throtl_init_add_tg_lists(td, tg, blkcg); rcu_read_unlock(); return tg; } @@ -544,6 +682,12 @@ static bool tg_with_in_bps_limit(struct throtl_data *td, struct throtl_grp *tg, return 0; } +static bool tg_no_rule_group(struct throtl_grp *tg, bool rw) { + if (tg->bps[rw] == -1 && tg->iops[rw] == -1) + return 1; + return 0; +} + /* * Returns whether one can dispatch a bio or not. Also returns approx number * of jiffies to wait before this bio is with-in IO rate and can be dispatched @@ -608,10 +752,6 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) tg->bytes_disp[rw] += bio->bi_size; tg->io_disp[rw]++; - /* - * TODO: This will take blkg->stats_lock. Figure out a way - * to avoid this cost. - */ blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, rw, sync); } @@ -989,15 +1129,51 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop) struct throtl_grp *tg; struct bio *bio = *biop; bool rw = bio_data_dir(bio), update_disptime = true; + struct blkio_cgroup *blkcg; if (bio->bi_rw & REQ_THROTTLED) { bio->bi_rw &= ~REQ_THROTTLED; return 0; } + /* + * A throtl_grp pointer retrieved under rcu can be used to access + * basic fields like stats and io rates. If a group has no rules, + * just update the dispatch stats in lockless manner and return. + */ + + rcu_read_lock(); + blkcg = task_blkio_cgroup(current); + tg = throtl_find_tg(td, blkcg); + if (tg) { + throtl_tg_fill_dev_details(td, tg); + + if (tg_no_rule_group(tg, rw)) { + blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, + rw, bio->bi_rw & REQ_SYNC); + rcu_read_unlock(); + return 0; + } + } + rcu_read_unlock(); + + /* + * Either group has not been allocated yet or it is not an unlimited + * IO group + */ + spin_lock_irq(q->queue_lock); tg = throtl_get_tg(td); + if (IS_ERR(tg)) { + if (PTR_ERR(tg) == -ENODEV) { + /* + * Queue is gone. No queue lock held here. + */ + return -ENODEV; + } + } + if (tg->nr_queued[rw]) { /* * There is already another bio queued in same dir. No @@ -1060,39 +1236,24 @@ int blk_throtl_init(struct request_queue *q) INIT_HLIST_HEAD(&td->tg_list); td->tg_service_tree = THROTL_RB_ROOT; td->limits_changed = false; + INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); - /* Init root group */ - tg = &td->root_tg; - INIT_HLIST_NODE(&tg->tg_node); - RB_CLEAR_NODE(&tg->rb_node); - bio_list_init(&tg->bio_lists[0]); - bio_list_init(&tg->bio_lists[1]); - - /* Practically unlimited BW */ - tg->bps[0] = tg->bps[1] = -1; - tg->iops[0] = tg->iops[1] = -1; - td->limits_changed = false; + /* alloc and Init root group. */ + td->queue = q; + tg = throtl_alloc_tg(td); - /* - * Set root group reference to 2. One reference will be dropped when - * all groups on tg_list are being deleted during queue exit. Other - * reference will remain there as we don't want to delete this group - * as it is statically allocated and gets destroyed when throtl_data - * goes away. - */ - atomic_set(&tg->ref, 2); - hlist_add_head(&tg->tg_node, &td->tg_list); - td->nr_undestroyed_grps++; + if (!tg) { + kfree(td); + return -ENOMEM; + } - INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); + td->root_tg = tg; rcu_read_lock(); - blkiocg_add_blkio_group(&blkio_root_cgroup, &tg->blkg, (void *)td, - 0, BLKIO_POLICY_THROTL); + throtl_init_add_tg_lists(td, tg, &blkio_root_cgroup); rcu_read_unlock(); /* Attach throtl data to request queue */ - td->queue = q; q->td = td; return 0; } diff --git a/block/blk.h b/block/blk.h index 61263463e38..d6586287adc 100644 --- a/block/blk.h +++ b/block/blk.h @@ -62,7 +62,28 @@ static inline struct request *__elv_next_request(struct request_queue *q) return rq; } - if (!q->elevator->ops->elevator_dispatch_fn(q, 0)) + /* + * Flush request is running and flush request isn't queueable + * in the drive, we can hold the queue till flush request is + * finished. Even we don't do this, driver can't dispatch next + * requests and will requeue them. And this can improve + * throughput too. For example, we have request flush1, write1, + * flush 2. flush1 is dispatched, then queue is hold, write1 + * isn't inserted to queue. After flush1 is finished, flush2 + * will be dispatched. Since disk cache is already clean, + * flush2 will be finished very soon, so looks like flush2 is + * folded to flush1. + * Since the queue is hold, a flag is set to indicate the queue + * should be restarted later. Please see flush_end_io() for + * details. + */ + if (q->flush_pending_idx != q->flush_running_idx && + !queue_flush_queueable(q)) { + q->flush_queue_delayed = 1; + return NULL; + } + if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) || + !q->elevator->ops->elevator_dispatch_fn(q, 0)) return NULL; } } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ab7a9e6a9b1..7c52d688892 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -300,7 +300,9 @@ struct cfq_data { /* List of cfq groups being managed on this device*/ struct hlist_head cfqg_list; - struct rcu_head rcu; + + /* Number of groups which are on blkcg->blkg_list */ + unsigned int nr_blkcg_linked_grps; }; static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd); @@ -665,15 +667,11 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2, if (rq2 == NULL) return rq1; - if (rq_is_sync(rq1) && !rq_is_sync(rq2)) - return rq1; - else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) - return rq2; - if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) - return rq1; - else if ((rq2->cmd_flags & REQ_META) && - !(rq1->cmd_flags & REQ_META)) - return rq2; + if (rq_is_sync(rq1) != rq_is_sync(rq2)) + return rq_is_sync(rq1) ? rq1 : rq2; + + if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_META) + return rq1->cmd_flags & REQ_META ? rq1 : rq2; s1 = blk_rq_pos(rq1); s2 = blk_rq_pos(rq2); @@ -1014,28 +1012,47 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg, cfqg->needs_update = true; } -static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd, - struct blkio_cgroup *blkcg, int create) +static void cfq_init_add_cfqg_lists(struct cfq_data *cfqd, + struct cfq_group *cfqg, struct blkio_cgroup *blkcg) { - struct cfq_group *cfqg = NULL; - void *key = cfqd; - int i, j; - struct cfq_rb_root *st; struct backing_dev_info *bdi = &cfqd->queue->backing_dev_info; unsigned int major, minor; - cfqg = cfqg_of_blkg(blkiocg_lookup_group(blkcg, key)); - if (cfqg && !cfqg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { + /* + * Add group onto cgroup list. It might happen that bdi->dev is + * not initialized yet. Initialize this new group without major + * and minor info and this info will be filled in once a new thread + * comes for IO. + */ + if (bdi->dev) { sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); - cfqg->blkg.dev = MKDEV(major, minor); - goto done; - } - if (cfqg || !create) - goto done; + cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, + (void *)cfqd, MKDEV(major, minor)); + } else + cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, + (void *)cfqd, 0); + + cfqd->nr_blkcg_linked_grps++; + cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev); + + /* Add group on cfqd list */ + hlist_add_head(&cfqg->cfqd_node, &cfqd->cfqg_list); +} + +/* + * Should be called from sleepable context. No request queue lock as per + * cpu stats are allocated dynamically and alloc_percpu needs to be called + * from sleepable context. + */ +static struct cfq_group * cfq_alloc_cfqg(struct cfq_data *cfqd) +{ + struct cfq_group *cfqg = NULL; + int i, j, ret; + struct cfq_rb_root *st; cfqg = kzalloc_node(sizeof(*cfqg), GFP_ATOMIC, cfqd->queue->node); if (!cfqg) - goto done; + return NULL; for_each_cfqg_st(cfqg, i, j, st) *st = CFQ_RB_ROOT; @@ -1049,43 +1066,94 @@ static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd, */ cfqg->ref = 1; + ret = blkio_alloc_blkg_stats(&cfqg->blkg); + if (ret) { + kfree(cfqg); + return NULL; + } + + return cfqg; +} + +static struct cfq_group * +cfq_find_cfqg(struct cfq_data *cfqd, struct blkio_cgroup *blkcg) +{ + struct cfq_group *cfqg = NULL; + void *key = cfqd; + struct backing_dev_info *bdi = &cfqd->queue->backing_dev_info; + unsigned int major, minor; + /* - * Add group onto cgroup list. It might happen that bdi->dev is - * not initialized yet. Initialize this new group without major - * and minor info and this info will be filled in once a new thread - * comes for IO. See code above. + * This is the common case when there are no blkio cgroups. + * Avoid lookup in this case */ - if (bdi->dev) { - sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); - cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, - MKDEV(major, minor)); - } else - cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, - 0); - - cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev); + if (blkcg == &blkio_root_cgroup) + cfqg = &cfqd->root_group; + else + cfqg = cfqg_of_blkg(blkiocg_lookup_group(blkcg, key)); - /* Add group on cfqd list */ - hlist_add_head(&cfqg->cfqd_node, &cfqd->cfqg_list); + if (cfqg && !cfqg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { + sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); + cfqg->blkg.dev = MKDEV(major, minor); + } -done: return cfqg; } /* - * Search for the cfq group current task belongs to. If create = 1, then also - * create the cfq group if it does not exist. request_queue lock must be held. + * Search for the cfq group current task belongs to. request_queue lock must + * be held. */ -static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create) +static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd) { struct blkio_cgroup *blkcg; - struct cfq_group *cfqg = NULL; + struct cfq_group *cfqg = NULL, *__cfqg = NULL; + struct request_queue *q = cfqd->queue; rcu_read_lock(); blkcg = task_blkio_cgroup(current); - cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create); - if (!cfqg && create) + cfqg = cfq_find_cfqg(cfqd, blkcg); + if (cfqg) { + rcu_read_unlock(); + return cfqg; + } + + /* + * Need to allocate a group. Allocation of group also needs allocation + * of per cpu stats which in-turn takes a mutex() and can block. Hence + * we need to drop rcu lock and queue_lock before we call alloc. + * + * Not taking any queue reference here and assuming that queue is + * around by the time we return. CFQ queue allocation code does + * the same. It might be racy though. + */ + + rcu_read_unlock(); + spin_unlock_irq(q->queue_lock); + + cfqg = cfq_alloc_cfqg(cfqd); + + spin_lock_irq(q->queue_lock); + + rcu_read_lock(); + blkcg = task_blkio_cgroup(current); + + /* + * If some other thread already allocated the group while we were + * not holding queue lock, free up the group + */ + __cfqg = cfq_find_cfqg(cfqd, blkcg); + + if (__cfqg) { + kfree(cfqg); + rcu_read_unlock(); + return __cfqg; + } + + if (!cfqg) cfqg = &cfqd->root_group; + + cfq_init_add_cfqg_lists(cfqd, cfqg, blkcg); rcu_read_unlock(); return cfqg; } @@ -1118,6 +1186,7 @@ static void cfq_put_cfqg(struct cfq_group *cfqg) return; for_each_cfqg_st(cfqg, i, j, st) BUG_ON(!RB_EMPTY_ROOT(&st->rb)); + free_percpu(cfqg->blkg.stats_cpu); kfree(cfqg); } @@ -1176,7 +1245,7 @@ void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg) } #else /* GROUP_IOSCHED */ -static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create) +static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd) { return &cfqd->root_group; } @@ -1210,7 +1279,6 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_rb_root *service_tree; int left; int new_cfqq = 1; - int group_changed = 0; service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq), cfqq_type(cfqq)); @@ -1281,7 +1349,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, rb_link_node(&cfqq->rb_node, parent, p); rb_insert_color(&cfqq->rb_node, &service_tree->rb); service_tree->count++; - if ((add_front || !new_cfqq) && !group_changed) + if (add_front || !new_cfqq) return; cfq_group_notify_queue_add(cfqd, cfqq->cfqg); } @@ -2029,7 +2097,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); - return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); + return 2 * base_rq * (IOPRIO_BE_NR - cfqq->ioprio); } /* @@ -2911,7 +2979,7 @@ cfq_find_alloc_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_group *cfqg; retry: - cfqg = cfq_get_cfqg(cfqd, 1); + cfqg = cfq_get_cfqg(cfqd); cic = cfq_cic_lookup(cfqd, ioc); /* cic always exists here */ cfqq = cic_to_cfqq(cic, is_sync); @@ -3815,15 +3883,11 @@ static void cfq_put_async_queues(struct cfq_data *cfqd) cfq_put_queue(cfqd->async_idle_cfqq); } -static void cfq_cfqd_free(struct rcu_head *head) -{ - kfree(container_of(head, struct cfq_data, rcu)); -} - static void cfq_exit_queue(struct elevator_queue *e) { struct cfq_data *cfqd = e->elevator_data; struct request_queue *q = cfqd->queue; + bool wait = false; cfq_shutdown_timer_wq(cfqd); @@ -3842,7 +3906,13 @@ static void cfq_exit_queue(struct elevator_queue *e) cfq_put_async_queues(cfqd); cfq_release_cfq_groups(cfqd); - cfq_blkiocg_del_blkio_group(&cfqd->root_group.blkg); + + /* + * If there are groups which we could not unlink from blkcg list, + * wait for a rcu period for them to be freed. + */ + if (cfqd->nr_blkcg_linked_grps) + wait = true; spin_unlock_irq(q->queue_lock); @@ -3852,8 +3922,25 @@ static void cfq_exit_queue(struct elevator_queue *e) ida_remove(&cic_index_ida, cfqd->cic_index); spin_unlock(&cic_index_lock); - /* Wait for cfqg->blkg->key accessors to exit their grace periods. */ - call_rcu(&cfqd->rcu, cfq_cfqd_free); + /* + * Wait for cfqg->blkg->key accessors to exit their grace periods. + * Do this wait only if there are other unlinked groups out + * there. This can happen if cgroup deletion path claimed the + * responsibility of cleaning up a group before queue cleanup code + * get to the group. + * + * Do not call synchronize_rcu() unconditionally as there are drivers + * which create/delete request queue hundreds of times during scan/boot + * and synchronize_rcu() can take significant time and slow down boot. + */ + if (wait) + synchronize_rcu(); + +#ifdef CONFIG_CFQ_GROUP_IOSCHED + /* Free up per cpu stats for root group */ + free_percpu(cfqd->root_group.blkg.stats_cpu); +#endif + kfree(cfqd); } static int cfq_alloc_cic_index(void) @@ -3886,8 +3973,12 @@ static void *cfq_init_queue(struct request_queue *q) return NULL; cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); - if (!cfqd) + if (!cfqd) { + spin_lock(&cic_index_lock); + ida_remove(&cic_index_ida, i); + spin_unlock(&cic_index_lock); return NULL; + } /* * Don't need take queue_lock in the routine, since we are @@ -3909,14 +4000,29 @@ static void *cfq_init_queue(struct request_queue *q) #ifdef CONFIG_CFQ_GROUP_IOSCHED /* - * Take a reference to root group which we never drop. This is just - * to make sure that cfq_put_cfqg() does not try to kfree root group + * Set root group reference to 2. One reference will be dropped when + * all groups on cfqd->cfqg_list are being deleted during queue exit. + * Other reference will remain there as we don't want to delete this + * group as it is statically allocated and gets destroyed when + * throtl_data goes away. */ - cfqg->ref = 1; + cfqg->ref = 2; + + if (blkio_alloc_blkg_stats(&cfqg->blkg)) { + kfree(cfqg); + kfree(cfqd); + return NULL; + } + rcu_read_lock(); + cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd, 0); rcu_read_unlock(); + cfqd->nr_blkcg_linked_grps++; + + /* Add group on cfqd->cfqg_list */ + hlist_add_head(&cfqg->cfqd_node, &cfqd->cfqg_list); #endif /* * Not strictly needed (since RB_ROOT just clears the node and we diff --git a/block/elevator.c b/block/elevator.c index 45ca1e34f58..b0b38ce0dcb 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -155,13 +155,8 @@ static struct elevator_type *elevator_get(const char *name) e = elevator_find(name); if (!e) { - char elv[ELV_NAME_MAX + strlen("-iosched")]; - spin_unlock(&elv_list_lock); - - snprintf(elv, sizeof(elv), "%s-iosched", name); - - request_module("%s", elv); + request_module("%s-iosched", name); spin_lock(&elv_list_lock); e = elevator_find(name); } @@ -421,8 +416,6 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) struct list_head *entry; int stop_flags; - BUG_ON(rq->cmd_flags & REQ_ON_PLUG); - if (q->last_merge == rq) q->last_merge = NULL; @@ -661,8 +654,6 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where) rq->q = q; - BUG_ON(rq->cmd_flags & REQ_ON_PLUG); - if (rq->cmd_flags & REQ_SOFTBARRIER) { /* barriers are scheduling boundary, update end_sector */ if (rq->cmd_type == REQ_TYPE_FS || diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 3a17ca5fff6..bc2218db5ba 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -73,17 +73,6 @@ config ACPI_PROCFS_POWER Say N to delete power /proc/acpi/ directories that have moved to /sys/ -config ACPI_POWER_METER - tristate "ACPI 4.0 power meter" - depends on HWMON - help - This driver exposes ACPI 4.0 power meters as hardware monitoring - devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware - and a power meter. - - To compile this driver as a module, choose M here: - the module will be called power-meter. - config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d113fa5100b..b66fbb2fc85 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -59,7 +59,6 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o -obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 30ea95f43e7..d51f9795c06 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1089,21 +1089,21 @@ static int atapi_drain_needed(struct request *rq) static int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) { + struct request_queue *q = sdev->request_queue; + if (!ata_id_has_unload(dev->id)) dev->flags |= ATA_DFLAG_NO_UNLOAD; /* configure max sectors */ - blk_queue_max_hw_sectors(sdev->request_queue, dev->max_sectors); + blk_queue_max_hw_sectors(q, dev->max_sectors); if (dev->class == ATA_DEV_ATAPI) { - struct request_queue *q = sdev->request_queue; void *buf; sdev->sector_size = ATA_SECT_SIZE; /* set DMA padding */ - blk_queue_update_dma_pad(sdev->request_queue, - ATA_DMA_PAD_SZ - 1); + blk_queue_update_dma_pad(q, ATA_DMA_PAD_SZ - 1); /* configure draining */ buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL); @@ -1131,8 +1131,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", sdev->sector_size); - blk_queue_update_dma_alignment(sdev->request_queue, - sdev->sector_size - 1); + blk_queue_update_dma_alignment(q, sdev->sector_size - 1); if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); @@ -1145,6 +1144,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); } + blk_queue_flush_queueable(q, false); + dev->sdev = sdev; return 0; } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 83c32cb7258..717d6e4e18d 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -470,6 +470,27 @@ config XEN_BLKDEV_FRONTEND block device driver. It communicates with a back-end driver in another domain which drives the actual block device. +config XEN_BLKDEV_BACKEND + tristate "Block-device backend driver" + depends on XEN_BACKEND + help + The block-device backend driver allows the kernel to export its + block devices to other guests via a high-performance shared-memory + interface. + + The corresponding Linux frontend driver is enabled by the + CONFIG_XEN_BLKDEV_FRONTEND configuration option. + + The backend driver attaches itself to a any block device specified + in the XenBus configuration. There are no limits to what the block + device as long as it has a major and minor. + + If you are compiling a kernel to run in a Xen block backend driver + domain (often this is domain 0) you should say Y here. To + compile this driver as a module, chose M here: the module + will be called xen-blkback. + + config VIRTIO_BLK tristate "Virtio block driver (EXPERIMENTAL)" depends on EXPERIMENTAL && VIRTIO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 40528ba56d1..76646e9a1c9 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_BLK_DEV_UB) += ub.o obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o +obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/ obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9bf13988f1a..8f4ef656a1a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -64,6 +64,10 @@ MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); MODULE_VERSION("3.6.26"); MODULE_LICENSE("GPL"); +static int cciss_tape_cmds = 6; +module_param(cciss_tape_cmds, int, 0644); +MODULE_PARM_DESC(cciss_tape_cmds, + "number of commands to allocate for tape devices (default: 6)"); static DEFINE_MUTEX(cciss_mutex); static struct proc_dir_entry *proc_cciss; @@ -194,6 +198,8 @@ static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev, static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar); static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag); +static __devinit int write_driver_ver_to_cfgtable( + CfgTable_struct __iomem *cfgtable); /* performant mode helper functions */ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, @@ -556,7 +562,7 @@ static void __devinit cciss_procinit(ctlr_info_t *h) #define to_hba(n) container_of(n, struct ctlr_info, dev) #define to_drv(n) container_of(n, drive_info_struct, dev) -/* List of controllers which cannot be reset on kexec with reset_devices */ +/* List of controllers which cannot be hard reset on kexec with reset_devices */ static u32 unresettable_controller[] = { 0x324a103C, /* Smart Array P712m */ 0x324b103C, /* SmartArray P711m */ @@ -574,23 +580,45 @@ static u32 unresettable_controller[] = { 0x409D0E11, /* Smart Array 6400 EM */ }; -static int ctlr_is_resettable(struct ctlr_info *h) +/* List of controllers which cannot even be soft reset */ +static u32 soft_unresettable_controller[] = { + 0x409C0E11, /* Smart Array 6400 */ + 0x409D0E11, /* Smart Array 6400 EM */ +}; + +static int ctlr_is_hard_resettable(u32 board_id) { int i; for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++) - if (unresettable_controller[i] == h->board_id) + if (unresettable_controller[i] == board_id) return 0; return 1; } +static int ctlr_is_soft_resettable(u32 board_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(soft_unresettable_controller); i++) + if (soft_unresettable_controller[i] == board_id) + return 0; + return 1; +} + +static int ctlr_is_resettable(u32 board_id) +{ + return ctlr_is_hard_resettable(board_id) || + ctlr_is_soft_resettable(board_id); +} + static ssize_t host_show_resettable(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h = to_hba(dev); - return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h)); + return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h->board_id)); } static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL); @@ -2567,7 +2595,7 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, } } else if (cmd_type == TYPE_MSG) { switch (cmd) { - case 0: /* ABORT message */ + case CCISS_ABORT_MSG: c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_WRITE; @@ -2577,16 +2605,16 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, /* buff contains the tag of the command to abort */ memcpy(&c->Request.CDB[4], buff, 8); break; - case 1: /* RESET message */ + case CCISS_RESET_MSG: c->Request.CDBLen = 16; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_NONE; c->Request.Timeout = 0; memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] = cmd; /* reset */ - c->Request.CDB[1] = 0x03; /* reset a target */ + c->Request.CDB[1] = CCISS_RESET_TYPE_TARGET; break; - case 3: /* No-Op message */ + case CCISS_NOOP_MSG: c->Request.CDBLen = 1; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_WRITE; @@ -2615,6 +2643,31 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, return status; } +static int __devinit cciss_send_reset(ctlr_info_t *h, unsigned char *scsi3addr, + u8 reset_type) +{ + CommandList_struct *c; + int return_status; + + c = cmd_alloc(h); + if (!c) + return -ENOMEM; + return_status = fill_cmd(h, c, CCISS_RESET_MSG, NULL, 0, 0, + CTLR_LUNID, TYPE_MSG); + c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */ + if (return_status != IO_OK) { + cmd_special_free(h, c); + return return_status; + } + c->waiting = NULL; + enqueue_cmd_and_start_io(h, c); + /* Don't wait for completion, the reset won't complete. Don't free + * the command either. This is the last command we will send before + * re-initializing everything, so it doesn't matter and won't leak. + */ + return 0; +} + static int check_target_status(ctlr_info_t *h, CommandList_struct *c) { switch (c->err_info->ScsiStatus) { @@ -3461,6 +3514,63 @@ static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag) return next_command(h); } +/* Some controllers, like p400, will give us one interrupt + * after a soft reset, even if we turned interrupts off. + * Only need to check for this in the cciss_xxx_discard_completions + * functions. + */ +static int ignore_bogus_interrupt(ctlr_info_t *h) +{ + if (likely(!reset_devices)) + return 0; + + if (likely(h->interrupts_enabled)) + return 0; + + dev_info(&h->pdev->dev, "Received interrupt while interrupts disabled " + "(known firmware bug.) Ignoring.\n"); + + return 1; +} + +static irqreturn_t cciss_intx_discard_completions(int irq, void *dev_id) +{ + ctlr_info_t *h = dev_id; + unsigned long flags; + u32 raw_tag; + + if (ignore_bogus_interrupt(h)) + return IRQ_NONE; + + if (interrupt_not_for_us(h)) + return IRQ_NONE; + spin_lock_irqsave(&h->lock, flags); + while (interrupt_pending(h)) { + raw_tag = get_next_completion(h); + while (raw_tag != FIFO_EMPTY) + raw_tag = next_command(h); + } + spin_unlock_irqrestore(&h->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t cciss_msix_discard_completions(int irq, void *dev_id) +{ + ctlr_info_t *h = dev_id; + unsigned long flags; + u32 raw_tag; + + if (ignore_bogus_interrupt(h)) + return IRQ_NONE; + + spin_lock_irqsave(&h->lock, flags); + raw_tag = get_next_completion(h); + while (raw_tag != FIFO_EMPTY) + raw_tag = next_command(h); + spin_unlock_irqrestore(&h->lock, flags); + return IRQ_HANDLED; +} + static irqreturn_t do_cciss_intx(int irq, void *dev_id) { ctlr_info_t *h = dev_id; @@ -4078,6 +4188,9 @@ static int __devinit cciss_find_cfgtables(ctlr_info_t *h) cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable)); if (!h->cfgtable) return -ENOMEM; + rc = write_driver_ver_to_cfgtable(h->cfgtable); + if (rc) + return rc; /* Find performant mode table. */ trans_offset = readl(&h->cfgtable->TransMethodOffset); h->transtable = remap_pci_mem(pci_resource_start(h->pdev, @@ -4112,7 +4225,7 @@ static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h) static void __devinit cciss_find_board_params(ctlr_info_t *h) { cciss_get_max_perf_mode_cmds(h); - h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */ + h->nr_cmds = h->max_commands - 4 - cciss_tape_cmds; h->maxsgentries = readl(&(h->cfgtable->MaxSGElements)); /* * Limit in-command s/g elements to 32 save dma'able memory. @@ -4348,7 +4461,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); if ((tag & ~3) == paddr32) break; - schedule_timeout_uninterruptible(HZ); + msleep(CCISS_POST_RESET_NOOP_TIMEOUT_MSECS); } iounmap(vaddr); @@ -4375,11 +4488,10 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u return 0; } -#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0) #define cciss_noop(p) cciss_message(p, 3, 0) static int cciss_controller_hard_reset(struct pci_dev *pdev, - void * __iomem vaddr, bool use_doorbell) + void * __iomem vaddr, u32 use_doorbell) { u16 pmcsr; int pos; @@ -4390,8 +4502,7 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev, * other way using the doorbell register. */ dev_info(&pdev->dev, "using doorbell to reset controller\n"); - writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL); - msleep(1000); + writel(use_doorbell, vaddr + SA5_DOORBELL); } else { /* Try to do it the PCI power state way */ /* Quoting from the Open CISS Specification: "The Power @@ -4422,12 +4533,64 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev, pmcsr &= ~PCI_PM_CTRL_STATE_MASK; pmcsr |= PCI_D0; pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); - - msleep(500); } return 0; } +static __devinit void init_driver_version(char *driver_version, int len) +{ + memset(driver_version, 0, len); + strncpy(driver_version, "cciss " DRIVER_NAME, len - 1); +} + +static __devinit int write_driver_ver_to_cfgtable( + CfgTable_struct __iomem *cfgtable) +{ + char *driver_version; + int i, size = sizeof(cfgtable->driver_version); + + driver_version = kmalloc(size, GFP_KERNEL); + if (!driver_version) + return -ENOMEM; + + init_driver_version(driver_version, size); + for (i = 0; i < size; i++) + writeb(driver_version[i], &cfgtable->driver_version[i]); + kfree(driver_version); + return 0; +} + +static __devinit void read_driver_ver_from_cfgtable( + CfgTable_struct __iomem *cfgtable, unsigned char *driver_ver) +{ + int i; + + for (i = 0; i < sizeof(cfgtable->driver_version); i++) + driver_ver[i] = readb(&cfgtable->driver_version[i]); +} + +static __devinit int controller_reset_failed( + CfgTable_struct __iomem *cfgtable) +{ + + char *driver_ver, *old_driver_ver; + int rc, size = sizeof(cfgtable->driver_version); + + old_driver_ver = kmalloc(2 * size, GFP_KERNEL); + if (!old_driver_ver) + return -ENOMEM; + driver_ver = old_driver_ver + size; + + /* After a reset, the 32 bytes of "driver version" in the cfgtable + * should have been changed, otherwise we know the reset failed. + */ + init_driver_version(old_driver_ver, size); + read_driver_ver_from_cfgtable(cfgtable, driver_ver); + rc = !memcmp(driver_ver, old_driver_ver, size); + kfree(old_driver_ver); + return rc; +} + /* This does a hard reset of the controller using PCI power management * states or using the doorbell register. */ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) @@ -4437,10 +4600,10 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) u64 cfg_base_addr_index; void __iomem *vaddr; unsigned long paddr; - u32 misc_fw_support, active_transport; + u32 misc_fw_support; int rc; CfgTable_struct __iomem *cfgtable; - bool use_doorbell; + u32 use_doorbell; u32 board_id; u16 command_register; @@ -4464,12 +4627,16 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) * likely not be happy. Just forbid resetting this conjoined mess. */ cciss_lookup_board_id(pdev, &board_id); - if (board_id == 0x409C0E11 || board_id == 0x409D0E11) { + if (!ctlr_is_resettable(board_id)) { dev_warn(&pdev->dev, "Cannot reset Smart Array 640x " "due to shared cache module."); return -ENODEV; } + /* if controller is soft- but not hard resettable... */ + if (!ctlr_is_hard_resettable(board_id)) + return -ENOTSUPP; /* try soft reset later. */ + /* Save the PCI command register */ pci_read_config_word(pdev, 4, &command_register); /* Turn the board off. This is so that later pci_restore_state() @@ -4497,16 +4664,28 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) rc = -ENOMEM; goto unmap_vaddr; } + rc = write_driver_ver_to_cfgtable(cfgtable); + if (rc) + goto unmap_vaddr; - /* If reset via doorbell register is supported, use that. */ - misc_fw_support = readl(&cfgtable->misc_fw_support); - use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; - - /* The doorbell reset seems to cause lockups on some Smart - * Arrays (e.g. P410, P410i, maybe others). Until this is - * fixed or at least isolated, avoid the doorbell reset. + /* If reset via doorbell register is supported, use that. + * There are two such methods. Favor the newest method. */ - use_doorbell = 0; + misc_fw_support = readl(&cfgtable->misc_fw_support); + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2; + if (use_doorbell) { + use_doorbell = DOORBELL_CTLR_RESET2; + } else { + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; + if (use_doorbell) { + dev_warn(&pdev->dev, "Controller claims that " + "'Bit 2 doorbell reset' is " + "supported, but not 'bit 5 doorbell reset'. " + "Firmware update is recommended.\n"); + rc = -ENOTSUPP; /* use the soft reset */ + goto unmap_cfgtable; + } + } rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); if (rc) @@ -4524,30 +4703,31 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) msleep(CCISS_POST_RESET_PAUSE_MSECS); /* Wait for board to become not ready, then ready. */ - dev_info(&pdev->dev, "Waiting for board to become ready.\n"); + dev_info(&pdev->dev, "Waiting for board to reset.\n"); rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY); - if (rc) /* Don't bail, might be E500, etc. which can't be reset */ - dev_warn(&pdev->dev, - "failed waiting for board to become not ready\n"); + if (rc) { + dev_warn(&pdev->dev, "Failed waiting for board to hard reset." + " Will try soft reset.\n"); + rc = -ENOTSUPP; /* Not expected, but try soft reset later */ + goto unmap_cfgtable; + } rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_READY); if (rc) { dev_warn(&pdev->dev, - "failed waiting for board to become ready\n"); + "failed waiting for board to become ready " + "after hard reset\n"); goto unmap_cfgtable; } - dev_info(&pdev->dev, "board ready.\n"); - /* Controller should be in simple mode at this point. If it's not, - * It means we're on one of those controllers which doesn't support - * the doorbell reset method and on which the PCI power management reset - * method doesn't work (P800, for example.) - * In those cases, don't try to proceed, as it generally doesn't work. - */ - active_transport = readl(&cfgtable->TransportActive); - if (active_transport & PERFORMANT_MODE) { - dev_warn(&pdev->dev, "Unable to successfully reset controller," - " Ignoring controller.\n"); - rc = -ENODEV; + rc = controller_reset_failed(vaddr); + if (rc < 0) + goto unmap_cfgtable; + if (rc) { + dev_warn(&pdev->dev, "Unable to successfully hard reset " + "controller. Will try soft reset.\n"); + rc = -ENOTSUPP; /* Not expected, but try soft reset later */ + } else { + dev_info(&pdev->dev, "Board ready after hard reset.\n"); } unmap_cfgtable: @@ -4574,11 +4754,12 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev) * due to concerns about shared bbwc between 6402/6404 pair. */ if (rc == -ENOTSUPP) - return 0; /* just try to do the kdump anyhow. */ + return rc; /* just try to do the kdump anyhow. */ if (rc) return -ENODEV; /* Now try to get the controller to respond to a no-op */ + dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n"); for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) { if (cciss_noop(pdev) == 0) break; @@ -4591,6 +4772,148 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev) return 0; } +static __devinit int cciss_allocate_cmd_pool(ctlr_info_t *h) +{ + h->cmd_pool_bits = kmalloc( + DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) * + sizeof(unsigned long), GFP_KERNEL); + h->cmd_pool = pci_alloc_consistent(h->pdev, + h->nr_cmds * sizeof(CommandList_struct), + &(h->cmd_pool_dhandle)); + h->errinfo_pool = pci_alloc_consistent(h->pdev, + h->nr_cmds * sizeof(ErrorInfo_struct), + &(h->errinfo_pool_dhandle)); + if ((h->cmd_pool_bits == NULL) + || (h->cmd_pool == NULL) + || (h->errinfo_pool == NULL)) { + dev_err(&h->pdev->dev, "out of memory"); + return -ENOMEM; + } + return 0; +} + +static __devinit int cciss_allocate_scatterlists(ctlr_info_t *h) +{ + int i; + + /* zero it, so that on free we need not know how many were alloc'ed */ + h->scatter_list = kzalloc(h->max_commands * + sizeof(struct scatterlist *), GFP_KERNEL); + if (!h->scatter_list) + return -ENOMEM; + + for (i = 0; i < h->nr_cmds; i++) { + h->scatter_list[i] = kmalloc(sizeof(struct scatterlist) * + h->maxsgentries, GFP_KERNEL); + if (h->scatter_list[i] == NULL) { + dev_err(&h->pdev->dev, "could not allocate " + "s/g lists\n"); + return -ENOMEM; + } + } + return 0; +} + +static void cciss_free_scatterlists(ctlr_info_t *h) +{ + int i; + + if (h->scatter_list) { + for (i = 0; i < h->nr_cmds; i++) + kfree(h->scatter_list[i]); + kfree(h->scatter_list); + } +} + +static void cciss_free_cmd_pool(ctlr_info_t *h) +{ + kfree(h->cmd_pool_bits); + if (h->cmd_pool) + pci_free_consistent(h->pdev, + h->nr_cmds * sizeof(CommandList_struct), + h->cmd_pool, h->cmd_pool_dhandle); + if (h->errinfo_pool) + pci_free_consistent(h->pdev, + h->nr_cmds * sizeof(ErrorInfo_struct), + h->errinfo_pool, h->errinfo_pool_dhandle); +} + +static int cciss_request_irq(ctlr_info_t *h, + irqreturn_t (*msixhandler)(int, void *), + irqreturn_t (*intxhandler)(int, void *)) +{ + if (h->msix_vector || h->msi_vector) { + if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, + IRQF_DISABLED, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get msi irq %d" + " for %s\n", h->intr[PERF_MODE_INT], + h->devname); + return -1; + } + + if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, + IRQF_DISABLED, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", + h->intr[PERF_MODE_INT], h->devname); + return -1; +} + +static int __devinit cciss_kdump_soft_reset(ctlr_info_t *h) +{ + if (cciss_send_reset(h, CTLR_LUNID, CCISS_RESET_TYPE_CONTROLLER)) { + dev_warn(&h->pdev->dev, "Resetting array controller failed.\n"); + return -EIO; + } + + dev_info(&h->pdev->dev, "Waiting for board to soft reset.\n"); + if (cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY)) { + dev_warn(&h->pdev->dev, "Soft reset had no effect.\n"); + return -1; + } + + dev_info(&h->pdev->dev, "Board reset, awaiting READY status.\n"); + if (cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY)) { + dev_warn(&h->pdev->dev, "Board failed to become ready " + "after soft reset.\n"); + return -1; + } + + return 0; +} + +static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h) +{ + int ctlr = h->ctlr; + + free_irq(h->intr[PERF_MODE_INT], h); +#ifdef CONFIG_PCI_MSI + if (h->msix_vector) + pci_disable_msix(h->pdev); + else if (h->msi_vector) + pci_disable_msi(h->pdev); +#endif /* CONFIG_PCI_MSI */ + cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); + cciss_free_scatterlists(h); + cciss_free_cmd_pool(h); + kfree(h->blockFetchTable); + if (h->reply_pool) + pci_free_consistent(h->pdev, h->max_commands * sizeof(__u64), + h->reply_pool, h->reply_pool_dhandle); + if (h->transtable) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); + if (h->vaddr) + iounmap(h->vaddr); + unregister_blkdev(h->major, h->devname); + cciss_destroy_hba_sysfs_entry(h); + pci_release_regions(h->pdev); + kfree(h); + hba[ctlr] = NULL; +} + /* * This is it. Find all the controllers and register them. I really hate * stealing all these major device numbers. @@ -4601,15 +4924,28 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, { int i; int j = 0; - int k = 0; int rc; + int try_soft_reset = 0; int dac, return_code; InquiryData_struct *inq_buff; ctlr_info_t *h; + unsigned long flags; rc = cciss_init_reset_devices(pdev); - if (rc) - return rc; + if (rc) { + if (rc != -ENOTSUPP) + return rc; + /* If the reset fails in a particular way (it has no way to do + * a proper hard reset, so returns -ENOTSUPP) we can try to do + * a soft reset once we get the controller configured up to the + * point that it can accept a command. + */ + try_soft_reset = 1; + rc = 0; + } + +reinit_after_soft_reset: + i = alloc_cciss_hba(pdev); if (i < 0) return -1; @@ -4627,6 +4963,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, sprintf(h->devname, "cciss%d", i); h->ctlr = i; + if (cciss_tape_cmds < 2) + cciss_tape_cmds = 2; + if (cciss_tape_cmds > 16) + cciss_tape_cmds = 16; + init_completion(&h->scan_wait); if (cciss_create_hba_sysfs_entry(h)) @@ -4662,62 +5003,20 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* make sure the board interrupts are off */ h->access.set_intr_mask(h, CCISS_INTR_OFF); - if (h->msi_vector || h->msix_vector) { - if (request_irq(h->intr[PERF_MODE_INT], - do_cciss_msix_intr, - IRQF_DISABLED, h->devname, h)) { - dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", - h->intr[PERF_MODE_INT], h->devname); - goto clean2; - } - } else { - if (request_irq(h->intr[PERF_MODE_INT], do_cciss_intx, - IRQF_DISABLED, h->devname, h)) { - dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", - h->intr[PERF_MODE_INT], h->devname); - goto clean2; - } - } + rc = cciss_request_irq(h, do_cciss_msix_intr, do_cciss_intx); + if (rc) + goto clean2; dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", h->devname, pdev->device, pci_name(pdev), h->intr[PERF_MODE_INT], dac ? "" : " not"); - h->cmd_pool_bits = - kmalloc(DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) - * sizeof(unsigned long), GFP_KERNEL); - h->cmd_pool = (CommandList_struct *) - pci_alloc_consistent(h->pdev, - h->nr_cmds * sizeof(CommandList_struct), - &(h->cmd_pool_dhandle)); - h->errinfo_pool = (ErrorInfo_struct *) - pci_alloc_consistent(h->pdev, - h->nr_cmds * sizeof(ErrorInfo_struct), - &(h->errinfo_pool_dhandle)); - if ((h->cmd_pool_bits == NULL) - || (h->cmd_pool == NULL) - || (h->errinfo_pool == NULL)) { - dev_err(&h->pdev->dev, "out of memory"); + if (cciss_allocate_cmd_pool(h)) goto clean4; - } - /* Need space for temp scatter list */ - h->scatter_list = kmalloc(h->max_commands * - sizeof(struct scatterlist *), - GFP_KERNEL); - if (!h->scatter_list) + if (cciss_allocate_scatterlists(h)) goto clean4; - for (k = 0; k < h->nr_cmds; k++) { - h->scatter_list[k] = kmalloc(sizeof(struct scatterlist) * - h->maxsgentries, - GFP_KERNEL); - if (h->scatter_list[k] == NULL) { - dev_err(&h->pdev->dev, - "could not allocate s/g lists\n"); - goto clean4; - } - } h->cmd_sg_list = cciss_allocate_sg_chain_blocks(h, h->chainsize, h->nr_cmds); if (!h->cmd_sg_list && h->chainsize > 0) @@ -4741,6 +5040,62 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, h->gendisk[j] = NULL; } + /* At this point, the controller is ready to take commands. + * Now, if reset_devices and the hard reset didn't work, try + * the soft reset and see if that works. + */ + if (try_soft_reset) { + + /* This is kind of gross. We may or may not get a completion + * from the soft reset command, and if we do, then the value + * from the fifo may or may not be valid. So, we wait 10 secs + * after the reset throwing away any completions we get during + * that time. Unregister the interrupt handler and register + * fake ones to scoop up any residual completions. + */ + spin_lock_irqsave(&h->lock, flags); + h->access.set_intr_mask(h, CCISS_INTR_OFF); + spin_unlock_irqrestore(&h->lock, flags); + free_irq(h->intr[PERF_MODE_INT], h); + rc = cciss_request_irq(h, cciss_msix_discard_completions, + cciss_intx_discard_completions); + if (rc) { + dev_warn(&h->pdev->dev, "Failed to request_irq after " + "soft reset.\n"); + goto clean4; + } + + rc = cciss_kdump_soft_reset(h); + if (rc) { + dev_warn(&h->pdev->dev, "Soft reset failed.\n"); + goto clean4; + } + + dev_info(&h->pdev->dev, "Board READY.\n"); + dev_info(&h->pdev->dev, + "Waiting for stale completions to drain.\n"); + h->access.set_intr_mask(h, CCISS_INTR_ON); + msleep(10000); + h->access.set_intr_mask(h, CCISS_INTR_OFF); + + rc = controller_reset_failed(h->cfgtable); + if (rc) + dev_info(&h->pdev->dev, + "Soft reset appears to have failed.\n"); + + /* since the controller's reset, we have to go back and re-init + * everything. Easiest to just forget what we've done and do it + * all over again. + */ + cciss_undo_allocations_after_kdump_soft_reset(h); + try_soft_reset = 0; + if (rc) + /* don't go to clean4, we already unallocated */ + return -ENODEV; + + goto reinit_after_soft_reset; + } + cciss_scsi_setup(h); /* Turn the interrupts on so we can service requests */ @@ -4775,21 +5130,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, return 1; clean4: - kfree(h->cmd_pool_bits); - /* Free up sg elements */ - for (k-- ; k >= 0; k--) - kfree(h->scatter_list[k]); - kfree(h->scatter_list); + cciss_free_cmd_pool(h); + cciss_free_scatterlists(h); cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); - if (h->cmd_pool) - pci_free_consistent(h->pdev, - h->nr_cmds * sizeof(CommandList_struct), - h->cmd_pool, h->cmd_pool_dhandle); - if (h->errinfo_pool) - pci_free_consistent(h->pdev, - h->nr_cmds * sizeof(ErrorInfo_struct), - h->errinfo_pool, - h->errinfo_pool_dhandle); free_irq(h->intr[PERF_MODE_INT], h); clean2: unregister_blkdev(h->major, h->devname); @@ -4887,16 +5230,16 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) iounmap(h->cfgtable); iounmap(h->vaddr); - pci_free_consistent(h->pdev, h->nr_cmds * sizeof(CommandList_struct), - h->cmd_pool, h->cmd_pool_dhandle); - pci_free_consistent(h->pdev, h->nr_cmds * sizeof(ErrorInfo_struct), - h->errinfo_pool, h->errinfo_pool_dhandle); - kfree(h->cmd_pool_bits); + cciss_free_cmd_pool(h); /* Free up sg elements */ for (j = 0; j < h->nr_cmds; j++) kfree(h->scatter_list[j]); kfree(h->scatter_list); cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); + kfree(h->blockFetchTable); + if (h->reply_pool) + pci_free_consistent(h->pdev, h->max_commands * sizeof(__u64), + h->reply_pool, h->reply_pool_dhandle); /* * Deliberately omit pci_disable_device(): it does something nasty to * Smart Array controllers that pci_enable_device does not undo diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 554bbd907d1..16b4d58d84d 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -200,7 +200,7 @@ struct ctlr_info * the above. */ #define CCISS_BOARD_READY_WAIT_SECS (120) -#define CCISS_BOARD_NOT_READY_WAIT_SECS (10) +#define CCISS_BOARD_NOT_READY_WAIT_SECS (100) #define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100) #define CCISS_BOARD_READY_ITERATIONS \ ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \ @@ -209,8 +209,9 @@ struct ctlr_info ((CCISS_BOARD_NOT_READY_WAIT_SECS * 1000) / \ CCISS_BOARD_READY_POLL_INTERVAL_MSECS) #define CCISS_POST_RESET_PAUSE_MSECS (3000) -#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000) +#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (4000) #define CCISS_POST_RESET_NOOP_RETRIES (12) +#define CCISS_POST_RESET_NOOP_TIMEOUT_MSECS (10000) /* Send the command to the hardware @@ -239,11 +240,13 @@ static void SA5_intr_mask(ctlr_info_t *h, unsigned long val) { /* Turn interrupts on */ h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { h->interrupts_enabled = 0; writel( SA5_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } } /* @@ -257,11 +260,13 @@ static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val) { /* Turn interrupts on */ h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { h->interrupts_enabled = 0; writel( SA5B_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } } @@ -271,10 +276,12 @@ static void SA5_performant_intr_mask(ctlr_info_t *h, unsigned long val) if (val) { /* turn on interrupts */ h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else { h->interrupts_enabled = 0; writel(SA5_PERF_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } } diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd441bef031..d9be6b4d49a 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -53,6 +53,7 @@ #define CFGTBL_ChangeReq 0x00000001l #define CFGTBL_AccCmds 0x00000001l #define DOORBELL_CTLR_RESET 0x00000004l +#define DOORBELL_CTLR_RESET2 0x00000020l #define CFGTBL_Trans_Simple 0x00000002l #define CFGTBL_Trans_Performant 0x00000004l @@ -142,6 +143,14 @@ typedef struct _ReadCapdata_struct_16 #define BMIC_CACHE_FLUSH 0xc2 #define CCISS_CACHE_FLUSH 0x01 /* C2 was already being used by CCISS */ +#define CCISS_ABORT_MSG 0x00 +#define CCISS_RESET_MSG 0x01 +#define CCISS_RESET_TYPE_CONTROLLER 0x00 +#define CCISS_RESET_TYPE_BUS 0x01 +#define CCISS_RESET_TYPE_TARGET 0x03 +#define CCISS_RESET_TYPE_LUN 0x04 +#define CCISS_NOOP_MSG 0x03 + /* Command List Structure */ #define CTLR_LUNID "\0\0\0\0\0\0\0\0" @@ -235,6 +244,8 @@ typedef struct _CfgTable_struct { u8 reserved[0x78 - 0x58]; u32 misc_fw_support; /* offset 0x78 */ #define MISC_FW_DOORBELL_RESET (0x02) +#define MISC_FW_DOORBELL_RESET2 (0x10) + u8 driver_version[32]; } CfgTable_struct; struct TransTable_struct { diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index df793803f5a..696100241a6 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -84,7 +84,6 @@ static struct scsi_host_template cciss_driver_template = { .proc_name = "cciss", .proc_info = cciss_scsi_proc_info, .queuecommand = cciss_scsi_queue_command, - .can_queue = SCSI_CCISS_CAN_QUEUE, .this_id = 7, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, @@ -108,16 +107,13 @@ struct cciss_scsi_cmd_stack_elem_t { #pragma pack() -#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \ - CCISS_MAX_SCSI_DEVS_PER_HBA + 2) - // plus two for init time usage - #pragma pack(1) struct cciss_scsi_cmd_stack_t { struct cciss_scsi_cmd_stack_elem_t *pool; - struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE]; + struct cciss_scsi_cmd_stack_elem_t **elem; dma_addr_t cmd_pool_handle; int top; + int nelems; }; #pragma pack() @@ -191,7 +187,7 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c) sa = h->scsi_ctlr; stk = &sa->cmd_stack; stk->top++; - if (stk->top >= CMD_STACK_SIZE) { + if (stk->top >= stk->nelems) { dev_err(&h->pdev->dev, "scsi_cmd_free called too many times.\n"); BUG(); @@ -206,13 +202,14 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) struct cciss_scsi_cmd_stack_t *stk; size_t size; + stk = &sa->cmd_stack; + stk->nelems = cciss_tape_cmds + 2; sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h, - h->chainsize, CMD_STACK_SIZE); + h->chainsize, stk->nelems); if (!sa->cmd_sg_list && h->chainsize > 0) return -ENOMEM; - stk = &sa->cmd_stack; - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems; /* Check alignment, see cciss_cmd.h near CommandList_struct def. */ BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0); @@ -221,18 +218,23 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle); if (stk->pool == NULL) { - cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); + cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems); sa->cmd_sg_list = NULL; return -ENOMEM; } - - for (i=0; i<CMD_STACK_SIZE; i++) { + stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL); + if (!stk->elem) { + pci_free_consistent(h->pdev, size, stk->pool, + stk->cmd_pool_handle); + return -1; + } + for (i = 0; i < stk->nelems; i++) { stk->elem[i] = &stk->pool[i]; stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); stk->elem[i]->cmdindex = i; } - stk->top = CMD_STACK_SIZE-1; + stk->top = stk->nelems-1; return 0; } @@ -245,16 +247,18 @@ scsi_cmd_stack_free(ctlr_info_t *h) sa = h->scsi_ctlr; stk = &sa->cmd_stack; - if (stk->top != CMD_STACK_SIZE-1) { + if (stk->top != stk->nelems-1) { dev_warn(&h->pdev->dev, "bug: %d scsi commands are still outstanding.\n", - CMD_STACK_SIZE - stk->top); + stk->nelems - stk->top); } - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems; pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle); stk->pool = NULL; - cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); + cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems); + kfree(stk->elem); + stk->elem = NULL; } #if 0 @@ -859,6 +863,7 @@ cciss_scsi_detect(ctlr_info_t *h) sh->io_port = 0; // good enough? FIXME, sh->n_io_port = 0; // I don't think we use these two... sh->this_id = SELF_SCSI_ID; + sh->can_queue = cciss_tape_cmds; sh->sg_tablesize = h->maxsgentries; sh->max_cmd_len = MAX_COMMAND_SIZE; diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h index 6d5822fe851..e71d986727c 100644 --- a/drivers/block/cciss_scsi.h +++ b/drivers/block/cciss_scsi.h @@ -36,13 +36,9 @@ addressible natively, and may in fact turn out to be not scsi at all. */ -#define SCSI_CCISS_CAN_QUEUE 2 /* -Note, cmd_per_lun could give us some trouble, so I'm setting it very low. -Likewise, SCSI_CCISS_CAN_QUEUE is set very conservatively. - If the upper scsi layer tries to track how many commands we have outstanding, it will be operating under the misapprehension that it is the only one sending us requests. We also have the block interface, diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index c6828b68d77..09ef9a878ef 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -28,7 +28,7 @@ #include "drbd_int.h" #include "drbd_wrappers.h" -/* We maintain a trivial check sum in our on disk activity log. +/* We maintain a trivial checksum in our on disk activity log. * With that we can ensure correct operation even when the storage * device might do a partial (last) sector write while losing power. */ diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 76210ba401a..f440a02dfdb 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -74,7 +74,7 @@ * as we are "attached" to a local disk, which at 32 GiB for 1PiB storage * seems excessive. * - * We plan to reduce the amount of in-core bitmap pages by pageing them in + * We plan to reduce the amount of in-core bitmap pages by paging them in * and out against their on-disk location as necessary, but need to make * sure we don't cause too much meta data IO, and must not deadlock in * tight memory situations. This needs some more work. @@ -200,7 +200,7 @@ void drbd_bm_unlock(struct drbd_conf *mdev) * we if bits have been cleared since last IO. */ #define BM_PAGE_LAZY_WRITEOUT 28 -/* store_page_idx uses non-atomic assingment. It is only used directly after +/* store_page_idx uses non-atomic assignment. It is only used directly after * allocating the page. All other bm_set_page_* and bm_clear_page_* need to * use atomic bit manipulation, as set_out_of_sync (and therefore bitmap * changes) may happen from various contexts, and wait_on_bit/wake_up_bit @@ -318,7 +318,7 @@ static void bm_unmap(unsigned long *p_addr) /* word offset from start of bitmap to word number _in_page_ * modulo longs per page #define MLPP(X) ((X) % (PAGE_SIZE/sizeof(long)) - hm, well, Philipp thinks gcc might not optimze the % into & (... - 1) + hm, well, Philipp thinks gcc might not optimize the % into & (... - 1) so do it explicitly: */ #define MLPP(X) ((X) & ((PAGE_SIZE/sizeof(long))-1)) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index d871b14ed5a..ef2ceed3be4 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -700,7 +700,7 @@ struct drbd_request { * see drbd_endio_pri(). */ struct bio *private_bio; - struct hlist_node colision; + struct hlist_node collision; sector_t sector; unsigned int size; unsigned int epoch; /* barrier_nr */ @@ -766,7 +766,7 @@ struct digest_info { struct drbd_epoch_entry { struct drbd_work w; - struct hlist_node colision; + struct hlist_node collision; struct drbd_epoch *epoch; /* for writes */ struct drbd_conf *mdev; struct page *pages; @@ -1129,6 +1129,8 @@ struct drbd_conf { int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ int rs_planed; /* resync sectors already planned */ atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */ + int peer_max_bio_size; + int local_max_bio_size; }; static inline struct drbd_conf *minor_to_mdev(unsigned int minor) @@ -1218,8 +1220,6 @@ extern void drbd_free_resources(struct drbd_conf *mdev); extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr, unsigned int set_size); extern void tl_clear(struct drbd_conf *mdev); -enum drbd_req_event; -extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what); extern void _tl_add_barrier(struct drbd_conf *, struct drbd_tl_epoch *); extern void drbd_free_sock(struct drbd_conf *mdev); extern int drbd_send(struct drbd_conf *mdev, struct socket *sock, @@ -1434,6 +1434,7 @@ struct bm_extent { * hash table. */ #define HT_SHIFT 8 #define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT)) +#define DRBD_MAX_BIO_SIZE_SAFE (1 << 12) /* Works always = 4k */ #define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */ @@ -1518,9 +1519,9 @@ extern void drbd_resume_io(struct drbd_conf *mdev); extern char *ppsize(char *buf, unsigned long long size); extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int); enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 }; -extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local); +extern enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local); extern void resync_after_online_grow(struct drbd_conf *); -extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local); +extern void drbd_reconsider_max_bio_size(struct drbd_conf *mdev); extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force); @@ -1828,6 +1829,8 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, if (!forcedetach) { if (__ratelimit(&drbd_ratelimit_state)) dev_err(DEV, "Local IO failed in %s.\n", where); + if (mdev->state.disk > D_INCONSISTENT) + _drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_HARD, NULL); break; } /* NOTE fall through to detach case if forcedetach set */ @@ -2153,6 +2156,10 @@ static inline int get_net_conf(struct drbd_conf *mdev) static inline void put_ldev(struct drbd_conf *mdev) { int i = atomic_dec_return(&mdev->local_cnt); + + /* This may be called from some endio handler, + * so we must not sleep here. */ + __release(local); D_ASSERT(i >= 0); if (i == 0) { diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5b525c179f3..0358e55356c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -745,6 +745,9 @@ is_valid_state(struct drbd_conf *mdev, union drbd_state ns) mdev->agreed_pro_version < 88) rv = SS_NOT_SUPPORTED; + else if (ns.conn >= C_CONNECTED && ns.pdsk == D_UNKNOWN) + rv = SS_CONNECTED_OUTDATES; + return rv; } @@ -1565,6 +1568,10 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, put_ldev(mdev); } + /* Notify peer that I had a local IO error, and did not detached.. */ + if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT) + drbd_send_state(mdev); + /* Disks got bigger while they were detached */ if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING && test_and_clear_bit(RESYNC_AFTER_NEG, &mdev->flags)) { @@ -2064,7 +2071,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl { struct p_sizes p; sector_t d_size, u_size; - int q_order_type; + int q_order_type, max_bio_size; int ok; if (get_ldev_if_state(mdev, D_NEGOTIATING)) { @@ -2072,17 +2079,20 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl d_size = drbd_get_max_capacity(mdev->ldev); u_size = mdev->ldev->dc.disk_size; q_order_type = drbd_queue_order_type(mdev); + max_bio_size = queue_max_hw_sectors(mdev->ldev->backing_bdev->bd_disk->queue) << 9; + max_bio_size = min_t(int, max_bio_size, DRBD_MAX_BIO_SIZE); put_ldev(mdev); } else { d_size = 0; u_size = 0; q_order_type = QUEUE_ORDERED_NONE; + max_bio_size = DRBD_MAX_BIO_SIZE; /* ... multiple BIOs per peer_request */ } p.d_size = cpu_to_be64(d_size); p.u_size = cpu_to_be64(u_size); p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev)); - p.max_bio_size = cpu_to_be32(queue_max_hw_sectors(mdev->rq_queue) << 9); + p.max_bio_size = cpu_to_be32(max_bio_size); p.queue_order_type = cpu_to_be16(q_order_type); p.dds_flags = cpu_to_be16(flags); @@ -2722,7 +2732,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) /* double check digest, sometimes buffers have been modified in flight. */ if (dgs > 0 && dgs <= 64) { - /* 64 byte, 512 bit, is the larges digest size + /* 64 byte, 512 bit, is the largest digest size * currently supported in kernel crypto. */ unsigned char digest[64]; drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, digest); @@ -3041,6 +3051,8 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) mdev->agreed_pro_version = PRO_VERSION_MAX; mdev->write_ordering = WO_bdev_flush; mdev->resync_wenr = LC_FREE; + mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE; + mdev->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE; } void drbd_mdev_cleanup(struct drbd_conf *mdev) @@ -3275,7 +3287,7 @@ static void drbd_delete_device(unsigned int minor) drbd_release_ee_lists(mdev); - /* should be free'd on disconnect? */ + /* should be freed on disconnect? */ kfree(mdev->ee_hash); /* mdev->ee_hash_s = 0; @@ -3415,7 +3427,9 @@ struct drbd_conf *drbd_new_device(unsigned int minor) q->backing_dev_info.congested_data = mdev; blk_queue_make_request(q, drbd_make_request); - blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9); + /* Setting the max_hw_sectors to an odd value of 8kibyte here + This triggers a max_bio_size message upon first attach or connect */ + blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_merge_bvec(q, drbd_merge_bvec); q->queue_lock = &mdev->req_lock; @@ -3627,7 +3641,8 @@ struct meta_data_on_disk { /* `-- act_log->nr_elements <-- sync_conf.al_extents */ u32 bm_offset; /* offset to the bitmap, from here */ u32 bm_bytes_per_bit; /* BM_BLOCK_SIZE */ - u32 reserved_u32[4]; + u32 la_peer_max_bio_size; /* last peer max_bio_size */ + u32 reserved_u32[3]; } __packed; @@ -3668,6 +3683,7 @@ void drbd_md_sync(struct drbd_conf *mdev) buffer->device_uuid = cpu_to_be64(mdev->ldev->md.device_uuid); buffer->bm_offset = cpu_to_be32(mdev->ldev->md.bm_offset); + buffer->la_peer_max_bio_size = cpu_to_be32(mdev->peer_max_bio_size); D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset); sector = mdev->ldev->md.md_offset; @@ -3751,6 +3767,15 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) mdev->sync_conf.al_extents = be32_to_cpu(buffer->al_nr_extents); bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid); + spin_lock_irq(&mdev->req_lock); + if (mdev->state.conn < C_CONNECTED) { + int peer; + peer = be32_to_cpu(buffer->la_peer_max_bio_size); + peer = max_t(int, peer, DRBD_MAX_BIO_SIZE_SAFE); + mdev->peer_max_bio_size = peer; + } + spin_unlock_irq(&mdev->req_lock); + if (mdev->sync_conf.al_extents < 7) mdev->sync_conf.al_extents = 127; diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 03b29f78a37..515bcd948a4 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -272,9 +272,28 @@ static int _try_outdate_peer_async(void *data) { struct drbd_conf *mdev = (struct drbd_conf *)data; enum drbd_disk_state nps; + union drbd_state ns; nps = drbd_try_outdate_peer(mdev); - drbd_request_state(mdev, NS(pdsk, nps)); + + /* Not using + drbd_request_state(mdev, NS(pdsk, nps)); + here, because we might were able to re-establish the connection + in the meantime. This can only partially be solved in the state's + engine is_valid_state() and is_valid_state_transition() + functions. + + nps can be D_INCONSISTENT, D_OUTDATED or D_UNKNOWN. + pdsk == D_INCONSISTENT while conn >= C_CONNECTED is valid, + therefore we have to have the pre state change check here. + */ + spin_lock_irq(&mdev->req_lock); + ns = mdev->state; + if (ns.conn < C_WF_REPORT_PARAMS) { + ns.pdsk = nps; + _drbd_set_state(mdev, ns, CS_VERBOSE, NULL); + } + spin_unlock_irq(&mdev->req_lock); return 0; } @@ -577,7 +596,7 @@ void drbd_resume_io(struct drbd_conf *mdev) * Returns 0 on success, negative return values indicate errors. * You should call drbd_md_sync() after calling this function. */ -enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local) +enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local) { sector_t prev_first_sect, prev_size; /* previous meta location */ sector_t la_size; @@ -773,30 +792,78 @@ static int drbd_check_al_size(struct drbd_conf *mdev) return 0; } -void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) __must_hold(local) +static void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) { struct request_queue * const q = mdev->rq_queue; - struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; - int max_segments = mdev->ldev->dc.max_bio_bvecs; - int max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); + int max_hw_sectors = max_bio_size >> 9; + int max_segments = 0; + + if (get_ldev_if_state(mdev, D_ATTACHING)) { + struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; + + max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); + max_segments = mdev->ldev->dc.max_bio_bvecs; + put_ldev(mdev); + } blk_queue_logical_block_size(q, 512); blk_queue_max_hw_sectors(q, max_hw_sectors); /* This is the workaround for "bio would need to, but cannot, be split" */ blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS); blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1); - blk_queue_stack_limits(q, b); - dev_info(DEV, "max BIO size = %u\n", queue_max_hw_sectors(q) << 9); + if (get_ldev_if_state(mdev, D_ATTACHING)) { + struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; + + blk_queue_stack_limits(q, b); - if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { - dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n", - q->backing_dev_info.ra_pages, - b->backing_dev_info.ra_pages); - q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages; + if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { + dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n", + q->backing_dev_info.ra_pages, + b->backing_dev_info.ra_pages); + q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages; + } + put_ldev(mdev); } } +void drbd_reconsider_max_bio_size(struct drbd_conf *mdev) +{ + int now, new, local, peer; + + now = queue_max_hw_sectors(mdev->rq_queue) << 9; + local = mdev->local_max_bio_size; /* Eventually last known value, from volatile memory */ + peer = mdev->peer_max_bio_size; /* Eventually last known value, from meta data */ + + if (get_ldev_if_state(mdev, D_ATTACHING)) { + local = queue_max_hw_sectors(mdev->ldev->backing_bdev->bd_disk->queue) << 9; + mdev->local_max_bio_size = local; + put_ldev(mdev); + } + + /* We may ignore peer limits if the peer is modern enough. + Because new from 8.3.8 onwards the peer can use multiple + BIOs for a single peer_request */ + if (mdev->state.conn >= C_CONNECTED) { + if (mdev->agreed_pro_version < 94) + peer = mdev->peer_max_bio_size; + else if (mdev->agreed_pro_version == 94) + peer = DRBD_MAX_SIZE_H80_PACKET; + else /* drbd 8.3.8 onwards */ + peer = DRBD_MAX_BIO_SIZE; + } + + new = min_t(int, local, peer); + + if (mdev->state.role == R_PRIMARY && new < now) + dev_err(DEV, "ASSERT FAILED new < now; (%d < %d)\n", new, now); + + if (new != now) + dev_info(DEV, "max BIO size = %u\n", new); + + drbd_setup_queue_param(mdev, new); +} + /* serialize deconfig (worker exiting, doing cleanup) * and reconfig (drbdsetup disk, drbdsetup net) * @@ -865,7 +932,6 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp struct block_device *bdev; struct lru_cache *resync_lru = NULL; union drbd_state ns, os; - unsigned int max_bio_size; enum drbd_state_rv rv; int cp_discovered = 0; int logical_block_size; @@ -1117,20 +1183,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp mdev->read_cnt = 0; mdev->writ_cnt = 0; - max_bio_size = DRBD_MAX_BIO_SIZE; - if (mdev->state.conn == C_CONNECTED) { - /* We are Primary, Connected, and now attach a new local - * backing store. We must not increase the user visible maximum - * bio size on this device to something the peer may not be - * able to handle. */ - if (mdev->agreed_pro_version < 94) - max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9; - else if (mdev->agreed_pro_version == 94) - max_bio_size = DRBD_MAX_SIZE_H80_PACKET; - /* else: drbd 8.3.9 and later, stay with default */ - } - - drbd_setup_queue_param(mdev, max_bio_size); + drbd_reconsider_max_bio_size(mdev); /* If I am currently not R_PRIMARY, * but meta data primary indicator is set, @@ -1152,7 +1205,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND)) set_bit(USE_DEGR_WFC_T, &mdev->flags); - dd = drbd_determin_dev_size(mdev, 0); + dd = drbd_determine_dev_size(mdev, 0); if (dd == dev_size_error) { retcode = ERR_NOMEM_BITMAP; goto force_diskless_dec; @@ -1281,11 +1334,19 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, struct drbd_nl_cfg_reply *reply) { + enum drbd_ret_code retcode; + int ret; drbd_suspend_io(mdev); /* so no-one is stuck in drbd_al_begin_io */ - reply->ret_code = drbd_request_state(mdev, NS(disk, D_DISKLESS)); - if (mdev->state.disk == D_DISKLESS) - wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); + retcode = drbd_request_state(mdev, NS(disk, D_FAILED)); + /* D_FAILED will transition to DISKLESS. */ + ret = wait_event_interruptible(mdev->misc_wait, + mdev->state.disk != D_FAILED); drbd_resume_io(mdev); + if ((int)retcode == (int)SS_IS_DISKLESS) + retcode = SS_NOTHING_TO_DO; + if (ret) + retcode = ERR_INTR; + reply->ret_code = retcode; return 0; } @@ -1658,7 +1719,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); - dd = drbd_determin_dev_size(mdev, ddsf); + dd = drbd_determine_dev_size(mdev, ddsf); drbd_md_sync(mdev); put_ldev(mdev); if (dd == dev_size_error) { diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index fd26666c0b0..25d32c5aa50 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -333,7 +333,7 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev, if (!page) goto fail; - INIT_HLIST_NODE(&e->colision); + INIT_HLIST_NODE(&e->collision); e->epoch = NULL; e->mdev = mdev; e->pages = page; @@ -356,7 +356,7 @@ void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int i kfree(e->digest); drbd_pp_free(mdev, e->pages, is_net); D_ASSERT(atomic_read(&e->pending_bios) == 0); - D_ASSERT(hlist_unhashed(&e->colision)); + D_ASSERT(hlist_unhashed(&e->collision)); mempool_free(e, drbd_ee_mempool); } @@ -787,7 +787,7 @@ static int drbd_connect(struct drbd_conf *mdev) } if (sock && msock) { - schedule_timeout_interruptible(HZ / 10); + schedule_timeout_interruptible(mdev->net_conf->ping_timeo*HZ/10); ok = drbd_socket_okay(mdev, &sock); ok = drbd_socket_okay(mdev, &msock) && ok; if (ok) @@ -899,11 +899,6 @@ retry: drbd_thread_start(&mdev->asender); - if (mdev->agreed_pro_version < 95 && get_ldev(mdev)) { - drbd_setup_queue_param(mdev, DRBD_MAX_SIZE_H80_PACKET); - put_ldev(mdev); - } - if (drbd_send_protocol(mdev) == -1) return -1; drbd_send_sync_param(mdev, &mdev->sync_conf); @@ -1418,7 +1413,7 @@ static int e_end_resync_block(struct drbd_conf *mdev, struct drbd_work *w, int u sector_t sector = e->sector; int ok; - D_ASSERT(hlist_unhashed(&e->colision)); + D_ASSERT(hlist_unhashed(&e->collision)); if (likely((e->flags & EE_WAS_ERROR) == 0)) { drbd_set_in_sync(mdev, sector, e->size); @@ -1487,7 +1482,7 @@ static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsi return false; } - /* hlist_del(&req->colision) is done in _req_may_be_done, to avoid + /* hlist_del(&req->collision) is done in _req_may_be_done, to avoid * special casing it there for the various failure cases. * still no race with drbd_fail_pending_reads */ ok = recv_dless_read(mdev, req, sector, data_size); @@ -1558,11 +1553,11 @@ static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel) * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right. */ if (mdev->net_conf->two_primaries) { spin_lock_irq(&mdev->req_lock); - D_ASSERT(!hlist_unhashed(&e->colision)); - hlist_del_init(&e->colision); + D_ASSERT(!hlist_unhashed(&e->collision)); + hlist_del_init(&e->collision); spin_unlock_irq(&mdev->req_lock); } else { - D_ASSERT(hlist_unhashed(&e->colision)); + D_ASSERT(hlist_unhashed(&e->collision)); } drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + (cancel ? EV_CLEANUP : 0)); @@ -1579,8 +1574,8 @@ static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int u ok = drbd_send_ack(mdev, P_DISCARD_ACK, e); spin_lock_irq(&mdev->req_lock); - D_ASSERT(!hlist_unhashed(&e->colision)); - hlist_del_init(&e->colision); + D_ASSERT(!hlist_unhashed(&e->collision)); + hlist_del_init(&e->collision); spin_unlock_irq(&mdev->req_lock); dec_unacked(mdev); @@ -1755,7 +1750,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned spin_lock_irq(&mdev->req_lock); - hlist_add_head(&e->colision, ee_hash_slot(mdev, sector)); + hlist_add_head(&e->collision, ee_hash_slot(mdev, sector)); #define OVERLAPS overlaps(i->sector, i->size, sector, size) slot = tl_hash_slot(mdev, sector); @@ -1765,7 +1760,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int have_conflict = 0; prepare_to_wait(&mdev->misc_wait, &wait, TASK_INTERRUPTIBLE); - hlist_for_each_entry(i, n, slot, colision) { + hlist_for_each_entry(i, n, slot, collision) { if (OVERLAPS) { /* only ALERT on first iteration, * we may be woken up early... */ @@ -1804,7 +1799,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned } if (signal_pending(current)) { - hlist_del_init(&e->colision); + hlist_del_init(&e->collision); spin_unlock_irq(&mdev->req_lock); @@ -1862,7 +1857,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned dev_err(DEV, "submit failed, triggering re-connect\n"); spin_lock_irq(&mdev->req_lock); list_del(&e->w.list); - hlist_del_init(&e->colision); + hlist_del_init(&e->collision); spin_unlock_irq(&mdev->req_lock); if (e->flags & EE_CALL_AL_COMPLETE_IO) drbd_al_complete_io(mdev, e->sector); @@ -2916,12 +2911,6 @@ disconnect: return false; } -static void drbd_setup_order_type(struct drbd_conf *mdev, int peer) -{ - /* sorry, we currently have no working implementation - * of distributed TCQ */ -} - /* warn if the arguments differ by more than 12.5% */ static void warn_if_differ_considerably(struct drbd_conf *mdev, const char *s, sector_t a, sector_t b) @@ -2939,7 +2928,6 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned { struct p_sizes *p = &mdev->data.rbuf.sizes; enum determine_dev_size dd = unchanged; - unsigned int max_bio_size; sector_t p_size, p_usize, my_usize; int ldsc = 0; /* local disk size changed */ enum dds_flags ddsf; @@ -2994,7 +2982,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned ddsf = be16_to_cpu(p->dds_flags); if (get_ldev(mdev)) { - dd = drbd_determin_dev_size(mdev, ddsf); + dd = drbd_determine_dev_size(mdev, ddsf); put_ldev(mdev); if (dd == dev_size_error) return false; @@ -3004,23 +2992,15 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned drbd_set_my_capacity(mdev, p_size); } + mdev->peer_max_bio_size = be32_to_cpu(p->max_bio_size); + drbd_reconsider_max_bio_size(mdev); + if (get_ldev(mdev)) { if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) { mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); ldsc = 1; } - if (mdev->agreed_pro_version < 94) - max_bio_size = be32_to_cpu(p->max_bio_size); - else if (mdev->agreed_pro_version == 94) - max_bio_size = DRBD_MAX_SIZE_H80_PACKET; - else /* drbd 8.3.8 onwards */ - max_bio_size = DRBD_MAX_BIO_SIZE; - - if (max_bio_size != queue_max_hw_sectors(mdev->rq_queue) << 9) - drbd_setup_queue_param(mdev, max_bio_size); - - drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type)); put_ldev(mdev); } @@ -4275,7 +4255,7 @@ static struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev, struct hlist_node *n; struct drbd_request *req; - hlist_for_each_entry(req, n, slot, colision) { + hlist_for_each_entry(req, n, slot, collision) { if ((unsigned long)req == (unsigned long)id) { if (req->sector != sector) { dev_err(DEV, "_ack_id_to_req: found req %p but it has " @@ -4554,6 +4534,7 @@ int drbd_asender(struct drbd_thread *thi) int received = 0; int expect = sizeof(struct p_header80); int empty; + int ping_timeout_active = 0; sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev)); @@ -4566,6 +4547,7 @@ int drbd_asender(struct drbd_thread *thi) ERR_IF(!drbd_send_ping(mdev)) goto reconnect; mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_timeo*HZ/10; + ping_timeout_active = 1; } /* conditionally cork; @@ -4620,8 +4602,7 @@ int drbd_asender(struct drbd_thread *thi) dev_err(DEV, "meta connection shut down by peer.\n"); goto reconnect; } else if (rv == -EAGAIN) { - if (mdev->meta.socket->sk->sk_rcvtimeo == - mdev->net_conf->ping_timeo*HZ/10) { + if (ping_timeout_active) { dev_err(DEV, "PingAck did not arrive in time.\n"); goto reconnect; } @@ -4660,6 +4641,11 @@ int drbd_asender(struct drbd_thread *thi) if (!cmd->process(mdev, h)) goto reconnect; + /* the idle_timeout (ping-int) + * has been restored in got_PingAck() */ + if (cmd == get_asender_cmd(P_PING_ACK)) + ping_timeout_active = 0; + buf = h; received = 0; expect = sizeof(struct p_header80); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 5c0c8be1bb0..3424d675b76 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -163,7 +163,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, * they must have been failed on the spot */ #define OVERLAPS overlaps(sector, size, i->sector, i->size) slot = tl_hash_slot(mdev, sector); - hlist_for_each_entry(i, n, slot, colision) { + hlist_for_each_entry(i, n, slot, collision) { if (OVERLAPS) { dev_alert(DEV, "LOGIC BUG: completed: %p %llus +%u; " "other: %p %llus +%u\n", @@ -187,7 +187,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, #undef OVERLAPS #define OVERLAPS overlaps(sector, size, e->sector, e->size) slot = ee_hash_slot(mdev, req->sector); - hlist_for_each_entry(e, n, slot, colision) { + hlist_for_each_entry(e, n, slot, collision) { if (OVERLAPS) { wake_up(&mdev->misc_wait); break; @@ -260,8 +260,8 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m) /* remove the request from the conflict detection * respective block_id verification hash */ - if (!hlist_unhashed(&req->colision)) - hlist_del(&req->colision); + if (!hlist_unhashed(&req->collision)) + hlist_del(&req->collision); else D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0); @@ -329,7 +329,7 @@ static int _req_conflicts(struct drbd_request *req) struct hlist_node *n; struct hlist_head *slot; - D_ASSERT(hlist_unhashed(&req->colision)); + D_ASSERT(hlist_unhashed(&req->collision)); if (!get_net_conf(mdev)) return 0; @@ -341,7 +341,7 @@ static int _req_conflicts(struct drbd_request *req) #define OVERLAPS overlaps(i->sector, i->size, sector, size) slot = tl_hash_slot(mdev, sector); - hlist_for_each_entry(i, n, slot, colision) { + hlist_for_each_entry(i, n, slot, collision) { if (OVERLAPS) { dev_alert(DEV, "%s[%u] Concurrent local write detected! " "[DISCARD L] new: %llus +%u; " @@ -359,7 +359,7 @@ static int _req_conflicts(struct drbd_request *req) #undef OVERLAPS #define OVERLAPS overlaps(e->sector, e->size, sector, size) slot = ee_hash_slot(mdev, sector); - hlist_for_each_entry(e, n, slot, colision) { + hlist_for_each_entry(e, n, slot, collision) { if (OVERLAPS) { dev_alert(DEV, "%s[%u] Concurrent remote write detected!" " [DISCARD L] new: %llus +%u; " @@ -491,7 +491,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, /* so we can verify the handle in the answer packet * corresponding hlist_del is in _req_may_be_done() */ - hlist_add_head(&req->colision, ar_hash_slot(mdev, req->sector)); + hlist_add_head(&req->collision, ar_hash_slot(mdev, req->sector)); set_bit(UNPLUG_REMOTE, &mdev->flags); @@ -507,7 +507,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, /* assert something? */ /* from drbd_make_request_common only */ - hlist_add_head(&req->colision, tl_hash_slot(mdev, req->sector)); + hlist_add_head(&req->collision, tl_hash_slot(mdev, req->sector)); /* corresponding hlist_del is in _req_may_be_done() */ /* NOTE @@ -1033,7 +1033,7 @@ fail_conflicting: err = 0; fail_free_complete: - if (rw == WRITE && local) + if (req->rq_state & RQ_IN_ACT_LOG) drbd_al_complete_io(mdev, sector); fail_and_free_req: if (local) { diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 32e2c3e6a81..68a234a5fdc 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -256,7 +256,7 @@ static inline struct drbd_request *_ar_id_to_req(struct drbd_conf *mdev, struct hlist_node *n; struct drbd_request *req; - hlist_for_each_entry(req, n, slot, colision) { + hlist_for_each_entry(req, n, slot, collision) { if ((unsigned long)req == (unsigned long)id) { D_ASSERT(req->sector == sector); return req; @@ -291,7 +291,7 @@ static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev, req->epoch = 0; req->sector = bio_src->bi_sector; req->size = bio_src->bi_size; - INIT_HLIST_NODE(&req->colision); + INIT_HLIST_NODE(&req->collision); INIT_LIST_HEAD(&req->tl_requests); INIT_LIST_HEAD(&req->w.list); } @@ -323,6 +323,7 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what, extern void complete_master_bio(struct drbd_conf *mdev, struct bio_and_error *m); extern void request_timer_fn(unsigned long data); +extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what); /* use this if you don't want to deal with calling complete_master_bio() * outside the spinlock, e.g. when walking some list on cleanup. */ diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index f7e6c92f8d0..4d76b06b6b2 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -126,7 +126,7 @@ static void drbd_endio_write_sec_final(struct drbd_epoch_entry *e) __releases(lo list_del(&e->w.list); /* has been on active_ee or sync_ee */ list_add_tail(&e->w.list, &mdev->done_ee); - /* No hlist_del_init(&e->colision) here, we did not send the Ack yet, + /* No hlist_del_init(&e->collision) here, we did not send the Ack yet, * neither did we wake possibly waiting conflicting requests. * done from "drbd_process_done_ee" within the appropriate w.cb * (e_end_block/e_end_resync_block) or from _drbd_clear_done_ee */ @@ -297,42 +297,48 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio * crypto_hash_final(&desc, digest); } -static int w_e_send_csum(struct drbd_conf *mdev, struct drbd_work *w, int cancel) +/* TODO merge common code with w_e_end_ov_req */ +int w_e_send_csum(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w); int digest_size; void *digest; - int ok; + int ok = 1; D_ASSERT(e->block_id == DRBD_MAGIC + 0xbeef); - if (unlikely(cancel)) { - drbd_free_ee(mdev, e); - return 1; - } + if (unlikely(cancel)) + goto out; - if (likely((e->flags & EE_WAS_ERROR) == 0)) { - digest_size = crypto_hash_digestsize(mdev->csums_tfm); - digest = kmalloc(digest_size, GFP_NOIO); - if (digest) { - drbd_csum_ee(mdev, mdev->csums_tfm, e, digest); + if (likely((e->flags & EE_WAS_ERROR) != 0)) + goto out; - inc_rs_pending(mdev); - ok = drbd_send_drequest_csum(mdev, - e->sector, - e->size, - digest, - digest_size, - P_CSUM_RS_REQUEST); - kfree(digest); - } else { - dev_err(DEV, "kmalloc() of digest failed.\n"); - ok = 0; - } - } else - ok = 1; + digest_size = crypto_hash_digestsize(mdev->csums_tfm); + digest = kmalloc(digest_size, GFP_NOIO); + if (digest) { + sector_t sector = e->sector; + unsigned int size = e->size; + drbd_csum_ee(mdev, mdev->csums_tfm, e, digest); + /* Free e and pages before send. + * In case we block on congestion, we could otherwise run into + * some distributed deadlock, if the other side blocks on + * congestion as well, because our receiver blocks in + * drbd_pp_alloc due to pp_in_use > max_buffers. */ + drbd_free_ee(mdev, e); + e = NULL; + inc_rs_pending(mdev); + ok = drbd_send_drequest_csum(mdev, sector, size, + digest, digest_size, + P_CSUM_RS_REQUEST); + kfree(digest); + } else { + dev_err(DEV, "kmalloc() of digest failed.\n"); + ok = 0; + } - drbd_free_ee(mdev, e); +out: + if (e) + drbd_free_ee(mdev, e); if (unlikely(!ok)) dev_err(DEV, "drbd_send_drequest(..., csum) failed\n"); @@ -834,7 +840,7 @@ int drbd_resync_finished(struct drbd_conf *mdev) const int ratio = (t == 0) ? 0 : (t < 100000) ? ((s*100)/t) : (s/(t/100)); - dev_info(DEV, "%u %% had equal check sums, eliminated: %luK; " + dev_info(DEV, "%u %% had equal checksums, eliminated: %luK; " "transferred %luK total %luK\n", ratio, Bit2KB(mdev->rs_same_csum), @@ -1071,9 +1077,12 @@ int w_e_end_csum_rs_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) return ok; } +/* TODO merge common code with w_e_send_csum */ int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w); + sector_t sector = e->sector; + unsigned int size = e->size; int digest_size; void *digest; int ok = 1; @@ -1093,17 +1102,25 @@ int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel) else memset(digest, 0, digest_size); + /* Free e and pages before send. + * In case we block on congestion, we could otherwise run into + * some distributed deadlock, if the other side blocks on + * congestion as well, because our receiver blocks in + * drbd_pp_alloc due to pp_in_use > max_buffers. */ + drbd_free_ee(mdev, e); + e = NULL; inc_rs_pending(mdev); - ok = drbd_send_drequest_csum(mdev, e->sector, e->size, - digest, digest_size, P_OV_REPLY); + ok = drbd_send_drequest_csum(mdev, sector, size, + digest, digest_size, + P_OV_REPLY); if (!ok) dec_rs_pending(mdev); kfree(digest); out: - drbd_free_ee(mdev, e); + if (e) + drbd_free_ee(mdev, e); dec_unacked(mdev); - return ok; } @@ -1122,8 +1139,10 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) { struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w); struct digest_info *di; - int digest_size; void *digest; + sector_t sector = e->sector; + unsigned int size = e->size; + int digest_size; int ok, eq = 0; if (unlikely(cancel)) { @@ -1153,16 +1172,21 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel) } } - dec_unacked(mdev); + /* Free e and pages before send. + * In case we block on congestion, we could otherwise run into + * some distributed deadlock, if the other side blocks on + * congestion as well, because our receiver blocks in + * drbd_pp_alloc due to pp_in_use > max_buffers. */ + drbd_free_ee(mdev, e); if (!eq) - drbd_ov_oos_found(mdev, e->sector, e->size); + drbd_ov_oos_found(mdev, sector, size); else ov_oos_print(mdev); - ok = drbd_send_ack_ex(mdev, P_OV_RESULT, e->sector, e->size, + ok = drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, eq ? ID_IN_SYNC : ID_OUT_OF_SYNC); - drbd_free_ee(mdev, e); + dec_unacked(mdev); --mdev->ov_left; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a076a14ca72..c59a672a3de 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1658,7 +1658,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data) struct kobject *kobj; mutex_lock(&loop_devices_mutex); - lo = loop_init_one(dev & MINORMASK); + lo = loop_init_one(MINOR(dev) >> part_shift); kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); mutex_unlock(&loop_devices_mutex); @@ -1691,15 +1691,18 @@ static int __init loop_init(void) if (max_part > 0) part_shift = fls(max_part); + if ((1UL << part_shift) > DISK_MAX_PARTS) + return -EINVAL; + if (max_loop > 1UL << (MINORBITS - part_shift)) return -EINVAL; if (max_loop) { nr = max_loop; - range = max_loop; + range = max_loop << part_shift; } else { nr = 8; - range = 1UL << (MINORBITS - part_shift); + range = 1UL << MINORBITS; } if (register_blkdev(LOOP_MAJOR, "loop")) @@ -1738,7 +1741,7 @@ static void __exit loop_exit(void) unsigned long range; struct loop_device *lo, *next; - range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift); + range = max_loop ? max_loop << part_shift : 1UL << MINORBITS; list_for_each_entry_safe(lo, next, &loop_devices, lo_list) loop_del_one(lo); diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 8690e31d993..a0aabd904a5 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -320,6 +320,8 @@ static void pcd_init_units(void) disk->first_minor = unit; strcpy(disk->disk_name, cd->name); /* umm... */ disk->fops = &pcd_bdops; + disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; + disk->events = DISK_EVENT_MEDIA_CHANGE; } } diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 9712fad82bc..1278098624e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1191,14 +1191,19 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) { struct rbd_device *dev = (struct rbd_device *)data; + int rc; + if (!dev) return; dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name, notify_id, (int)opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - __rbd_update_snaps(dev); + rc = __rbd_update_snaps(dev); mutex_unlock(&ctl_mutex); + if (rc) + pr_warning(DRV_NAME "%d got notification but failed to update" + " snaps: %d\n", dev->major, rc); rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name); } @@ -1597,7 +1602,7 @@ static int rbd_header_add_snap(struct rbd_device *dev, int name_len = strlen(snap_name); u64 new_snapid; int ret; - void *data, *data_start, *data_end; + void *data, *p, *e; u64 ver; /* we should create a snapshot only if we're pointing at the head */ @@ -1614,16 +1619,16 @@ static int rbd_header_add_snap(struct rbd_device *dev, if (!data) return -ENOMEM; - data_start = data; - data_end = data + name_len + 16; + p = data; + e = data + name_len + 16; - ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad); - ceph_encode_64_safe(&data, data_end, new_snapid, bad); + ceph_encode_string_safe(&p, e, snap_name, name_len, bad); + ceph_encode_64_safe(&p, e, new_snapid, bad); ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add", - data_start, data - data_start, &ver); + data, p - data, &ver); - kfree(data_start); + kfree(data); if (ret < 0) return ret; @@ -1659,6 +1664,9 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) if (ret < 0) return ret; + /* resized? */ + set_capacity(rbd_dev->disk, h.image_size / 512ULL); + down_write(&rbd_dev->header.snap_rwsem); snap_seq = rbd_dev->header.snapc->seq; @@ -1716,7 +1724,8 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) if (!disk) goto out; - sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id); + snprintf(disk->disk_name, sizeof(disk->disk_name), DRV_NAME "%d", + rbd_dev->id); disk->major = rbd_dev->major; disk->first_minor = 0; disk->fops = &rbd_bd_ops; diff --git a/drivers/block/xen-blkback/Makefile b/drivers/block/xen-blkback/Makefile new file mode 100644 index 00000000000..e491c1b7687 --- /dev/null +++ b/drivers/block/xen-blkback/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_XEN_BLKDEV_BACKEND) := xen-blkback.o + +xen-blkback-y := blkback.o xenbus.o diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c new file mode 100644 index 00000000000..c73910cc28c --- /dev/null +++ b/drivers/block/xen-blkback/blkback.c @@ -0,0 +1,824 @@ +/****************************************************************************** + * + * Back-end of the driver for virtual block devices. This portion of the + * driver exports a 'unified' block-device interface that can be accessed + * by any operating system that implements a compatible front end. A + * reference front-end implementation can be found in: + * drivers/block/xen-blkfront.c + * + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand + * Copyright (c) 2005, Christopher Clark + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <linux/spinlock.h> +#include <linux/kthread.h> +#include <linux/list.h> +#include <linux/delay.h> +#include <linux/freezer.h> + +#include <xen/events.h> +#include <xen/page.h> +#include <asm/xen/hypervisor.h> +#include <asm/xen/hypercall.h> +#include "common.h" + +/* + * These are rather arbitrary. They are fairly large because adjacent requests + * pulled from a communication ring are quite likely to end up being part of + * the same scatter/gather request at the disc. + * + * ** TRY INCREASING 'xen_blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** + * + * This will increase the chances of being able to write whole tracks. + * 64 should be enough to keep us competitive with Linux. + */ +static int xen_blkif_reqs = 64; +module_param_named(reqs, xen_blkif_reqs, int, 0); +MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate"); + +/* Run-time switchable: /sys/module/blkback/parameters/ */ +static unsigned int log_stats; +module_param(log_stats, int, 0644); + +/* + * Each outstanding request that we've passed to the lower device layers has a + * 'pending_req' allocated to it. Each buffer_head that completes decrements + * the pendcnt towards zero. When it hits zero, the specified domain has a + * response queued for it, with the saved 'id' passed back. + */ +struct pending_req { + struct xen_blkif *blkif; + u64 id; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; +}; + +#define BLKBACK_INVALID_HANDLE (~0) + +struct xen_blkbk { + struct pending_req *pending_reqs; + /* List of all 'pending_req' available */ + struct list_head pending_free; + /* And its spinlock. */ + spinlock_t pending_free_lock; + wait_queue_head_t pending_free_wq; + /* The list of all pages that are available. */ + struct page **pending_pages; + /* And the grant handles that are available. */ + grant_handle_t *pending_grant_handles; +}; + +static struct xen_blkbk *blkbk; + +/* + * Little helpful macro to figure out the index and virtual address of the + * pending_pages[..]. For each 'pending_req' we have have up to + * BLKIF_MAX_SEGMENTS_PER_REQUEST (11) pages. The seg would be from 0 through + * 10 and would index in the pending_pages[..]. + */ +static inline int vaddr_pagenr(struct pending_req *req, int seg) +{ + return (req - blkbk->pending_reqs) * + BLKIF_MAX_SEGMENTS_PER_REQUEST + seg; +} + +#define pending_page(req, seg) pending_pages[vaddr_pagenr(req, seg)] + +static inline unsigned long vaddr(struct pending_req *req, int seg) +{ + unsigned long pfn = page_to_pfn(blkbk->pending_page(req, seg)); + return (unsigned long)pfn_to_kaddr(pfn); +} + +#define pending_handle(_req, _seg) \ + (blkbk->pending_grant_handles[vaddr_pagenr(_req, _seg)]) + + +static int do_block_io_op(struct xen_blkif *blkif); +static int dispatch_rw_block_io(struct xen_blkif *blkif, + struct blkif_request *req, + struct pending_req *pending_req); +static void make_response(struct xen_blkif *blkif, u64 id, + unsigned short op, int st); + +/* + * Retrieve from the 'pending_reqs' a free pending_req structure to be used. + */ +static struct pending_req *alloc_req(void) +{ + struct pending_req *req = NULL; + unsigned long flags; + + spin_lock_irqsave(&blkbk->pending_free_lock, flags); + if (!list_empty(&blkbk->pending_free)) { + req = list_entry(blkbk->pending_free.next, struct pending_req, + free_list); + list_del(&req->free_list); + } + spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); + return req; +} + +/* + * Return the 'pending_req' structure back to the freepool. We also + * wake up the thread if it was waiting for a free page. + */ +static void free_req(struct pending_req *req) +{ + unsigned long flags; + int was_empty; + + spin_lock_irqsave(&blkbk->pending_free_lock, flags); + was_empty = list_empty(&blkbk->pending_free); + list_add(&req->free_list, &blkbk->pending_free); + spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); + if (was_empty) + wake_up(&blkbk->pending_free_wq); +} + +/* + * Routines for managing virtual block devices (vbds). + */ +static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif, + int operation) +{ + struct xen_vbd *vbd = &blkif->vbd; + int rc = -EACCES; + + if ((operation != READ) && vbd->readonly) + goto out; + + if (likely(req->nr_sects)) { + blkif_sector_t end = req->sector_number + req->nr_sects; + + if (unlikely(end < req->sector_number)) + goto out; + if (unlikely(end > vbd_sz(vbd))) + goto out; + } + + req->dev = vbd->pdevice; + req->bdev = vbd->bdev; + rc = 0; + + out: + return rc; +} + +static void xen_vbd_resize(struct xen_blkif *blkif) +{ + struct xen_vbd *vbd = &blkif->vbd; + struct xenbus_transaction xbt; + int err; + struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be); + unsigned long long new_size = vbd_sz(vbd); + + pr_info(DRV_PFX "VBD Resize: Domid: %d, Device: (%d, %d)\n", + blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); + pr_info(DRV_PFX "VBD Resize: new size %llu\n", new_size); + vbd->size = new_size; +again: + err = xenbus_transaction_start(&xbt); + if (err) { + pr_warn(DRV_PFX "Error starting transaction"); + return; + } + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", + (unsigned long long)vbd_sz(vbd)); + if (err) { + pr_warn(DRV_PFX "Error writing new size"); + goto abort; + } + /* + * Write the current state; we will use this to synchronize + * the front-end. If the current state is "connected" the + * front-end will get the new size information online. + */ + err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); + if (err) { + pr_warn(DRV_PFX "Error writing the state"); + goto abort; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + pr_warn(DRV_PFX "Error ending transaction"); + return; +abort: + xenbus_transaction_end(xbt, 1); +} + +/* + * Notification from the guest OS. + */ +static void blkif_notify_work(struct xen_blkif *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + +irqreturn_t xen_blkif_be_int(int irq, void *dev_id) +{ + blkif_notify_work(dev_id); + return IRQ_HANDLED; +} + +/* + * SCHEDULER FUNCTIONS + */ + +static void print_stats(struct xen_blkif *blkif) +{ + pr_info("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; +} + +int xen_blkif_schedule(void *arg) +{ + struct xen_blkif *blkif = arg; + struct xen_vbd *vbd = &blkif->vbd; + + xen_blkif_get(blkif); + + while (!kthread_should_stop()) { + if (try_to_freeze()) + continue; + if (unlikely(vbd->size != vbd_sz(vbd))) + xen_vbd_resize(blkif); + + wait_event_interruptible( + blkif->wq, + blkif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + blkbk->pending_free_wq, + !list_empty(&blkbk->pending_free) || + kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ + + if (do_block_io_op(blkif)) + blkif->waiting_reqs = 1; + + if (log_stats && time_after(jiffies, blkif->st_print)) + print_stats(blkif); + } + + if (log_stats) + print_stats(blkif); + + blkif->xenblkd = NULL; + xen_blkif_put(blkif); + + return 0; +} + +struct seg_buf { + unsigned long buf; + unsigned int nsec; +}; +/* + * Unmap the grant references, and also remove the M2P over-rides + * used in the 'pending_req'. + */ +static void xen_blkbk_unmap(struct pending_req *req) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int i, invcount = 0; + grant_handle_t handle; + int ret; + + for (i = 0; i < req->nr_pages; i++) { + handle = pending_handle(req, i); + if (handle == BLKBACK_INVALID_HANDLE) + continue; + gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i), + GNTMAP_host_map, handle); + pending_handle(req, i) = BLKBACK_INVALID_HANDLE; + invcount++; + } + + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, unmap, invcount); + BUG_ON(ret); + /* + * Note, we use invcount, so nr->pages, so we can't index + * using vaddr(req, i). + */ + for (i = 0; i < invcount; i++) { + ret = m2p_remove_override( + virt_to_page(unmap[i].host_addr), false); + if (ret) { + pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n", + (unsigned long)unmap[i].host_addr); + continue; + } + } +} + +static int xen_blkbk_map(struct blkif_request *req, + struct pending_req *pending_req, + struct seg_buf seg[]) +{ + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i; + int nseg = req->nr_segments; + int ret = 0; + + /* + * Fill out preq.nr_sects with proper amount of sectors, and setup + * assign map[..] with the PFN of the page in our domain with the + * corresponding grant reference for each page. + */ + for (i = 0; i < nseg; i++) { + uint32_t flags; + + flags = GNTMAP_host_map; + if (pending_req->operation != BLKIF_OP_READ) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags, + req->u.rw.seg[i].gref, + pending_req->blkif->domid); + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); + BUG_ON(ret); + + /* + * Now swizzle the MFN in our domain with the MFN from the other domain + * so that when we access vaddr(pending_req,i) it has the contents of + * the page from the other domain. + */ + for (i = 0; i < nseg; i++) { + if (unlikely(map[i].status != 0)) { + pr_debug(DRV_PFX "invalid buffer -- could not remap it\n"); + map[i].handle = BLKBACK_INVALID_HANDLE; + ret |= 1; + } + + pending_handle(pending_req, i) = map[i].handle; + + if (ret) + continue; + + ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr), + blkbk->pending_page(pending_req, i), false); + if (ret) { + pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n", + (unsigned long)map[i].dev_bus_addr, ret); + /* We could switch over to GNTTABOP_copy */ + continue; + } + + seg[i].buf = map[i].dev_bus_addr | + (req->u.rw.seg[i].first_sect << 9); + } + return ret; +} + +/* + * Completion callback on the bio's. Called as bh->b_end_io() + */ + +static void __end_block_io_op(struct pending_req *pending_req, int error) +{ + /* An error fails the entire request. */ + if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) && + (error == -EOPNOTSUPP)) { + pr_debug(DRV_PFX "flush diskcache op failed, not supported\n"); + xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); + pending_req->status = BLKIF_RSP_EOPNOTSUPP; + } else if (error) { + pr_debug(DRV_PFX "Buffer not up-to-date at end of operation," + " error=%d\n", error); + pending_req->status = BLKIF_RSP_ERROR; + } + + /* + * If all of the bio's have completed it is time to unmap + * the grant references associated with 'request' and provide + * the proper response on the ring. + */ + if (atomic_dec_and_test(&pending_req->pendcnt)) { + xen_blkbk_unmap(pending_req); + make_response(pending_req->blkif, pending_req->id, + pending_req->operation, pending_req->status); + xen_blkif_put(pending_req->blkif); + free_req(pending_req); + } +} + +/* + * bio callback. + */ +static void end_block_io_op(struct bio *bio, int error) +{ + __end_block_io_op(bio->bi_private, error); + bio_put(bio); +} + + + +/* + * Function to copy the from the ring buffer the 'struct blkif_request' + * (which has the sectors we want, number of them, grant references, etc), + * and transmute it to the block API to hand it over to the proper block disk. + */ +static int do_block_io_op(struct xen_blkif *blkif) +{ + union blkif_back_rings *blk_rings = &blkif->blk_rings; + struct blkif_request req; + struct pending_req *pending_req; + RING_IDX rc, rp; + int more_to_do = 0; + + rc = blk_rings->common.req_cons; + rp = blk_rings->common.sring->req_prod; + rmb(); /* Ensure we see queued requests up to 'rp'. */ + + while (rc != rp) { + + if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) + break; + + if (kthread_should_stop()) { + more_to_do = 1; + break; + } + + pending_req = alloc_req(); + if (NULL == pending_req) { + blkif->st_oo_req++; + more_to_do = 1; + break; + } + + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req)); + break; + case BLKIF_PROTOCOL_X86_32: + blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc)); + break; + case BLKIF_PROTOCOL_X86_64: + blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc)); + break; + default: + BUG(); + } + blk_rings->common.req_cons = ++rc; /* before make_response() */ + + /* Apply all sanity checks to /private copy/ of request. */ + barrier(); + + if (dispatch_rw_block_io(blkif, &req, pending_req)) + break; + + /* Yield point for this unbounded loop. */ + cond_resched(); + } + + return more_to_do; +} + +/* + * Transmutation of the 'struct blkif_request' to a proper 'struct bio' + * and call the 'submit_bio' to pass it to the underlying storage. + */ +static int dispatch_rw_block_io(struct xen_blkif *blkif, + struct blkif_request *req, + struct pending_req *pending_req) +{ + struct phys_req preq; + struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int nseg; + struct bio *bio = NULL; + struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, nbio = 0; + int operation; + struct blk_plug plug; + + switch (req->operation) { + case BLKIF_OP_READ: + blkif->st_rd_req++; + operation = READ; + break; + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + operation = WRITE_ODIRECT; + break; + case BLKIF_OP_FLUSH_DISKCACHE: + blkif->st_f_req++; + operation = WRITE_FLUSH; + break; + case BLKIF_OP_WRITE_BARRIER: + default: + operation = 0; /* make gcc happy */ + goto fail_response; + break; + } + + /* Check that the number of segments is sane. */ + nseg = req->nr_segments; + if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || + unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { + pr_debug(DRV_PFX "Bad number of segments in request (%d)\n", + nseg); + /* Haven't submitted any bio's yet. */ + goto fail_response; + } + + preq.dev = req->handle; + preq.sector_number = req->u.rw.sector_number; + preq.nr_sects = 0; + + pending_req->blkif = blkif; + pending_req->id = req->id; + pending_req->operation = req->operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + + for (i = 0; i < nseg; i++) { + seg[i].nsec = req->u.rw.seg[i].last_sect - + req->u.rw.seg[i].first_sect + 1; + if ((req->u.rw.seg[i].last_sect >= (PAGE_SIZE >> 9)) || + (req->u.rw.seg[i].last_sect < req->u.rw.seg[i].first_sect)) + goto fail_response; + preq.nr_sects += seg[i].nsec; + + } + + if (xen_vbd_translate(&preq, blkif, operation) != 0) { + pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n", + operation == READ ? "read" : "write", + preq.sector_number, + preq.sector_number + preq.nr_sects, preq.dev); + goto fail_response; + } + + /* + * This check _MUST_ be done after xen_vbd_translate as the preq.bdev + * is set there. + */ + for (i = 0; i < nseg; i++) { + if (((int)preq.sector_number|(int)seg[i].nsec) & + ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) { + pr_debug(DRV_PFX "Misaligned I/O request from domain %d", + blkif->domid); + goto fail_response; + } + } + + /* + * If we have failed at this point, we need to undo the M2P override, + * set gnttab_set_unmap_op on all of the grant references and perform + * the hypercall to unmap the grants - that is all done in + * xen_blkbk_unmap. + */ + if (xen_blkbk_map(req, pending_req, seg)) + goto fail_flush; + + /* This corresponding xen_blkif_put is done in __end_block_io_op */ + xen_blkif_get(blkif); + + for (i = 0; i < nseg; i++) { + while ((bio == NULL) || + (bio_add_page(bio, + blkbk->pending_page(pending_req, i), + seg[i].nsec << 9, + seg[i].buf & ~PAGE_MASK) == 0)) { + + bio = bio_alloc(GFP_KERNEL, nseg-i); + if (unlikely(bio == NULL)) + goto fail_put_bio; + + biolist[nbio++] = bio; + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; + bio->bi_sector = preq.sector_number; + } + + preq.sector_number += seg[i].nsec; + } + + /* This will be hit if the operation was a flush. */ + if (!bio) { + BUG_ON(operation != WRITE_FLUSH); + + bio = bio_alloc(GFP_KERNEL, 0); + if (unlikely(bio == NULL)) + goto fail_put_bio; + + biolist[nbio++] = bio; + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; + } + + /* + * We set it one so that the last submit_bio does not have to call + * atomic_inc. + */ + atomic_set(&pending_req->pendcnt, nbio); + + /* Get a reference count for the disk queue and start sending I/O */ + blk_start_plug(&plug); + + for (i = 0; i < nbio; i++) + submit_bio(operation, biolist[i]); + + /* Let the I/Os go.. */ + blk_finish_plug(&plug); + + if (operation == READ) + blkif->st_rd_sect += preq.nr_sects; + else if (operation == WRITE || operation == WRITE_FLUSH) + blkif->st_wr_sect += preq.nr_sects; + + return 0; + + fail_flush: + xen_blkbk_unmap(pending_req); + fail_response: + /* Haven't submitted any bio's yet. */ + make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + free_req(pending_req); + msleep(1); /* back off a bit */ + return -EIO; + + fail_put_bio: + for (i = 0; i < nbio; i++) + bio_put(biolist[i]); + __end_block_io_op(pending_req, -EINVAL); + msleep(1); /* back off a bit */ + return -EIO; +} + + + +/* + * Put a response on the ring on how the operation fared. + */ +static void make_response(struct xen_blkif *blkif, u64 id, + unsigned short op, int st) +{ + struct blkif_response resp; + unsigned long flags; + union blkif_back_rings *blk_rings = &blkif->blk_rings; + int more_to_do = 0; + int notify; + + resp.id = id; + resp.operation = op; + resp.status = st; + + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_32: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_64: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + default: + BUG(); + } + blk_rings->common.rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); + if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do); + + } else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) { + more_to_do = 1; + } + + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); + + if (more_to_do) + blkif_notify_work(blkif); + if (notify) + notify_remote_via_irq(blkif->irq); +} + +static int __init xen_blkif_init(void) +{ + int i, mmap_pages; + int rc = 0; + + if (!xen_pv_domain()) + return -ENODEV; + + blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); + if (!blkbk) { + pr_alert(DRV_PFX "%s: out of memory!\n", __func__); + return -ENOMEM; + } + + mmap_pages = xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; + + blkbk->pending_reqs = kmalloc(sizeof(blkbk->pending_reqs[0]) * + xen_blkif_reqs, GFP_KERNEL); + blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) * + mmap_pages, GFP_KERNEL); + blkbk->pending_pages = kzalloc(sizeof(blkbk->pending_pages[0]) * + mmap_pages, GFP_KERNEL); + + if (!blkbk->pending_reqs || !blkbk->pending_grant_handles || + !blkbk->pending_pages) { + rc = -ENOMEM; + goto out_of_memory; + } + + for (i = 0; i < mmap_pages; i++) { + blkbk->pending_grant_handles[i] = BLKBACK_INVALID_HANDLE; + blkbk->pending_pages[i] = alloc_page(GFP_KERNEL); + if (blkbk->pending_pages[i] == NULL) { + rc = -ENOMEM; + goto out_of_memory; + } + } + rc = xen_blkif_interface_init(); + if (rc) + goto failed_init; + + memset(blkbk->pending_reqs, 0, sizeof(blkbk->pending_reqs)); + + INIT_LIST_HEAD(&blkbk->pending_free); + spin_lock_init(&blkbk->pending_free_lock); + init_waitqueue_head(&blkbk->pending_free_wq); + + for (i = 0; i < xen_blkif_reqs; i++) + list_add_tail(&blkbk->pending_reqs[i].free_list, + &blkbk->pending_free); + + rc = xen_blkif_xenbus_init(); + if (rc) + goto failed_init; + + return 0; + + out_of_memory: + pr_alert(DRV_PFX "%s: out of memory\n", __func__); + failed_init: + kfree(blkbk->pending_reqs); + kfree(blkbk->pending_grant_handles); + for (i = 0; i < mmap_pages; i++) { + if (blkbk->pending_pages[i]) + __free_page(blkbk->pending_pages[i]); + } + kfree(blkbk->pending_pages); + kfree(blkbk); + blkbk = NULL; + return rc; +} + +module_init(xen_blkif_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h new file mode 100644 index 00000000000..9e40b283a46 --- /dev/null +++ b/drivers/block/xen-blkback/common.h @@ -0,0 +1,233 @@ +/* + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __XEN_BLKIF__BACKEND__COMMON_H__ +#define __XEN_BLKIF__BACKEND__COMMON_H__ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <linux/wait.h> +#include <linux/io.h> +#include <asm/setup.h> +#include <asm/pgalloc.h> +#include <asm/hypervisor.h> +#include <xen/grant_table.h> +#include <xen/xenbus.h> +#include <xen/interface/io/ring.h> +#include <xen/interface/io/blkif.h> +#include <xen/interface/io/protocols.h> + +#define DRV_PFX "xen-blkback:" +#define DPRINTK(fmt, args...) \ + pr_debug(DRV_PFX "(%s:%d) " fmt ".\n", \ + __func__, __LINE__, ##args) + + +/* Not a real protocol. Used to generate ring structs which contain + * the elements common to all protocols only. This way we get a + * compiler-checkable way to use common struct elements, so we can + * avoid using switch(protocol) in a number of places. */ +struct blkif_common_request { + char dummy; +}; +struct blkif_common_response { + char dummy; +}; + +/* i386 protocol version */ +#pragma pack(push, 4) +struct blkif_x86_32_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_32_response { + uint64_t id; /* copied from request */ + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; +#pragma pack(pop) + +/* x86_64 protocol version */ +struct blkif_x86_64_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t __attribute__((__aligned__(8))) id; + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_64_response { + uint64_t __attribute__((__aligned__(8))) id; + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; + +DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, + struct blkif_common_response); +DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, + struct blkif_x86_32_response); +DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, + struct blkif_x86_64_response); + +union blkif_back_rings { + struct blkif_back_ring native; + struct blkif_common_back_ring common; + struct blkif_x86_32_back_ring x86_32; + struct blkif_x86_64_back_ring x86_64; +}; + +enum blkif_protocol { + BLKIF_PROTOCOL_NATIVE = 1, + BLKIF_PROTOCOL_X86_32 = 2, + BLKIF_PROTOCOL_X86_64 = 3, +}; + +struct xen_vbd { + /* What the domain refers to this vbd as. */ + blkif_vdev_t handle; + /* Non-zero -> read-only */ + unsigned char readonly; + /* VDISK_xxx */ + unsigned char type; + /* phys device that this vbd maps to. */ + u32 pdevice; + struct block_device *bdev; + /* Cached size parameter. */ + sector_t size; + bool flush_support; +}; + +struct backend_info; + +struct xen_blkif { + /* Unique identifier for this interface. */ + domid_t domid; + unsigned int handle; + /* Physical parameters of the comms window. */ + unsigned int irq; + /* Comms information. */ + enum blkif_protocol blk_protocol; + union blkif_back_rings blk_rings; + struct vm_struct *blk_ring_area; + /* The VBD attached to this interface. */ + struct xen_vbd vbd; + /* Back pointer to the backend_info. */ + struct backend_info *be; + /* Private fields. */ + spinlock_t blk_ring_lock; + atomic_t refcnt; + + wait_queue_head_t wq; + /* One thread per one blkif. */ + struct task_struct *xenblkd; + unsigned int waiting_reqs; + + /* statistics */ + unsigned long st_print; + int st_rd_req; + int st_wr_req; + int st_oo_req; + int st_f_req; + int st_rd_sect; + int st_wr_sect; + + wait_queue_head_t waiting_to_free; + + grant_handle_t shmem_handle; + grant_ref_t shmem_ref; +}; + + +#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ + (_v)->bdev->bd_part->nr_sects : \ + get_capacity((_v)->bdev->bd_disk)) + +#define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt)) +#define xen_blkif_put(_b) \ + do { \ + if (atomic_dec_and_test(&(_b)->refcnt)) \ + wake_up(&(_b)->waiting_to_free);\ + } while (0) + +struct phys_req { + unsigned short dev; + unsigned short nr_sects; + struct block_device *bdev; + blkif_sector_t sector_number; +}; +int xen_blkif_interface_init(void); + +int xen_blkif_xenbus_init(void); + +irqreturn_t xen_blkif_be_int(int irq, void *dev_id); +int xen_blkif_schedule(void *arg); + +int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, + struct backend_info *be, int state); + +struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); + +static inline void blkif_get_x86_32_req(struct blkif_request *dst, + struct blkif_x86_32_request *src) +{ + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->u.rw.sector_number = src->sector_number; + barrier(); + if (n > dst->nr_segments) + n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->u.rw.seg[i] = src->seg[i]; +} + +static inline void blkif_get_x86_64_req(struct blkif_request *dst, + struct blkif_x86_64_request *src) +{ + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->u.rw.sector_number = src->sector_number; + barrier(); + if (n > dst->nr_segments) + n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->u.rw.seg[i] = src->seg[i]; +} + +#endif /* __XEN_BLKIF__BACKEND__COMMON_H__ */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c new file mode 100644 index 00000000000..34570823355 --- /dev/null +++ b/drivers/block/xen-blkback/xenbus.c @@ -0,0 +1,768 @@ +/* Xenbus code for blkif backend + Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au> + Copyright (C) 2005 XenSource Ltd + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 <stdarg.h> +#include <linux/module.h> +#include <linux/kthread.h> +#include <xen/events.h> +#include <xen/grant_table.h> +#include "common.h" + +struct backend_info { + struct xenbus_device *dev; + struct xen_blkif *blkif; + struct xenbus_watch backend_watch; + unsigned major; + unsigned minor; + char *mode; +}; + +static struct kmem_cache *xen_blkif_cachep; +static void connect(struct backend_info *); +static int connect_ring(struct backend_info *); +static void backend_changed(struct xenbus_watch *, const char **, + unsigned int); + +struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be) +{ + return be->dev; +} + +static int blkback_name(struct xen_blkif *blkif, char *buf) +{ + char *devpath, *devname; + struct xenbus_device *dev = blkif->be->dev; + + devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL); + if (IS_ERR(devpath)) + return PTR_ERR(devpath); + + devname = strstr(devpath, "/dev/"); + if (devname != NULL) + devname += strlen("/dev/"); + else + devname = devpath; + + snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname); + kfree(devpath); + + return 0; +} + +static void xen_update_blkif_status(struct xen_blkif *blkif) +{ + int err; + char name[TASK_COMM_LEN]; + + /* Not ready to connect? */ + if (!blkif->irq || !blkif->vbd.bdev) + return; + + /* Already connected? */ + if (blkif->be->dev->state == XenbusStateConnected) + return; + + /* Attempt to connect: exit if we fail to. */ + connect(blkif->be); + if (blkif->be->dev->state != XenbusStateConnected) + return; + + err = blkback_name(blkif, name); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "get blkback dev name"); + return; + } + + err = filemap_write_and_wait(blkif->vbd.bdev->bd_inode->i_mapping); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "block flush"); + return; + } + invalidate_inode_pages2(blkif->vbd.bdev->bd_inode->i_mapping); + + blkif->xenblkd = kthread_run(xen_blkif_schedule, blkif, name); + if (IS_ERR(blkif->xenblkd)) { + err = PTR_ERR(blkif->xenblkd); + blkif->xenblkd = NULL; + xenbus_dev_error(blkif->be->dev, err, "start xenblkd"); + } +} + +static struct xen_blkif *xen_blkif_alloc(domid_t domid) +{ + struct xen_blkif *blkif; + + blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); + if (!blkif) + return ERR_PTR(-ENOMEM); + + memset(blkif, 0, sizeof(*blkif)); + blkif->domid = domid; + spin_lock_init(&blkif->blk_ring_lock); + atomic_set(&blkif->refcnt, 1); + init_waitqueue_head(&blkif->wq); + blkif->st_print = jiffies; + init_waitqueue_head(&blkif->waiting_to_free); + + return blkif; +} + +static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page) +{ + struct gnttab_map_grant_ref op; + + gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, shared_page, blkif->domid); + + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + + if (op.status) { + DPRINTK("Grant table operation failure !\n"); + return op.status; + } + + blkif->shmem_ref = shared_page; + blkif->shmem_handle = op.handle; + + return 0; +} + +static void unmap_frontend_page(struct xen_blkif *blkif) +{ + struct gnttab_unmap_grant_ref op; + + gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, blkif->shmem_handle); + + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); +} + +static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, + unsigned int evtchn) +{ + int err; + + /* Already connected through? */ + if (blkif->irq) + return 0; + + blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); + if (!blkif->blk_ring_area) + return -ENOMEM; + + err = map_frontend_page(blkif, shared_page); + if (err) { + free_vm_area(blkif->blk_ring_area); + return err; + } + + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + struct blkif_sring *sring; + sring = (struct blkif_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + struct blkif_x86_32_sring *sring_x86_32; + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + struct blkif_x86_64_sring *sring_x86_64; + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); + break; + } + default: + BUG(); + } + + err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn, + xen_blkif_be_int, 0, + "blkif-backend", blkif); + if (err < 0) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + return err; + } + blkif->irq = err; + + return 0; +} + +static void xen_blkif_disconnect(struct xen_blkif *blkif) +{ + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + + atomic_dec(&blkif->refcnt); + wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); + + if (blkif->irq) { + unbind_from_irqhandler(blkif->irq, blkif); + blkif->irq = 0; + } + + if (blkif->blk_rings.common.sring) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + } +} + +void xen_blkif_free(struct xen_blkif *blkif) +{ + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); + kmem_cache_free(xen_blkif_cachep, blkif); +} + +int __init xen_blkif_interface_init(void) +{ + xen_blkif_cachep = kmem_cache_create("blkif_cache", + sizeof(struct xen_blkif), + 0, 0, NULL); + if (!xen_blkif_cachep) + return -ENOMEM; + + return 0; +} + +/* + * sysfs interface for VBD I/O requests + */ + +#define VBD_SHOW(name, format, args...) \ + static ssize_t show_##name(struct device *_dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + struct xenbus_device *dev = to_xenbus_device(_dev); \ + struct backend_info *be = dev_get_drvdata(&dev->dev); \ + \ + return sprintf(buf, format, ##args); \ + } \ + static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); +VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); +VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); +VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req); +VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); +VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); + +static struct attribute *xen_vbdstat_attrs[] = { + &dev_attr_oo_req.attr, + &dev_attr_rd_req.attr, + &dev_attr_wr_req.attr, + &dev_attr_f_req.attr, + &dev_attr_rd_sect.attr, + &dev_attr_wr_sect.attr, + NULL +}; + +static struct attribute_group xen_vbdstat_group = { + .name = "statistics", + .attrs = xen_vbdstat_attrs, +}; + +VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); +VBD_SHOW(mode, "%s\n", be->mode); + +int xenvbd_sysfs_addif(struct xenbus_device *dev) +{ + int error; + + error = device_create_file(&dev->dev, &dev_attr_physical_device); + if (error) + goto fail1; + + error = device_create_file(&dev->dev, &dev_attr_mode); + if (error) + goto fail2; + + error = sysfs_create_group(&dev->dev.kobj, &xen_vbdstat_group); + if (error) + goto fail3; + + return 0; + +fail3: sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); +fail2: device_remove_file(&dev->dev, &dev_attr_mode); +fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); + return error; +} + +void xenvbd_sysfs_delif(struct xenbus_device *dev) +{ + sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); + device_remove_file(&dev->dev, &dev_attr_mode); + device_remove_file(&dev->dev, &dev_attr_physical_device); +} + + +static void xen_vbd_free(struct xen_vbd *vbd) +{ + if (vbd->bdev) + blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); + vbd->bdev = NULL; +} + +static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, + unsigned major, unsigned minor, int readonly, + int cdrom) +{ + struct xen_vbd *vbd; + struct block_device *bdev; + struct request_queue *q; + + vbd = &blkif->vbd; + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + + vbd->pdevice = MKDEV(major, minor); + + bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? + FMODE_READ : FMODE_WRITE, NULL); + + if (IS_ERR(bdev)) { + DPRINTK("xen_vbd_create: device %08x could not be opened.\n", + vbd->pdevice); + return -ENOENT; + } + + vbd->bdev = bdev; + vbd->size = vbd_sz(vbd); + + if (vbd->bdev->bd_disk == NULL) { + DPRINTK("xen_vbd_create: device %08x doesn't exist.\n", + vbd->pdevice); + xen_vbd_free(vbd); + return -ENOENT; + } + + if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) + vbd->type |= VDISK_CDROM; + if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) + vbd->type |= VDISK_REMOVABLE; + + q = bdev_get_queue(bdev); + if (q && q->flush_flags) + vbd->flush_support = true; + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; +} +static int xen_blkbk_remove(struct xenbus_device *dev) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + + DPRINTK(""); + + if (be->major || be->minor) + xenvbd_sysfs_delif(dev); + + if (be->backend_watch.node) { + unregister_xenbus_watch(&be->backend_watch); + kfree(be->backend_watch.node); + be->backend_watch.node = NULL; + } + + if (be->blkif) { + xen_blkif_disconnect(be->blkif); + xen_vbd_free(&be->blkif->vbd); + xen_blkif_free(be->blkif); + be->blkif = NULL; + } + + kfree(be); + dev_set_drvdata(&dev->dev, NULL); + return 0; +} + +int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, + struct backend_info *be, int state) +{ + struct xenbus_device *dev = be->dev; + int err; + + err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", + "%d", state); + if (err) + xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); + + return err; +} + +/* + * Entry point to this code when a new device is created. Allocate the basic + * structures, and watch the store waiting for the hotplug scripts to tell us + * the device's physical major and minor numbers. Switch to InitWait. + */ +static int xen_blkbk_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err; + struct backend_info *be = kzalloc(sizeof(struct backend_info), + GFP_KERNEL); + if (!be) { + xenbus_dev_fatal(dev, -ENOMEM, + "allocating backend structure"); + return -ENOMEM; + } + be->dev = dev; + dev_set_drvdata(&dev->dev, be); + + be->blkif = xen_blkif_alloc(dev->otherend_id); + if (IS_ERR(be->blkif)) { + err = PTR_ERR(be->blkif); + be->blkif = NULL; + xenbus_dev_fatal(dev, err, "creating block interface"); + goto fail; + } + + /* setup back pointer */ + be->blkif->be = be; + + err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed, + "%s/%s", dev->nodename, "physical-device"); + if (err) + goto fail; + + err = xenbus_switch_state(dev, XenbusStateInitWait); + if (err) + goto fail; + + return 0; + +fail: + DPRINTK("failed"); + xen_blkbk_remove(dev); + return err; +} + + +/* + * Callback received when the hotplug scripts have placed the physical-device + * node. Read it and the mode node, and create a vbd. If the frontend is + * ready, connect. + */ +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + int err; + unsigned major; + unsigned minor; + struct backend_info *be + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + int cdrom = 0; + char *device_type; + + DPRINTK(""); + + err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x", + &major, &minor); + if (XENBUS_EXIST_ERR(err)) { + /* + * Since this watch will fire once immediately after it is + * registered, we expect this. Ignore it, and wait for the + * hotplug scripts. + */ + return; + } + if (err != 2) { + xenbus_dev_fatal(dev, err, "reading physical-device"); + return; + } + + if ((be->major || be->minor) && + ((be->major != major) || (be->minor != minor))) { + pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", + be->major, be->minor, major, minor); + return; + } + + be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL); + if (IS_ERR(be->mode)) { + err = PTR_ERR(be->mode); + be->mode = NULL; + xenbus_dev_fatal(dev, err, "reading mode"); + return; + } + + device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL); + if (!IS_ERR(device_type)) { + cdrom = strcmp(device_type, "cdrom") == 0; + kfree(device_type); + } + + if (be->major == 0 && be->minor == 0) { + /* Front end dir is a number, which is used as the handle. */ + + char *p = strrchr(dev->otherend, '/') + 1; + long handle; + err = strict_strtoul(p, 0, &handle); + if (err) + return; + + be->major = major; + be->minor = minor; + + err = xen_vbd_create(be->blkif, handle, major, minor, + (NULL == strchr(be->mode, 'w')), cdrom); + if (err) { + be->major = 0; + be->minor = 0; + xenbus_dev_fatal(dev, err, "creating vbd structure"); + return; + } + + err = xenvbd_sysfs_addif(dev); + if (err) { + xen_vbd_free(&be->blkif->vbd); + be->major = 0; + be->minor = 0; + xenbus_dev_fatal(dev, err, "creating sysfs entries"); + return; + } + + /* We're potentially connected now */ + xen_update_blkif_status(be->blkif); + } +} + + +/* + * Callback received when the frontend's state changes. + */ +static void frontend_changed(struct xenbus_device *dev, + enum xenbus_state frontend_state) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + int err; + + DPRINTK("%s", xenbus_strstate(frontend_state)); + + switch (frontend_state) { + case XenbusStateInitialising: + if (dev->state == XenbusStateClosed) { + pr_info(DRV_PFX "%s: prepare for reconnect\n", + dev->nodename); + xenbus_switch_state(dev, XenbusStateInitWait); + } + break; + + case XenbusStateInitialised: + case XenbusStateConnected: + /* + * Ensure we connect even when two watches fire in + * close successsion and we miss the intermediate value + * of frontend_state. + */ + if (dev->state == XenbusStateConnected) + break; + + /* + * Enforce precondition before potential leak point. + * blkif_disconnect() is idempotent. + */ + xen_blkif_disconnect(be->blkif); + + err = connect_ring(be); + if (err) + break; + xen_update_blkif_status(be->blkif); + break; + + case XenbusStateClosing: + xen_blkif_disconnect(be->blkif); + xenbus_switch_state(dev, XenbusStateClosing); + break; + + case XenbusStateClosed: + xenbus_switch_state(dev, XenbusStateClosed); + if (xenbus_dev_is_online(dev)) + break; + /* fall through if not online */ + case XenbusStateUnknown: + /* implies blkif_disconnect() via blkback_remove() */ + device_unregister(&dev->dev); + break; + + default: + xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", + frontend_state); + break; + } +} + + +/* ** Connection ** */ + + +/* + * Write the physical details regarding the block device to the store, and + * switch to Connected state. + */ +static void connect(struct backend_info *be) +{ + struct xenbus_transaction xbt; + int err; + struct xenbus_device *dev = be->dev; + + DPRINTK("%s", dev->otherend); + + /* Supply the information about the device the frontend needs */ +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + return; + } + + err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); + if (err) + goto abort; + + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", + (unsigned long long)vbd_sz(&be->blkif->vbd)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/sectors", + dev->nodename); + goto abort; + } + + /* FIXME: use a typename instead */ + err = xenbus_printf(xbt, dev->nodename, "info", "%u", + be->blkif->vbd.type | + (be->blkif->vbd.readonly ? VDISK_READONLY : 0)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/info", + dev->nodename); + goto abort; + } + err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", + (unsigned long) + bdev_logical_block_size(be->blkif->vbd.bdev)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/sector-size", + dev->nodename); + goto abort; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + xenbus_dev_fatal(dev, err, "ending transaction"); + + err = xenbus_switch_state(dev, XenbusStateConnected); + if (err) + xenbus_dev_fatal(dev, err, "switching to Connected state", + dev->nodename); + + return; + abort: + xenbus_transaction_end(xbt, 1); +} + + +static int connect_ring(struct backend_info *be) +{ + struct xenbus_device *dev = be->dev; + unsigned long ring_ref; + unsigned int evtchn; + char protocol[64] = ""; + int err; + + DPRINTK("%s", dev->otherend); + + err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", + &ring_ref, "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_fatal(dev, err, + "reading %s/ring-ref and event-channel", + dev->otherend); + return err; + } + + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", + "%63s", protocol, NULL); + if (err) + strcpy(protocol, "unspecified, assuming native"); + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; + } + pr_info(DRV_PFX "ring-ref %ld, event-channel %d, protocol %d (%s)\n", + ring_ref, evtchn, be->blkif->blk_protocol, protocol); + + /* Map the shared frame, irq etc. */ + err = xen_blkif_map(be->blkif, ring_ref, evtchn); + if (err) { + xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", + ring_ref, evtchn); + return err; + } + + return 0; +} + + +/* ** Driver Registration ** */ + + +static const struct xenbus_device_id xen_blkbk_ids[] = { + { "vbd" }, + { "" } +}; + + +static struct xenbus_driver xen_blkbk = { + .name = "vbd", + .owner = THIS_MODULE, + .ids = xen_blkbk_ids, + .probe = xen_blkbk_probe, + .remove = xen_blkbk_remove, + .otherend_changed = frontend_changed +}; + + +int xen_blkif_xenbus_init(void) +{ + return xenbus_register_backend(&xen_blkbk); +} diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 9cb8668ff5f..b536a9cef91 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -97,6 +97,7 @@ struct blkfront_info struct blk_shadow shadow[BLK_RING_SIZE]; unsigned long shadow_free; unsigned int feature_flush; + unsigned int flush_op; int is_ready; }; @@ -250,8 +251,7 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode, /* * Generate a Xen blkfront IO request from a blk layer request. Reads - * and writes are handled as expected. Since we lack a loose flush - * request, we map flushes into a full ordered barrier. + * and writes are handled as expected. * * @req: a request struct */ @@ -293,14 +293,13 @@ static int blkif_queue_request(struct request *req) if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) { /* - * Ideally we could just do an unordered - * flush-to-disk, but all we have is a full write - * barrier at the moment. However, a barrier write is + * Ideally we can do an unordered flush-to-disk. In case the + * backend onlysupports barriers, use that. A barrier request * a superset of FUA, so we can implement it the same * way. (It's also a FLUSH+FUA, since it is * guaranteed ordered WRT previous writes.) */ - ring_req->operation = BLKIF_OP_WRITE_BARRIER; + ring_req->operation = info->flush_op; } ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); @@ -433,8 +432,11 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) static void xlvbd_flush(struct blkfront_info *info) { blk_queue_flush(info->rq, info->feature_flush); - printk(KERN_INFO "blkfront: %s: barriers %s\n", + printk(KERN_INFO "blkfront: %s: %s: %s\n", info->gd->disk_name, + info->flush_op == BLKIF_OP_WRITE_BARRIER ? + "barrier" : (info->flush_op == BLKIF_OP_FLUSH_DISKCACHE ? + "flush diskcache" : "barrier or flush"), info->feature_flush ? "enabled" : "disabled"); } @@ -720,15 +722,20 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; switch (bret->operation) { + case BLKIF_OP_FLUSH_DISKCACHE: case BLKIF_OP_WRITE_BARRIER: if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { - printk(KERN_WARNING "blkfront: %s: write barrier op failed\n", + printk(KERN_WARNING "blkfront: %s: write %s op failed\n", + info->flush_op == BLKIF_OP_WRITE_BARRIER ? + "barrier" : "flush disk cache", info->gd->disk_name); error = -EOPNOTSUPP; } if (unlikely(bret->status == BLKIF_RSP_ERROR && info->shadow[id].req.nr_segments == 0)) { - printk(KERN_WARNING "blkfront: %s: empty write barrier op failed\n", + printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n", + info->flush_op == BLKIF_OP_WRITE_BARRIER ? + "barrier" : "flush disk cache", info->gd->disk_name); error = -EOPNOTSUPP; } @@ -736,6 +743,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) if (error == -EOPNOTSUPP) error = 0; info->feature_flush = 0; + info->flush_op = 0; xlvbd_flush(info); } /* fall through */ @@ -1100,7 +1108,7 @@ static void blkfront_connect(struct blkfront_info *info) unsigned long sector_size; unsigned int binfo; int err; - int barrier; + int barrier, flush; switch (info->connected) { case BLKIF_STATE_CONNECTED: @@ -1140,8 +1148,11 @@ static void blkfront_connect(struct blkfront_info *info) return; } + info->feature_flush = 0; + info->flush_op = 0; + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, - "feature-barrier", "%lu", &barrier, + "feature-barrier", "%d", &barrier, NULL); /* @@ -1151,11 +1162,23 @@ static void blkfront_connect(struct blkfront_info *info) * * If there are barriers, then we use flush. */ - info->feature_flush = 0; - - if (!err && barrier) + if (!err && barrier) { info->feature_flush = REQ_FLUSH | REQ_FUA; + info->flush_op = BLKIF_OP_WRITE_BARRIER; + } + /* + * And if there is "feature-flush-cache" use that above + * barriers. + */ + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, + "feature-flush-cache", "%d", &flush, + NULL); + if (!err && flush) { + info->feature_flush = REQ_FLUSH; + info->flush_op = BLKIF_OP_FLUSH_DISKCACHE; + } + err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); if (err) { xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e427fbe4599..ae15a4ddaa9 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -625,7 +625,9 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) blk_queue_max_hw_sectors(q, 4096 / 512); gendisk->queue = q; gendisk->fops = &viocd_fops; - gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE; + gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE | + GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; + gendisk->events = DISK_EVENT_MEDIA_CHANGE; set_capacity(gendisk, 0); gendisk->private_data = d; d->viocd_disk = gendisk; diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index d72433f2d31..6e40072fbf6 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -5,6 +5,9 @@ * * Copyright (C) 2001 Massimo Dal Zotto <dz@debian.org> * + * Hwmon integration: + * Copyright (C) 2011 Jean Delvare <khali@linux-fr.org> + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any @@ -24,6 +27,8 @@ #include <linux/dmi.h> #include <linux/capability.h> #include <linux/mutex.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -58,6 +63,7 @@ static DEFINE_MUTEX(i8k_mutex); static char bios_version[4]; +static struct device *i8k_hwmon_dev; MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); @@ -139,8 +145,8 @@ static int i8k_smm(struct smm_regs *regs) "movl %%edi,20(%%rax)\n\t" "popq %%rdx\n\t" "movl %%edx,0(%%rax)\n\t" - "lahf\n\t" - "shrl $8,%%eax\n\t" + "pushfq\n\t" + "popq %%rax\n\t" "andl $1,%%eax\n" :"=a"(rc) : "a"(regs) @@ -455,6 +461,152 @@ static int i8k_open_fs(struct inode *inode, struct file *file) return single_open(file, i8k_proc_show, NULL); } + +/* + * Hwmon interface + */ + +static ssize_t i8k_hwmon_show_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int cpu_temp; + + cpu_temp = i8k_get_temp(0); + if (cpu_temp < 0) + return cpu_temp; + return sprintf(buf, "%d\n", cpu_temp * 1000); +} + +static ssize_t i8k_hwmon_show_fan(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + int fan_speed; + + fan_speed = i8k_get_fan_speed(index); + if (fan_speed < 0) + return fan_speed; + return sprintf(buf, "%d\n", fan_speed); +} + +static ssize_t i8k_hwmon_show_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + static const char *labels[4] = { + "i8k", + "CPU", + "Left Fan", + "Right Fan", + }; + int index = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%s\n", labels[index]); +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, + I8K_FAN_LEFT); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL, + I8K_FAN_RIGHT); +static SENSOR_DEVICE_ATTR(name, S_IRUGO, i8k_hwmon_show_label, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2); +static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 3); + +static void i8k_hwmon_remove_files(struct device *dev) +{ + device_remove_file(dev, &dev_attr_temp1_input); + device_remove_file(dev, &sensor_dev_attr_fan1_input.dev_attr); + device_remove_file(dev, &sensor_dev_attr_fan2_input.dev_attr); + device_remove_file(dev, &sensor_dev_attr_temp1_label.dev_attr); + device_remove_file(dev, &sensor_dev_attr_fan1_label.dev_attr); + device_remove_file(dev, &sensor_dev_attr_fan2_label.dev_attr); + device_remove_file(dev, &sensor_dev_attr_name.dev_attr); +} + +static int __init i8k_init_hwmon(void) +{ + int err; + + i8k_hwmon_dev = hwmon_device_register(NULL); + if (IS_ERR(i8k_hwmon_dev)) { + err = PTR_ERR(i8k_hwmon_dev); + i8k_hwmon_dev = NULL; + printk(KERN_ERR "i8k: hwmon registration failed (%d)\n", err); + return err; + } + + /* Required name attribute */ + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_name.dev_attr); + if (err) + goto exit_unregister; + + /* CPU temperature attributes, if temperature reading is OK */ + err = i8k_get_temp(0); + if (err < 0) { + dev_dbg(i8k_hwmon_dev, + "Not creating temperature attributes (%d)\n", err); + } else { + err = device_create_file(i8k_hwmon_dev, &dev_attr_temp1_input); + if (err) + goto exit_remove_files; + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_temp1_label.dev_attr); + if (err) + goto exit_remove_files; + } + + /* Left fan attributes, if left fan is present */ + err = i8k_get_fan_status(I8K_FAN_LEFT); + if (err < 0) { + dev_dbg(i8k_hwmon_dev, + "Not creating %s fan attributes (%d)\n", "left", err); + } else { + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_fan1_input.dev_attr); + if (err) + goto exit_remove_files; + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_fan1_label.dev_attr); + if (err) + goto exit_remove_files; + } + + /* Right fan attributes, if right fan is present */ + err = i8k_get_fan_status(I8K_FAN_RIGHT); + if (err < 0) { + dev_dbg(i8k_hwmon_dev, + "Not creating %s fan attributes (%d)\n", "right", err); + } else { + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_fan2_input.dev_attr); + if (err) + goto exit_remove_files; + err = device_create_file(i8k_hwmon_dev, + &sensor_dev_attr_fan2_label.dev_attr); + if (err) + goto exit_remove_files; + } + + return 0; + + exit_remove_files: + i8k_hwmon_remove_files(i8k_hwmon_dev); + exit_unregister: + hwmon_device_unregister(i8k_hwmon_dev); + return err; +} + +static void __exit i8k_exit_hwmon(void) +{ + i8k_hwmon_remove_files(i8k_hwmon_dev); + hwmon_device_unregister(i8k_hwmon_dev); +} + static struct dmi_system_id __initdata i8k_dmi_table[] = { { .ident = "Dell Inspiron", @@ -580,6 +732,7 @@ static int __init i8k_probe(void) static int __init i8k_init(void) { struct proc_dir_entry *proc_i8k; + int err; /* Are we running on an supported laptop? */ if (i8k_probe()) @@ -590,15 +743,24 @@ static int __init i8k_init(void) if (!proc_i8k) return -ENOENT; + err = i8k_init_hwmon(); + if (err) + goto exit_remove_proc; + printk(KERN_INFO "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n", I8K_VERSION); return 0; + + exit_remove_proc: + remove_proc_entry("i8k", NULL); + return err; } static void __exit i8k_exit(void) { + i8k_exit_hwmon(); remove_proc_entry("i8k", NULL); } diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index c7f1a6f16b6..e2fc2d21fa6 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -39,3 +39,5 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o ##################################################################################d +# ARM SoC drivers +obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c new file mode 100644 index 00000000000..d90456a809f --- /dev/null +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Sundar Iyer <sundar.iyer@stericsson.com> + * Author: Martin Persson <martin.persson@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + */ +#include <linux/kernel.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/mfd/db8500-prcmu.h> +#include <mach/id.h> + +static struct cpufreq_frequency_table freq_table[] = { + [0] = { + .index = 0, + .frequency = 300000, + }, + [1] = { + .index = 1, + .frequency = 600000, + }, + [2] = { + /* Used for MAX_OPP, if available */ + .index = 2, + .frequency = CPUFREQ_TABLE_END, + }, + [3] = { + .index = 3, + .frequency = CPUFREQ_TABLE_END, + }, +}; + +static enum arm_opp idx2opp[] = { + ARM_50_OPP, + ARM_100_OPP, + ARM_MAX_OPP +}; + +static struct freq_attr *db8500_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static int db8500_cpufreq_verify_speed(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, freq_table); +} + +static int db8500_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + unsigned int idx; + + /* scale the target frequency to one of the extremes supported */ + if (target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + if (target_freq > policy->cpuinfo.max_freq) + target_freq = policy->cpuinfo.max_freq; + + /* Lookup the next frequency */ + if (cpufreq_frequency_table_target + (policy, freq_table, target_freq, relation, &idx)) { + return -EINVAL; + } + + freqs.old = policy->cur; + freqs.new = freq_table[idx].frequency; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) + return 0; + + /* pre-change notification */ + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* request the PRCM unit for opp change */ + if (prcmu_set_arm_opp(idx2opp[idx])) { + pr_err("db8500-cpufreq: Failed to set OPP level\n"); + return -EINVAL; + } + + /* post change notification */ + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; +} + +static unsigned int db8500_cpufreq_getspeed(unsigned int cpu) +{ + int i; + /* request the prcm to get the current ARM opp */ + for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++) + ; + return freq_table[i].frequency; +} + +static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) +{ + int res; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); + + if (cpu_is_u8500v2() && !prcmu_is_u8400()) { + freq_table[0].frequency = 400000; + freq_table[1].frequency = 800000; + if (prcmu_has_arm_maxopp()) + freq_table[2].frequency = 1000000; + } + + /* get policy fields based on the table */ + res = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!res) + cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + else { + pr_err("db8500-cpufreq : Failed to read policy table\n"); + return res; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = db8500_cpufreq_getspeed(policy->cpu); + + for (i = 0; freq_table[i].frequency != policy->cur; i++) + ; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + /* + * FIXME : Need to take time measurement across the target() + * function with no/some/all drivers in the notification + * list. + */ + policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ + + /* policy sharing between dual CPUs */ + cpumask_copy(policy->cpus, &cpu_present_map); + + policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; + + return 0; +} + +static struct cpufreq_driver db8500_cpufreq_driver = { + .flags = CPUFREQ_STICKY, + .verify = db8500_cpufreq_verify_speed, + .target = db8500_cpufreq_target, + .get = db8500_cpufreq_getspeed, + .init = db8500_cpufreq_init, + .name = "DB8500", + .attr = db8500_cpufreq_attr, +}; + +static int __init db8500_cpufreq_register(void) +{ + if (!cpu_is_u8500v20_or_later()) + return -ENODEV; + + pr_info("cpufreq for DB8500 started\n"); + return cpufreq_register_driver(&db8500_cpufreq_driver); +} +device_initcall(db8500_cpufreq_register); diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index dcc1b2139ff..636e40925b1 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -213,12 +213,17 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) struct sh_dmae_device, common); struct sh_dmae_pdata *pdata = shdev->pdata; const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; - u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); + u16 __iomem *addr = shdev->dmars; int shift = chan_pdata->dmars_bit; if (dmae_is_busy(sh_chan)) return -EBUSY; + /* in the case of a missing DMARS resource use first memory window */ + if (!addr) + addr = (u16 __iomem *)shdev->chan_reg; + addr += chan_pdata->dmars / sizeof(u16); + __raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift), addr); @@ -1078,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) unsigned long irqflags = IRQF_DISABLED, chan_flag[SH_DMAC_MAX_CHANNELS] = {}; int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; - int err, i, irq_cnt = 0, irqres = 0; + int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0; struct sh_dmae_device *shdev; struct resource *chan, *dmars, *errirq_res, *chanirq_res; @@ -1087,7 +1092,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) return -ENODEV; chan = platform_get_resource(pdev, IORESOURCE_MEM, 0); - /* DMARS area is optional, if absent, this controller cannot do slave DMA */ + /* DMARS area is optional */ dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1); /* * IRQ resources: @@ -1154,7 +1159,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) INIT_LIST_HEAD(&shdev->common.channels); dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); - if (dmars) + if (pdata->slave && pdata->slave_num) dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); shdev->common.device_alloc_chan_resources @@ -1203,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev) !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { /* Special case - all multiplexed */ for (; irq_cnt < pdata->channel_num; irq_cnt++) { - chan_irq[irq_cnt] = chanirq_res->start; - chan_flag[irq_cnt] = IRQF_SHARED; + if (irq_cnt < SH_DMAC_MAX_CHANNELS) { + chan_irq[irq_cnt] = chanirq_res->start; + chan_flag[irq_cnt] = IRQF_SHARED; + } else { + irq_cap = 1; + break; + } } } else { do { @@ -1218,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev) "Found IRQ %d for channel %d\n", i, irq_cnt); chan_irq[irq_cnt++] = i; + + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) + break; + } + + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { + irq_cap = 1; + break; } chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, ++irqres); } while (irq_cnt < pdata->channel_num && chanirq_res); } - if (irq_cnt < pdata->channel_num) - goto eirqres; - /* Create DMA Channel */ - for (i = 0; i < pdata->channel_num; i++) { + for (i = 0; i < irq_cnt; i++) { err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]); if (err) goto chan_probe_err; } + if (irq_cap) + dev_notice(&pdev->dev, "Attempting to register %d DMA " + "channels when a maximum of %d are supported.\n", + pdata->channel_num, SH_DMAC_MAX_CHANNELS); + pm_runtime_put(&pdev->dev); platform_set_drvdata(pdev, shdev); @@ -1243,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) chan_probe_err: sh_dmae_chan_remove(shdev); -eirqres: + #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) free_irq(errirq, shdev); eirq_err: diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 3f9d3cd0658..5ae9fc51218 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -17,7 +17,7 @@ #include <linux/interrupt.h> #include <linux/list.h> -#define SH_DMAC_MAX_CHANNELS 6 +#define SH_DMAC_MAX_CHANNELS 20 #define SH_DMA_SLAVE_NUMBER 256 #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 43221beb9e9..16db83c83c8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -41,7 +41,7 @@ comment "Native drivers" config SENSORS_ABITUGURU tristate "Abit uGuru (rev 1 & 2)" - depends on X86 && EXPERIMENTAL + depends on X86 && DMI && EXPERIMENTAL help If you say yes here you get support for the sensor part of the first and second revision of the Abit uGuru chip. The voltage and frequency @@ -56,7 +56,7 @@ config SENSORS_ABITUGURU config SENSORS_ABITUGURU3 tristate "Abit uGuru (rev 3)" - depends on X86 && EXPERIMENTAL + depends on X86 && DMI && EXPERIMENTAL help If you say yes here you get support for the sensor part of the third revision of the Abit uGuru chip. Only reading the sensors @@ -213,7 +213,7 @@ config SENSORS_ADT7475 config SENSORS_ASC7621 tristate "Andigilog aSC7621" - depends on HWMON && I2C + depends on I2C help If you say yes here you get support for the aSC7621 family of SMBus sensors chip found on most Intel X38, X48, X58, @@ -237,17 +237,27 @@ config SENSORS_K8TEMP will be called k8temp. config SENSORS_K10TEMP - tristate "AMD Family 10h/11h/12h/14h temperature sensor" + tristate "AMD Family 10h+ temperature sensor" depends on X86 && PCI help If you say yes here you get support for the temperature sensor(s) inside your CPU. Supported are later revisions of the AMD Family 10h and all revisions of the AMD Family 11h, - 12h (Llano), and 14h (Brazos) microarchitectures. + 12h (Llano), 14h (Brazos) and 15h (Bulldozer) microarchitectures. This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_FAM15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called fam15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL @@ -319,7 +329,7 @@ config SENSORS_F71882FG If you say yes here you get support for hardware monitoring features of many Fintek Super-I/O (LPC) chips. The currently supported chips are: - F71808E + F71808E/A F71858FG F71862FG F71863FG @@ -978,6 +988,16 @@ config SENSORS_EMC2103 This driver can also be built as a module. If so, the module will be called emc2103. +config SENSORS_EMC6W201 + tristate "SMSC EMC6W201" + depends on I2C + help + If you say yes here you get support for the SMSC EMC6W201 + hardware monitoring chip. + + This driver can also be built as a module. If so, the module + will be called emc6w201. + config SENSORS_SMSC47M1 tristate "SMSC LPC47M10x and compatibles" help @@ -1341,6 +1361,16 @@ if ACPI comment "ACPI drivers" +config SENSORS_ACPI_POWER + tristate "ACPI 4.0 power meter" + help + This driver exposes ACPI 4.0 power meters as hardware monitoring + devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware + and a power meter. + + To compile this driver as a module, choose M here: + the module will be called acpi_power_meter. + config SENSORS_ATK0110 tristate "ASUS ATK0110" depends on X86 && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 28e8d52f637..28061cfa0cd 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_HWMON) += hwmon.o obj-$(CONFIG_HWMON_VID) += hwmon-vid.o # APCI drivers +obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o obj-$(CONFIG_SENSORS_ATK0110) += asus_atk0110.o # Native drivers @@ -45,9 +46,11 @@ obj-$(CONFIG_SENSORS_DS620) += ds620.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o +obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index e7d4c4687f0..65a35cf5b3c 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -1448,15 +1448,12 @@ static int __init abituguru_init(void) { int address, err; struct resource res = { .flags = IORESOURCE_IO }; - -#ifdef CONFIG_DMI const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); /* safety check, refuse to load on non Abit motherboards */ if (!force && (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))) return -ENODEV; -#endif address = abituguru_detect(); if (address < 0) diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index e89d572e332..d30855a7578 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -1119,8 +1119,6 @@ static struct platform_driver abituguru3_driver = { .resume = abituguru3_resume }; -#ifdef CONFIG_DMI - static int __init abituguru3_dmi_detect(void) { const char *board_vendor, *board_name; @@ -1159,15 +1157,6 @@ static int __init abituguru3_dmi_detect(void) return 1; } -#else /* !CONFIG_DMI */ - -static inline int abituguru3_dmi_detect(void) -{ - return 1; -} - -#endif /* CONFIG_DMI */ - /* FIXME: Manual detection should die eventually; we need to collect stable * DMI model names first before we can rely entirely on CONFIG_DMI. */ @@ -1216,10 +1205,8 @@ static int __init abituguru3_init(void) if (err) return err; -#ifdef CONFIG_DMI pr_warn("this motherboard was not detected using DMI. " "Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n"); -#endif } err = platform_driver_register(&abituguru3_driver); diff --git a/drivers/acpi/power_meter.c b/drivers/hwmon/acpi_power_meter.c index 66f67293341..66f67293341 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index fbdc7655303..b2cacbe707a 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c @@ -62,7 +62,7 @@ static ssize_t adcxx_read(struct device *dev, { struct spi_device *spi = to_spi_device(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); u8 tx_buf[2]; u8 rx_buf[2]; int status; @@ -105,7 +105,7 @@ static ssize_t adcxx_show_max(struct device *dev, struct device_attribute *devattr, char *buf) { struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); u32 reference; if (mutex_lock_interruptible(&adc->lock)) @@ -122,7 +122,7 @@ static ssize_t adcxx_set_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); unsigned long value; if (strict_strtoul(buf, 10, &value)) @@ -142,7 +142,7 @@ static ssize_t adcxx_show_name(struct device *dev, struct device_attribute *devattr, char *buf) { struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); return sprintf(buf, "adcxx%ds\n", adc->channels); } @@ -182,7 +182,7 @@ static int __devinit adcxx_probe(struct spi_device *spi) mutex_lock(&adc->lock); - dev_set_drvdata(&spi->dev, adc); + spi_set_drvdata(spi, adc); for (i = 0; i < 3 + adc->channels; i++) { status = device_create_file(&spi->dev, &ad_input[i].dev_attr); @@ -206,7 +206,7 @@ out_err: for (i--; i >= 0; i--) device_remove_file(&spi->dev, &ad_input[i].dev_attr); - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); mutex_unlock(&adc->lock); kfree(adc); return status; @@ -214,7 +214,7 @@ out_err: static int __devexit adcxx_remove(struct spi_device *spi) { - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); int i; mutex_lock(&adc->lock); @@ -222,7 +222,7 @@ static int __devexit adcxx_remove(struct spi_device *spi) for (i = 0; i < 3 + adc->channels; i++) device_remove_file(&spi->dev, &ad_input[i].dev_attr); - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); mutex_unlock(&adc->lock); kfree(adc); diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c new file mode 100644 index 00000000000..e0ef32378ac --- /dev/null +++ b/drivers/hwmon/emc6w201.c @@ -0,0 +1,539 @@ +/* + * emc6w201.c - Hardware monitoring driver for the SMSC EMC6W201 + * Copyright (C) 2011 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> + +/* + * Addresses to scan + */ + +static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; + +/* + * The EMC6W201 registers + */ + +#define EMC6W201_REG_IN(nr) (0x20 + (nr)) +#define EMC6W201_REG_TEMP(nr) (0x26 + (nr)) +#define EMC6W201_REG_FAN(nr) (0x2C + (nr) * 2) +#define EMC6W201_REG_COMPANY 0x3E +#define EMC6W201_REG_VERSTEP 0x3F +#define EMC6W201_REG_CONFIG 0x40 +#define EMC6W201_REG_IN_LOW(nr) (0x4A + (nr) * 2) +#define EMC6W201_REG_IN_HIGH(nr) (0x4B + (nr) * 2) +#define EMC6W201_REG_TEMP_LOW(nr) (0x56 + (nr) * 2) +#define EMC6W201_REG_TEMP_HIGH(nr) (0x57 + (nr) * 2) +#define EMC6W201_REG_FAN_MIN(nr) (0x62 + (nr) * 2) + +enum { input, min, max } subfeature; + +/* + * Per-device data + */ + +struct emc6w201_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* registers values */ + u8 in[3][6]; + s8 temp[3][6]; + u16 fan[2][5]; +}; + +/* + * Combine LSB and MSB registers in a single value + * Locking: must be called with data->update_lock held + */ +static u16 emc6w201_read16(struct i2c_client *client, u8 reg) +{ + int lsb, msb; + + lsb = i2c_smbus_read_byte_data(client, reg); + msb = i2c_smbus_read_byte_data(client, reg + 1); + if (lsb < 0 || msb < 0) { + dev_err(&client->dev, "16-bit read failed at 0x%02x\n", reg); + return 0xFFFF; /* Arbitrary value */ + } + + return (msb << 8) | lsb; +} + +/* + * Write 16-bit value to LSB and MSB registers + * Locking: must be called with data->update_lock held + */ +static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val) +{ + int err; + + err = i2c_smbus_write_byte_data(client, reg, val & 0xff); + if (!err) + err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8); + if (err < 0) + dev_err(&client->dev, "16-bit write failed at 0x%02x\n", reg); + + return err; +} + +static struct emc6w201_data *emc6w201_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct emc6w201_data *data = i2c_get_clientdata(client); + int nr; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + for (nr = 0; nr < 6; nr++) { + data->in[input][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_IN(nr)); + data->in[min][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_IN_LOW(nr)); + data->in[max][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_IN_HIGH(nr)); + } + + for (nr = 0; nr < 6; nr++) { + data->temp[input][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_TEMP(nr)); + data->temp[min][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_TEMP_LOW(nr)); + data->temp[max][nr] = + i2c_smbus_read_byte_data(client, + EMC6W201_REG_TEMP_HIGH(nr)); + } + + for (nr = 0; nr < 5; nr++) { + data->fan[input][nr] = + emc6w201_read16(client, + EMC6W201_REG_FAN(nr)); + data->fan[min][nr] = + emc6w201_read16(client, + EMC6W201_REG_FAN_MIN(nr)); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* + * Sysfs callback functions + */ + +static const u16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 }; + +static ssize_t show_in(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct emc6w201_data *data = emc6w201_update_device(dev); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + + return sprintf(buf, "%u\n", + (unsigned)data->in[sf][nr] * nominal_mv[nr] / 0xC0); +} + +static ssize_t set_in(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct emc6w201_data *data = i2c_get_clientdata(client); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + int err; + long val; + u8 reg; + + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; + + val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]); + reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr) + : EMC6W201_REG_IN_HIGH(nr); + + mutex_lock(&data->update_lock); + data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255); + err = i2c_smbus_write_byte_data(client, reg, data->in[sf][nr]); + mutex_unlock(&data->update_lock); + + return err < 0 ? err : count; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct emc6w201_data *data = emc6w201_update_device(dev); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + + return sprintf(buf, "%d\n", (int)data->temp[sf][nr] * 1000); +} + +static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct emc6w201_data *data = i2c_get_clientdata(client); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + int err; + long val; + u8 reg; + + err = strict_strtol(buf, 10, &val); + if (err < 0) + return err; + + val /= 1000; + reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr) + : EMC6W201_REG_TEMP_HIGH(nr); + + mutex_lock(&data->update_lock); + data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128); + err = i2c_smbus_write_byte_data(client, reg, data->temp[sf][nr]); + mutex_unlock(&data->update_lock); + + return err < 0 ? err : count; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct emc6w201_data *data = emc6w201_update_device(dev); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + unsigned rpm; + + if (data->fan[sf][nr] == 0 || data->fan[sf][nr] == 0xFFFF) + rpm = 0; + else + rpm = 5400000U / data->fan[sf][nr]; + + return sprintf(buf, "%u\n", rpm); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct emc6w201_data *data = i2c_get_clientdata(client); + int sf = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + int err; + unsigned long val; + + err = strict_strtoul(buf, 10, &val); + if (err < 0) + return err; + + if (val == 0) { + val = 0xFFFF; + } else { + val = DIV_ROUND_CLOSEST(5400000U, val); + val = SENSORS_LIMIT(val, 0, 0xFFFE); + } + + mutex_lock(&data->update_lock); + data->fan[sf][nr] = val; + err = emc6w201_write16(client, EMC6W201_REG_FAN_MIN(nr), + data->fan[sf][nr]); + mutex_unlock(&data->update_lock); + + return err < 0 ? err : count; +} + +static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, input); +static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in, + 0, min); +static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in, + 0, max); +static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, input); +static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in, + 1, min); +static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in, + 1, max); +static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, input); +static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in, + 2, min); +static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in, + 2, max); +static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, input); +static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in, + 3, min); +static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in, + 3, max); +static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, input); +static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in, + 4, min); +static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in, + 4, max); +static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, input); +static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in, + 5, min); +static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in, + 5, max); + +static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, input); +static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 0, min); +static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 0, max); +static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, input); +static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 1, min); +static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 1, max); +static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, input); +static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 2, min); +static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 2, max); +static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, input); +static SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 3, min); +static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 3, max); +static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, input); +static SENSOR_DEVICE_ATTR_2(temp5_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 4, min); +static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 4, max); +static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, input); +static SENSOR_DEVICE_ATTR_2(temp6_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + 5, min); +static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + 5, max); + +static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, input); +static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan, + 0, min); +static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, input); +static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan, + 1, min); +static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, input); +static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan, + 2, min); +static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, input); +static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan, + 3, min); +static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input); +static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan, + 4, min); + +static struct attribute *emc6w201_attributes[] = { + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp5_min.dev_attr.attr, + &sensor_dev_attr_temp5_max.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + &sensor_dev_attr_temp6_min.dev_attr.attr, + &sensor_dev_attr_temp6_max.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan5_min.dev_attr.attr, + NULL +}; + +static const struct attribute_group emc6w201_group = { + .attrs = emc6w201_attributes, +}; + +/* + * Driver interface + */ + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int emc6w201_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int company, verstep, config; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + /* Identification */ + company = i2c_smbus_read_byte_data(client, EMC6W201_REG_COMPANY); + if (company != 0x5C) + return -ENODEV; + verstep = i2c_smbus_read_byte_data(client, EMC6W201_REG_VERSTEP); + if (verstep < 0 || (verstep & 0xF0) != 0xB0) + return -ENODEV; + if ((verstep & 0x0F) > 2) { + dev_dbg(&client->dev, "Unknwown EMC6W201 stepping %d\n", + verstep & 0x0F); + return -ENODEV; + } + + /* Check configuration */ + config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG); + if ((config & 0xF4) != 0x04) + return -ENODEV; + if (!(config & 0x01)) { + dev_err(&client->dev, "Monitoring not enabled\n"); + return -ENODEV; + } + + strlcpy(info->type, "emc6w201", I2C_NAME_SIZE); + + return 0; +} + +static int emc6w201_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc6w201_data *data; + int err; + + data = kzalloc(sizeof(struct emc6w201_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Create sysfs attribute */ + err = sysfs_create_group(&client->dev.kobj, &emc6w201_group); + if (err) + goto exit_free; + + /* Expose as a hwmon device */ + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + return 0; + + exit_remove: + sysfs_remove_group(&client->dev.kobj, &emc6w201_group); + exit_free: + kfree(data); + exit: + return err; +} + +static int emc6w201_remove(struct i2c_client *client) +{ + struct emc6w201_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &emc6w201_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id emc6w201_id[] = { + { "emc6w201", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc6w201_id); + +static struct i2c_driver emc6w201_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc6w201", + }, + .probe = emc6w201_probe, + .remove = emc6w201_remove, + .id_table = emc6w201_id, + .detect = emc6w201_detect, + .address_list = normal_i2c, +}; + +static int __init sensors_emc6w201_init(void) +{ + return i2c_add_driver(&emc6w201_driver); +} +module_init(sensors_emc6w201_init); + +static void __exit sensors_emc6w201_exit(void) +{ + i2c_del_driver(&emc6w201_driver); +} +module_exit(sensors_emc6w201_exit); + +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca07a32447c..a4a94a096c9 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -48,6 +48,7 @@ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ #define SIO_F71808E_ID 0x0901 /* Chipset ID */ +#define SIO_F71808A_ID 0x1001 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71869_ID 0x0814 /* Chipset ID */ @@ -107,11 +108,12 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg, +enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71882fg, f71889fg, f71889ed, f71889a, f8000, f81865f }; static const char *f71882fg_names[] = { "f71808e", + "f71808a", "f71858fg", "f71862fg", "f71869", /* Both f71869f and f71869e, reg. compatible and same id */ @@ -125,6 +127,7 @@ static const char *f71882fg_names[] = { static const char f71882fg_has_in[][F71882FG_MAX_INS] = { [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + [f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1 }, [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, @@ -138,6 +141,7 @@ static const char f71882fg_has_in[][F71882FG_MAX_INS] = { static const char f71882fg_has_in1_alarm[] = { [f71808e] = 0, + [f71808a] = 0, [f71858fg] = 0, [f71862fg] = 0, [f71869] = 0, @@ -149,8 +153,9 @@ static const char f71882fg_has_in1_alarm[] = { [f81865f] = 1, }; -static const char f71882fg_has_beep[] = { +static const char f71882fg_fan_has_beep[] = { [f71808e] = 0, + [f71808a] = 0, [f71858fg] = 0, [f71862fg] = 1, [f71869] = 1, @@ -164,6 +169,7 @@ static const char f71882fg_has_beep[] = { static const char f71882fg_nr_fans[] = { [f71808e] = 3, + [f71808a] = 2, /* +1 fan which is monitor + simple pwm only */ [f71858fg] = 3, [f71862fg] = 3, [f71869] = 3, @@ -171,12 +177,27 @@ static const char f71882fg_nr_fans[] = { [f71889fg] = 3, [f71889ed] = 3, [f71889a] = 3, - [f8000] = 3, + [f8000] = 3, /* +1 fan which is monitor only */ [f81865f] = 2, }; +static const char f71882fg_temp_has_beep[] = { + [f71808e] = 0, + [f71808a] = 1, + [f71858fg] = 0, + [f71862fg] = 1, + [f71869] = 1, + [f71882fg] = 1, + [f71889fg] = 1, + [f71889ed] = 1, + [f71889a] = 1, + [f8000] = 0, + [f81865f] = 1, +}; + static const char f71882fg_nr_temps[] = { [f71808e] = 2, + [f71808a] = 2, [f71858fg] = 3, [f71862fg] = 3, [f71869] = 3, @@ -301,6 +322,10 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf); static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_simple_pwm(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_simple_pwm(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf); static ssize_t store_pwm_enable(struct device *dev, @@ -550,6 +575,14 @@ static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { { show_pwm_interpolate, store_pwm_interpolate, 0, 3), } }; +/* Attr for the third fan of the f71808a, which only has manual pwm */ +static struct sensor_device_attribute_2 f71808a_fan3_attr[] = { + SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), + SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), + SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, + show_simple_pwm, store_simple_pwm, 0, 2), +}; + /* Attr for models which can beep on Fan alarm */ static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = { SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, @@ -1146,12 +1179,13 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[3] = (reg & 0x08) ? 2 : 4; } - if (f71882fg_has_beep[data->type]) { + if (f71882fg_fan_has_beep[data->type]) data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); + + if (f71882fg_temp_has_beep[data->type]) data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); - } data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); @@ -1232,7 +1266,13 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->pwm[nr] = f71882fg_read8(data, F71882FG_REG_PWM(nr)); } - /* The f8000 can monitor 1 more fan, but has no pwm for it */ + /* Some models have 1 more fan with limited capabilities */ + if (data->type == f71808a) { + data->fan[2] = f71882fg_read16(data, + F71882FG_REG_FAN(2)); + data->pwm[2] = f71882fg_read8(data, + F71882FG_REG_PWM(2)); + } if (data->type == f8000) data->fan[3] = f71882fg_read16(data, F71882FG_REG_FAN(3)); @@ -1722,6 +1762,38 @@ leave: return count; } +static ssize_t show_simple_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int val, nr = to_sensor_dev_attr_2(devattr)->index; + + val = data->pwm[nr]; + return sprintf(buf, "%d\n", val); +} + +static ssize_t store_simple_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int err, nr = to_sensor_dev_attr_2(devattr)->index; + long val; + + err = strict_strtol(buf, 10, &val); + if (err) + return err; + + val = SENSORS_LIMIT(val, 0, 255); + + mutex_lock(&data->update_lock); + f71882fg_write8(data, F71882FG_REG_PWM(nr), val); + data->pwm[nr] = val; + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -2140,7 +2212,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) if (err) goto exit_unregister_sysfs; - if (f71882fg_has_beep[data->type]) { + if (f71882fg_temp_has_beep[data->type]) { err = f71882fg_create_sysfs_files(pdev, &fxxxx_temp_beep_attr[0][0], ARRAY_SIZE(fxxxx_temp_beep_attr[0]) @@ -2169,6 +2241,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) if (start_reg & 0x02) { switch (data->type) { case f71808e: + case f71808a: case f71869: /* These always have signed auto point temps */ data->auto_point_temp_signed = 1; @@ -2221,7 +2294,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) if (err) goto exit_unregister_sysfs; - if (f71882fg_has_beep[data->type]) { + if (f71882fg_fan_has_beep[data->type]) { err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_beep_attr, nr_fans); if (err) @@ -2230,6 +2303,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) switch (data->type) { case f71808e: + case f71808a: case f71869: case f71889fg: case f71889ed: @@ -2255,6 +2329,16 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) } switch (data->type) { + case f71808a: + err = f71882fg_create_sysfs_files(pdev, + &fxxxx_auto_pwm_attr[0][0], + ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + f71808a_fan3_attr, + ARRAY_SIZE(f71808a_fan3_attr)); + break; case f71862fg: err = f71882fg_create_sysfs_files(pdev, f71862fg_auto_pwm_attr, @@ -2343,7 +2427,7 @@ static int f71882fg_remove(struct platform_device *pdev) &fxxxx_temp_attr[0][0], ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps); } - if (f71882fg_has_beep[data->type]) { + if (f71882fg_temp_has_beep[data->type]) { f71882fg_remove_sysfs_files(pdev, &fxxxx_temp_beep_attr[0][0], ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps); @@ -2366,12 +2450,20 @@ static int f71882fg_remove(struct platform_device *pdev) f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0], ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans); - if (f71882fg_has_beep[data->type]) { + if (f71882fg_fan_has_beep[data->type]) { f71882fg_remove_sysfs_files(pdev, fxxxx_fan_beep_attr, nr_fans); } switch (data->type) { + case f71808a: + f71882fg_remove_sysfs_files(pdev, + &fxxxx_auto_pwm_attr[0][0], + ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); + f71882fg_remove_sysfs_files(pdev, + f71808a_fan3_attr, + ARRAY_SIZE(f71808a_fan3_attr)); + break; case f71862fg: f71882fg_remove_sysfs_files(pdev, f71862fg_auto_pwm_attr, @@ -2424,6 +2516,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, case SIO_F71808E_ID: sio_data->type = f71808e; break; + case SIO_F71808A_ID: + sio_data->type = f71808a; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c new file mode 100644 index 00000000000..523f8fb9e7d --- /dev/null +++ b/drivers/hwmon/fam15h_power.c @@ -0,0 +1,229 @@ +/* + * fam15h_power.c - AMD Family 15h processor power monitoring + * + * Copyright (c) 2011 Advanced Micro Devices, Inc. + * Author: Andreas Herrmann <andreas.herrmann3@amd.com> + * + * + * This driver is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License; either + * version 2 of the License, or (at your option) any later version. + * + * This driver 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 driver; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); +MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>"); +MODULE_LICENSE("GPL"); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8 + +/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8 + +struct fam15h_power_data { + struct device *hwmon_dev; + unsigned int tdp_to_watts; + unsigned int base_tdp; + unsigned int processor_pwr_watts; +}; + +static ssize_t show_power(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 val, tdp_limit, running_avg_range; + s32 running_avg_capture; + u64 curr_pwr_watts; + struct pci_dev *f4 = to_pci_dev(dev); + struct fam15h_power_data *data = dev_get_drvdata(dev); + + pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), + REG_TDP_RUNNING_AVERAGE, &val); + running_avg_capture = (val >> 4) & 0x3fffff; + running_avg_capture = sign_extend32(running_avg_capture, 22); + running_avg_range = val & 0xf; + + pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), + REG_TDP_LIMIT3, &val); + + tdp_limit = val >> 16; + curr_pwr_watts = tdp_limit + data->base_tdp - + (s32)(running_avg_capture >> (running_avg_range + 1)); + curr_pwr_watts *= data->tdp_to_watts; + + /* + * Convert to microWatt + * + * power is in Watt provided as fixed point integer with + * scaling factor 1/(2^16). For conversion we use + * (10^6)/(2^16) = 15625/(2^10) + */ + curr_pwr_watts = (curr_pwr_watts * 15625) >> 10; + return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts); +} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_crit(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", data->processor_pwr_watts); +} +static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); + +static ssize_t show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "fam15h_power\n"); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static struct attribute *fam15h_power_attrs[] = { + &dev_attr_power1_input.attr, + &dev_attr_power1_crit.attr, + &dev_attr_name.attr, + NULL +}; + +static const struct attribute_group fam15h_power_attr_group = { + .attrs = fam15h_power_attrs, +}; + +static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) +{ + u32 val; + + pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 3), + REG_NORTHBRIDGE_CAP, &val); + if ((val & BIT(29)) && ((val >> 30) & 3)) + return false; + + return true; +} + +static void __devinit fam15h_power_init_data(struct pci_dev *f4, + struct fam15h_power_data *data) +{ + u32 val; + u64 tmp; + + pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); + data->base_tdp = val >> 16; + tmp = val & 0xffff; + + pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), + REG_TDP_LIMIT3, &val); + + data->tdp_to_watts = ((val & 0x3ff) << 6) | ((val >> 10) & 0x3f); + tmp *= data->tdp_to_watts; + + /* result not allowed to be >= 256W */ + if ((tmp >> 16) >= 256) + dev_warn(&f4->dev, "Bogus value for ProcessorPwrWatts " + "(processor_pwr_watts>=%u)\n", + (unsigned int) (tmp >> 16)); + + /* convert to microWatt */ + data->processor_pwr_watts = (tmp * 15625) >> 10; +} + +static int __devinit fam15h_power_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct fam15h_power_data *data; + struct device *dev; + int err; + + if (!fam15h_power_is_internal_node0(pdev)) { + err = -ENODEV; + goto exit; + } + + data = kzalloc(sizeof(struct fam15h_power_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + fam15h_power_init_data(pdev, data); + dev = &pdev->dev; + + dev_set_drvdata(dev, data); + err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group); + if (err) + goto exit_free_data; + + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_group; + } + + return 0; + +exit_remove_group: + sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); +exit_free_data: + kfree(data); +exit: + return err; +} + +static void __devexit fam15h_power_remove(struct pci_dev *pdev) +{ + struct device *dev; + struct fam15h_power_data *data; + + dev = &pdev->dev; + data = dev_get_drvdata(dev); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); + dev_set_drvdata(dev, NULL); + kfree(data); +} + +static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, + {} +}; +MODULE_DEVICE_TABLE(pci, fam15h_power_id_table); + +static struct pci_driver fam15h_power_driver = { + .name = "fam15h_power", + .id_table = fam15h_power_id_table, + .probe = fam15h_power_probe, + .remove = __devexit_p(fam15h_power_remove), +}; + +static int __init fam15h_power_init(void) +{ + return pci_register_driver(&fam15h_power_driver); +} + +static void __exit fam15h_power_exit(void) +{ + pci_unregister_driver(&fam15h_power_driver); +} + +module_init(fam15h_power_init) +module_exit(fam15h_power_exit) diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index bc6e2ab3a36..537409d07ee 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -523,7 +523,7 @@ static void aem_delete(struct aem_data *data) aem_remove_sensors(data); hwmon_device_unregister(data->hwmon_dev); ipmi_destroy_user(data->ipmi.user); - dev_set_drvdata(&data->pdev->dev, NULL); + platform_set_drvdata(data->pdev, NULL); platform_device_unregister(data->pdev); aem_idr_put(data->id); kfree(data); @@ -594,7 +594,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) if (res) goto ipmi_err; - dev_set_drvdata(&data->pdev->dev, data); + platform_set_drvdata(data->pdev, data); /* Set up IPMI interface */ if (aem_init_ipmi_data(&data->ipmi, probe->interface, @@ -630,7 +630,7 @@ sensor_err: hwmon_reg_err: ipmi_destroy_user(data->ipmi.user); ipmi_err: - dev_set_drvdata(&data->pdev->dev, NULL); + platform_set_drvdata(data->pdev, NULL); platform_device_unregister(data->pdev); dev_err: aem_idr_put(data->id); @@ -727,7 +727,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe, if (res) goto ipmi_err; - dev_set_drvdata(&data->pdev->dev, data); + platform_set_drvdata(data->pdev, data); /* Set up IPMI interface */ if (aem_init_ipmi_data(&data->ipmi, probe->interface, @@ -763,7 +763,7 @@ sensor_err: hwmon_reg_err: ipmi_destroy_user(data->ipmi.user); ipmi_err: - dev_set_drvdata(&data->pdev->dev, NULL); + platform_set_drvdata(data->pdev, NULL); platform_device_unregister(data->pdev); dev_err: aem_idr_put(data->id); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 316b64823f7..bb6405b9200 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -77,15 +77,13 @@ static struct platform_device *pdev; #define DEVID 0x20 /* Register: Device ID */ #define DEVREV 0x22 /* Register: Device Revision */ -static inline int -superio_inb(int reg) +static inline int superio_inb(int reg) { outb(reg, REG); return inb(VAL); } -static inline void -superio_outb(int reg, int val) +static inline void superio_outb(int reg, int val) { outb(reg, REG); outb(val, VAL); @@ -101,27 +99,32 @@ static int superio_inw(int reg) return val; } -static inline void -superio_select(int ldn) +static inline void superio_select(int ldn) { outb(DEV, REG); outb(ldn, VAL); } -static inline void -superio_enter(void) +static inline int superio_enter(void) { + /* + * Try to reserve REG and REG + 1 for exclusive access. + */ + if (!request_muxed_region(REG, 2, DRVNAME)) + return -EBUSY; + outb(0x87, REG); outb(0x01, REG); outb(0x55, REG); outb(0x55, REG); + return 0; } -static inline void -superio_exit(void) +static inline void superio_exit(void) { outb(0x02, REG); outb(0x02, VAL); + release_region(REG, 2); } /* Logical device 4 registers */ @@ -1542,11 +1545,15 @@ static const struct attribute_group it87_group_label = { static int __init it87_find(unsigned short *address, struct it87_sio_data *sio_data) { - int err = -ENODEV; + int err; u16 chip_type; const char *board_vendor, *board_name; - superio_enter(); + err = superio_enter(); + if (err) + return err; + + err = -ENODEV; chip_type = force_id ? force_id : superio_inw(DEVID); switch (chip_type) { diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index 93499123706..02cebb74e20 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -213,7 +213,7 @@ static const struct dev_pm_ops jc42_dev_pm_ops = { /* This is the driver that will be inserted */ static struct i2c_driver jc42_driver = { - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_SPD, .driver = { .name = "jc42", .pm = JC42_DEV_PM_OPS, diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 82bf65aa296..41aa6a31987 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -1,5 +1,5 @@ /* - * k10temp.c - AMD Family 10h/11h/12h/14h processor hardware monitoring + * k10temp.c - AMD Family 10h/11h/12h/14h/15h processor hardware monitoring * * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de> * @@ -25,7 +25,7 @@ #include <linux/pci.h> #include <asm/processor.h> -MODULE_DESCRIPTION("AMD Family 10h/11h/12h/14h CPU core temperature monitor"); +MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); MODULE_LICENSE("GPL"); @@ -173,7 +173,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev, err = PTR_ERR(hwmon_dev); goto exit_remove; } - dev_set_drvdata(&pdev->dev, hwmon_dev); + pci_set_drvdata(pdev, hwmon_dev); if (unreliable && force) dev_warn(&pdev->dev, @@ -194,7 +194,7 @@ exit: static void __devexit k10temp_remove(struct pci_dev *pdev) { - hwmon_device_unregister(dev_get_drvdata(&pdev->dev)); + hwmon_device_unregister(pci_get_drvdata(pdev)); device_remove_file(&pdev->dev, &dev_attr_name); device_remove_file(&pdev->dev, &dev_attr_temp1_input); device_remove_file(&pdev->dev, &dev_attr_temp1_max); @@ -202,13 +202,14 @@ static void __devexit k10temp_remove(struct pci_dev *pdev) &sensor_dev_attr_temp1_crit.dev_attr); device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_crit_hyst.dev_attr); - dev_set_drvdata(&pdev->dev, NULL); + pci_set_drvdata(pdev, NULL); } static const struct pci_device_id k10temp_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, {} }; MODULE_DEVICE_TABLE(pci, k10temp_id_table); diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 418496f1302..b923bc2307a 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -252,7 +252,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, data->name = "k8temp"; mutex_init(&data->update_lock); - dev_set_drvdata(&pdev->dev, data); + pci_set_drvdata(pdev, data); /* Register sysfs hooks */ err = device_create_file(&pdev->dev, @@ -307,7 +307,7 @@ exit_remove: &sensor_dev_attr_temp4_input.dev_attr); device_remove_file(&pdev->dev, &dev_attr_name); exit_free: - dev_set_drvdata(&pdev->dev, NULL); + pci_set_drvdata(pdev, NULL); kfree(data); exit: return err; @@ -315,7 +315,7 @@ exit: static void __devexit k8temp_remove(struct pci_dev *pdev) { - struct k8temp_data *data = dev_get_drvdata(&pdev->dev); + struct k8temp_data *data = pci_get_drvdata(pdev); hwmon_device_unregister(data->hwmon_dev); device_remove_file(&pdev->dev, @@ -327,7 +327,7 @@ static void __devexit k8temp_remove(struct pci_dev *pdev) device_remove_file(&pdev->dev, &sensor_dev_attr_temp4_input.dev_attr); device_remove_file(&pdev->dev, &dev_attr_name); - dev_set_drvdata(&pdev->dev, NULL); + pci_set_drvdata(pdev, NULL); kfree(data); } diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 3b84fb50305..c274ea25d89 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -58,7 +58,7 @@ static ssize_t lm70_sense_temp(struct device *dev, int status, val = 0; u8 rxbuf[2]; s16 raw=0; - struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + struct lm70 *p_lm70 = spi_get_drvdata(spi); if (mutex_lock_interruptible(&p_lm70->lock)) return -ERESTARTSYS; @@ -163,7 +163,7 @@ static int __devinit lm70_probe(struct spi_device *spi) status = PTR_ERR(p_lm70->hwmon_dev); goto out_dev_reg_failed; } - dev_set_drvdata(&spi->dev, p_lm70); + spi_set_drvdata(spi, p_lm70); if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input)) || (status = device_create_file(&spi->dev, &dev_attr_name))) { @@ -177,19 +177,19 @@ out_dev_create_file_failed: device_remove_file(&spi->dev, &dev_attr_temp1_input); hwmon_device_unregister(p_lm70->hwmon_dev); out_dev_reg_failed: - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); kfree(p_lm70); return status; } static int __devexit lm70_remove(struct spi_device *spi) { - struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + struct lm70 *p_lm70 = spi_get_drvdata(spi); device_remove_file(&spi->dev, &dev_attr_temp1_input); device_remove_file(&spi->dev, &dev_attr_name); hwmon_device_unregister(p_lm70->hwmon_dev); - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); kfree(p_lm70); return 0; diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 9a11532ecae..ece3aafa54b 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -41,13 +41,6 @@ #include <linux/err.h> /* - * Addresses to scan. There are four disjoint possibilities, by pin config. - */ - -static const unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, - I2C_CLIENT_END}; - -/* * Insmod parameters */ @@ -114,8 +107,6 @@ module_param(clock, int, S_IRUGO); static int max6650_probe(struct i2c_client *client, const struct i2c_device_id *id); -static int max6650_detect(struct i2c_client *client, - struct i2c_board_info *info); static int max6650_init_client(struct i2c_client *client); static int max6650_remove(struct i2c_client *client); static struct max6650_data *max6650_update_device(struct device *dev); @@ -125,21 +116,19 @@ static struct max6650_data *max6650_update_device(struct device *dev); */ static const struct i2c_device_id max6650_id[] = { - { "max6650", 0 }, + { "max6650", 1 }, + { "max6651", 4 }, { } }; MODULE_DEVICE_TABLE(i2c, max6650_id); static struct i2c_driver max6650_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "max6650", }, .probe = max6650_probe, .remove = max6650_remove, .id_table = max6650_id, - .detect = max6650_detect, - .address_list = normal_i2c, }; /* @@ -150,6 +139,7 @@ struct max6650_data { struct device *hwmon_dev; struct mutex update_lock; + int nr_fans; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -501,9 +491,6 @@ static mode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, static struct attribute *max6650_attrs[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, &dev_attr_fan1_target.attr, &dev_attr_fan1_div.attr, &dev_attr_pwm1_enable.attr, @@ -521,42 +508,21 @@ static struct attribute_group max6650_attr_grp = { .is_visible = max6650_attrs_visible, }; +static struct attribute *max6651_attrs[] = { + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group max6651_attr_grp = { + .attrs = max6651_attrs, +}; + /* * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6650_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - - dev_dbg(&adapter->dev, "max6650_detect called\n"); - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " - "byte read mode, skipping.\n"); - return -ENODEV; - } - - if (((i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { - dev_dbg(&adapter->dev, - "max6650: detection failed at 0x%02x.\n", address); - return -ENODEV; - } - - dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); - - strlcpy(info->type, "max6650", I2C_NAME_SIZE); - - return 0; -} - static int max6650_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -570,6 +536,7 @@ static int max6650_probe(struct i2c_client *client, i2c_set_clientdata(client, data); mutex_init(&data->update_lock); + data->nr_fans = id->driver_data; /* * Initialize the max6650 chip @@ -581,6 +548,12 @@ static int max6650_probe(struct i2c_client *client, err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); if (err) goto err_free; + /* 3 additional fan inputs for the MAX6651 */ + if (data->nr_fans == 4) { + err = sysfs_create_group(&client->dev.kobj, &max6651_attr_grp); + if (err) + goto err_remove; + } data->hwmon_dev = hwmon_device_register(&client->dev); if (!IS_ERR(data->hwmon_dev)) @@ -588,6 +561,9 @@ static int max6650_probe(struct i2c_client *client, err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); + if (data->nr_fans == 4) + sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); +err_remove: sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); err_free: kfree(data); @@ -598,8 +574,10 @@ static int max6650_remove(struct i2c_client *client) { struct max6650_data *data = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); hwmon_device_unregister(data->hwmon_dev); + if (data->nr_fans == 4) + sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); + sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); kfree(data); return 0; } @@ -712,7 +690,7 @@ static struct max6650_data *max6650_update_device(struct device *dev) MAX6650_REG_SPEED); data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); - for (i = 0; i < 4; i++) { + for (i = 0; i < data->nr_fans; i++) { data->tach[i] = i2c_smbus_read_byte_data(client, tach_reg[i]); } diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index 9a51dcca9b0..020c87273ea 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -52,6 +52,9 @@ #define SCH5627_COMPANY_ID 0x5c #define SCH5627_PRIMARY_ID 0xa0 +#define SCH5627_CMD_READ 0x02 +#define SCH5627_CMD_WRITE 0x03 + #define SCH5627_REG_BUILD_CODE 0x39 #define SCH5627_REG_BUILD_ID 0x3a #define SCH5627_REG_HWMON_ID 0x3c @@ -94,11 +97,13 @@ static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = { struct sch5627_data { unsigned short addr; struct device *hwmon_dev; + u8 control; u8 temp_max[SCH5627_NO_TEMPS]; u8 temp_crit[SCH5627_NO_TEMPS]; u16 fan_min[SCH5627_NO_FANS]; struct mutex update_lock; + unsigned long last_battery; /* In jiffies */ char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ u16 temp[SCH5627_NO_TEMPS]; @@ -140,7 +145,7 @@ static inline void superio_exit(int base) release_region(base, 2); } -static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg) +static int sch5627_send_cmd(struct sch5627_data *data, u8 cmd, u16 reg, u8 v) { u8 val; int i; @@ -163,10 +168,14 @@ static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg) outb(0x80, data->addr + 3); /* Write Request Packet Header */ - outb(0x02, data->addr + 4); /* Access Type: VREG read */ + outb(cmd, data->addr + 4); /* VREG Access Type read:0x02 write:0x03 */ outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */ outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */ + /* Write Value field */ + if (cmd == SCH5627_CMD_WRITE) + outb(v, data->addr + 4); + /* Write Address field */ outb(reg & 0xff, data->addr + 6); outb(reg >> 8, data->addr + 7); @@ -224,8 +233,22 @@ static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg) * But if we do that things don't work, so let's not. */ - /* Read Data from Mailbox */ - return inb(data->addr + 4); + /* Read Value field */ + if (cmd == SCH5627_CMD_READ) + return inb(data->addr + 4); + + return 0; +} + +static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg) +{ + return sch5627_send_cmd(data, SCH5627_CMD_READ, reg, 0); +} + +static int sch5627_write_virtual_reg(struct sch5627_data *data, + u16 reg, u8 val) +{ + return sch5627_send_cmd(data, SCH5627_CMD_WRITE, reg, val); } static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg) @@ -272,6 +295,13 @@ static struct sch5627_data *sch5627_update_device(struct device *dev) mutex_lock(&data->update_lock); + /* Trigger a Vbat voltage measurement every 5 minutes */ + if (time_after(jiffies, data->last_battery + 300 * HZ)) { + sch5627_write_virtual_reg(data, SCH5627_REG_CTRL, + data->control | 0x10); + data->last_battery = jiffies; + } + /* Cache the values for 1 second */ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { for (i = 0; i < SCH5627_NO_TEMPS; i++) { @@ -696,11 +726,17 @@ static int __devinit sch5627_probe(struct platform_device *pdev) err = val; goto error; } - if (!(val & 0x01)) { + data->control = val; + if (!(data->control & 0x01)) { pr_err("hardware monitoring not enabled\n"); err = -ENODEV; goto error; } + /* Trigger a Vbat voltage measurement, so that we get a valid reading + the first time we read Vbat */ + sch5627_write_virtual_reg(data, SCH5627_REG_CTRL, + data->control | 0x10); + data->last_battery = jiffies; /* * Read limits, we do this only once as reading a register on diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 1f36c635d93..27a62711e0a 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -258,7 +258,7 @@ static int __devinit env_probe(struct platform_device *op) goto out_sysfs_remove_group; } - dev_set_drvdata(&op->dev, p); + platform_set_drvdata(op, p); err = 0; out: @@ -277,7 +277,7 @@ out_free: static int __devexit env_remove(struct platform_device *op) { - struct env *p = dev_get_drvdata(&op->dev); + struct env *p = platform_get_drvdata(op); if (p) { sysfs_remove_group(&op->dev.kobj, &env_group); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index a5ec5a7cb38..6e5123b1d34 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1781,7 +1781,8 @@ static int ide_cd_probe(ide_drive_t *drive) ide_cd_read_toc(drive, &sense); g->fops = &idecd_ops; - g->flags |= GENHD_FL_REMOVABLE; + g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; + g->events = DISK_EVENT_MEDIA_CHANGE; add_disk(g); return 0; diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h index 4d8ea32e8a0..22be27b424d 100644 --- a/drivers/input/input-compat.h +++ b/drivers/input/input-compat.h @@ -19,7 +19,7 @@ /* Note to the author of this code: did it ever occur to you why the ifdefs are needed? Think about it again. -AK */ -#ifdef CONFIG_X86_64 +#if defined(CONFIG_X86_64) || defined(CONFIG_TILE) # define INPUT_COMPAT_TEST is_compat_task() #elif defined(CONFIG_S390) # define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3ed3ff06be5..481770ab271 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -538,7 +538,7 @@ config AB8500_CORE config AB8500_I2C_CORE bool "AB8500 register access via PRCMU I2C" - depends on AB8500_CORE && UX500_SOC_DB8500 + depends on AB8500_CORE && MFD_DB8500_PRCMU default y help This enables register access to the AB8500 chip via PRCMU I2C. @@ -575,6 +575,26 @@ config AB3550_CORE LEDs, vibrator, system power and temperature, power management and ALSA sound. +config MFD_DB8500_PRCMU + bool "ST-Ericsson DB8500 Power Reset Control Management Unit" + depends on UX500_SOC_DB8500 + select MFD_CORE + help + Select this option to enable support for the DB8500 Power Reset + and Control Management Unit. This is basically an autonomous + system controller running an XP70 microprocessor, which is accessed + through a register map. + +config MFD_DB5500_PRCMU + bool "ST-Ericsson DB5500 Power Reset Control Management Unit" + depends on UX500_SOC_DB5500 + select MFD_CORE + help + Select this option to enable support for the DB5500 Power Reset + and Control Management Unit. This is basically an autonomous + system controller running an XP70 microprocessor, which is accessed + through a register map. + config MFD_CS5535 tristate "Support for CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 419caa9d7dc..24aa44448da 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -74,9 +74,12 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o obj-$(CONFIG_AB3550_CORE) += ab3550-core.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o -obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o +obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o +# ab8500-i2c need to come after db8500-prcmu (which provides the channel) +obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o +obj-$(CONFIG_MFD_DB5500_PRCMU) += db5500-prcmu.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c index 821e6b86afd..9be541c6b00 100644 --- a/drivers/mfd/ab8500-i2c.c +++ b/drivers/mfd/ab8500-i2c.c @@ -11,8 +11,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/mfd/ab8500.h> - -#include <mach/prcmu.h> +#include <linux/mfd/db8500-prcmu.h> static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) { diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/drivers/mfd/db5500-prcmu-regs.h index 455467e8879..9a8e9e4ddd3 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/drivers/mfd/db5500-prcmu-regs.h @@ -15,11 +15,20 @@ #include <mach/hardware.h> -#define _PRCMU_BASE IO_ADDRESS(U8500_PRCMU_BASE) - #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) +#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f +#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf + +#define PRCM_PLLARM_LOCKP (_PRCMU_BASE + 0x0a8) +#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2 + #define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114) +#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1 + #define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98) +#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1 +#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100 + #define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) #define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) #define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) @@ -28,7 +37,8 @@ /* ARM WFI Standby signal register */ #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) -#define PRCMU_IOCR (_PRCMU_BASE + 0x310) +#define PRCM_IOCR (_PRCMU_BASE + 0x310) +#define PRCM_IOCR_IOFORCE 0x1 /* CPU mailbox registers */ #define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc) @@ -37,6 +47,8 @@ /* Dual A9 core interrupt management unit registers */ #define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328) +#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1 + #define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c) #define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c) #define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120) @@ -74,14 +86,17 @@ /* PRCMU clock/PLL/reset registers */ #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) +#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) #define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) #define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) #define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) #define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) +#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) #define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) #define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) +#define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) /* ePOD and memory power signal control registers */ #define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) @@ -92,5 +107,9 @@ /* Miscellaneous unit registers */ #define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) +#define PRCM_GPIOCR (_PRCMU_BASE + 0x138) +#define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 +#define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 + -#endif /* __MACH_PRCMU_REGS_H */ +#endif /* __MACH_PRCMU__REGS_H */ diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c new file mode 100644 index 00000000000..9dbb3cab4a6 --- /dev/null +++ b/drivers/mfd/db5500-prcmu.c @@ -0,0 +1,448 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> + * + * U5500 PRCM Unit interface driver + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/completion.h> +#include <linux/irq.h> +#include <linux/jiffies.h> +#include <linux/bitops.h> +#include <linux/interrupt.h> +#include <linux/mfd/db5500-prcmu.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/db5500-regs.h> +#include "db5500-prcmu-regs.h" + +#define _PRCM_MB_HEADER (tcdm_base + 0xFE8) +#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0) +#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1) +#define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2) +#define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3) +#define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4) +#define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5) +#define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6) +#define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7) +#define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8) +#define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9) +#define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa) +#define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb) +#define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc) +#define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd) +#define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe) +#define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf) + +/* Req Mailboxes */ +#define PRCM_REQ_MB0 (tcdm_base + 0xFD8) +#define PRCM_REQ_MB1 (tcdm_base + 0xFCC) +#define PRCM_REQ_MB2 (tcdm_base + 0xFC4) +#define PRCM_REQ_MB3 (tcdm_base + 0xFC0) +#define PRCM_REQ_MB4 (tcdm_base + 0xF98) +#define PRCM_REQ_MB5 (tcdm_base + 0xF90) +#define PRCM_REQ_MB6 (tcdm_base + 0xF8C) +#define PRCM_REQ_MB7 (tcdm_base + 0xF84) + +/* Ack Mailboxes */ +#define PRCM_ACK_MB0 (tcdm_base + 0xF38) +#define PRCM_ACK_MB1 (tcdm_base + 0xF30) +#define PRCM_ACK_MB2 (tcdm_base + 0xF24) +#define PRCM_ACK_MB3 (tcdm_base + 0xF20) +#define PRCM_ACK_MB4 (tcdm_base + 0xF1C) +#define PRCM_ACK_MB5 (tcdm_base + 0xF14) +#define PRCM_ACK_MB6 (tcdm_base + 0xF0C) +#define PRCM_ACK_MB7 (tcdm_base + 0xF08) + +enum mb_return_code { + RC_SUCCESS, + RC_FAIL, +}; + +/* Mailbox 0 headers. */ +enum mb0_header { + /* request */ + RMB0H_PWR_STATE_TRANS = 1, + RMB0H_WAKE_UP_CFG, + RMB0H_RD_WAKE_UP_ACK, + /* acknowledge */ + AMB0H_WAKE_UP = 1, +}; + +/* Mailbox 5 headers. */ +enum mb5_header { + MB5H_I2C_WRITE = 1, + MB5H_I2C_READ, +}; + +/* Request mailbox 5 fields. */ +#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0) +#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1) +#define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2) +#define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4) + +/* Acknowledge mailbox 5 fields. */ +#define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0) +#define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4) + +#define NUM_MB 8 +#define MBOX_BIT BIT +#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1) + +/* +* Used by MCDE to setup all necessary PRCMU registers +*/ +#define PRCMU_RESET_DSIPLL 0x00004000 +#define PRCMU_UNCLAMP_DSIPLL 0x00400800 + +/* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/ +#define PRCMU_DSI_CLOCK_SETTING 0x00000128 +/* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */ +#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135 +#define PRCMU_PLLDSI_FREQ_SETTING 0x0004013C +#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002 +#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000101 +#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101 + +#define PRCMU_ENABLE_PLLDSI 0x00000001 +#define PRCMU_DISABLE_PLLDSI 0x00000000 + +#define PRCMU_DSI_RESET_SW 0x00000003 + +#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 + +/* + * mb0_transfer - state needed for mailbox 0 communication. + * @lock: The transaction lock. + */ +static struct { + spinlock_t lock; +} mb0_transfer; + +/* + * mb5_transfer - state needed for mailbox 5 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @ack: Reply ("acknowledge") data. + */ +static struct { + struct mutex lock; + struct completion work; + struct { + u8 header; + u8 status; + u8 value[4]; + } ack; +} mb5_transfer; + +/* PRCMU TCDM base IO address. */ +static __iomem void *tcdm_base; + +/** + * db5500_prcmu_abb_read() - Read register value(s) from the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The read out value(s). + * @size: The number of registers to read. + * + * Reads register value(s) from the ABB. + * @size has to be <= 4. + */ +int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if ((size < 1) || (4 < size)) + return -EINVAL; + + mutex_lock(&mb5_transfer.lock); + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + writeb(slave, PRCM_REQ_MB5_I2C_SLAVE); + writeb(reg, PRCM_REQ_MB5_I2C_REG); + writeb(size, PRCM_REQ_MB5_I2C_SIZE); + writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER); + + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); + wait_for_completion(&mb5_transfer.work); + + r = 0; + if ((mb5_transfer.ack.header == MB5H_I2C_READ) && + (mb5_transfer.ack.status == RC_SUCCESS)) + memcpy(value, mb5_transfer.ack.value, (size_t)size); + else + r = -EIO; + + mutex_unlock(&mb5_transfer.lock); + + return r; +} + +/** + * db5500_prcmu_abb_write() - Write register value(s) to the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The value(s) to write. + * @size: The number of registers to write. + * + * Writes register value(s) to the ABB. + * @size has to be <= 4. + */ +int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if ((size < 1) || (4 < size)) + return -EINVAL; + + mutex_lock(&mb5_transfer.lock); + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + writeb(slave, PRCM_REQ_MB5_I2C_SLAVE); + writeb(reg, PRCM_REQ_MB5_I2C_REG); + writeb(size, PRCM_REQ_MB5_I2C_SIZE); + memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size); + writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER); + + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); + wait_for_completion(&mb5_transfer.work); + + if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) && + (mb5_transfer.ack.status == RC_SUCCESS)) + r = 0; + else + r = -EIO; + + mutex_unlock(&mb5_transfer.lock); + + return r; +} + +int db5500_prcmu_enable_dsipll(void) +{ + int i; + + /* Enable DSIPLL_RESETN resets */ + writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); + /* Unclamp DSIPLL in/out */ + writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); + /* Set DSI PLL FREQ */ + writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); + writel(PRCMU_DSI_PLLOUT_SEL_SETTING, + PRCM_DSI_PLLOUT_SEL); + /* Enable Escape clocks */ + writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); + + /* Start DSI PLL */ + writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); + /* Reset DSI PLL */ + writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); + for (i = 0; i < 10; i++) { + if ((readl(PRCM_PLLDSI_LOCKP) & + PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED) + break; + udelay(100); + } + /* Release DSIPLL_RESETN */ + writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); + return 0; +} + +int db5500_prcmu_disable_dsipll(void) +{ + /* Disable dsi pll */ + writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); + /* Disable escapeclock */ + writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); + return 0; +} + +int db5500_prcmu_set_display_clocks(void) +{ + /* HDMI and TVCLK Should be handled somewhere else */ + /* PLLDIV=8, PLLSW=2, CLKEN=1 */ + writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); + /* PLLDIV=14, PLLSW=2, CLKEN=1 */ + writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); + return 0; +} + +static void ack_dbb_wakeup(void) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + cpu_relax(); + + writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER); + writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); +} + +static inline void print_unknown_header_warning(u8 n, u8 header) +{ + pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n", + header, n); +} + +static bool read_mailbox_0(void) +{ + bool r; + u8 header; + + header = readb(PRCM_ACK_MB0_HEADER); + switch (header) { + case AMB0H_WAKE_UP: + r = true; + break; + default: + print_unknown_header_warning(0, header); + r = false; + break; + } + writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); + return r; +} + +static bool read_mailbox_1(void) +{ + writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_2(void) +{ + writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_3(void) +{ + writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_4(void) +{ + writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_5(void) +{ + u8 header; + + header = readb(PRCM_ACK_MB5_HEADER); + switch (header) { + case MB5H_I2C_READ: + memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4); + case MB5H_I2C_WRITE: + mb5_transfer.ack.header = header; + mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE); + complete(&mb5_transfer.work); + break; + default: + print_unknown_header_warning(5, header); + break; + } + writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_6(void) +{ + writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool read_mailbox_7(void) +{ + writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR); + return false; +} + +static bool (* const read_mailbox[NUM_MB])(void) = { + read_mailbox_0, + read_mailbox_1, + read_mailbox_2, + read_mailbox_3, + read_mailbox_4, + read_mailbox_5, + read_mailbox_6, + read_mailbox_7 +}; + +static irqreturn_t prcmu_irq_handler(int irq, void *data) +{ + u32 bits; + u8 n; + irqreturn_t r; + + bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); + if (unlikely(!bits)) + return IRQ_NONE; + + r = IRQ_HANDLED; + for (n = 0; bits; n++) { + if (bits & MBOX_BIT(n)) { + bits -= MBOX_BIT(n); + if (read_mailbox[n]()) + r = IRQ_WAKE_THREAD; + } + } + return r; +} + +static irqreturn_t prcmu_irq_thread_fn(int irq, void *data) +{ + ack_dbb_wakeup(); + return IRQ_HANDLED; +} + +void __init db5500_prcmu_early_init(void) +{ + tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE); + spin_lock_init(&mb0_transfer.lock); + mutex_init(&mb5_transfer.lock); + init_completion(&mb5_transfer.work); +} + +/** + * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic + * + */ +int __init db5500_prcmu_init(void) +{ + int r = 0; + + if (ux500_is_svp() || !cpu_is_u5500()) + return -ENODEV; + + /* Clean up the mailbox interrupts after pre-kernel code. */ + writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR); + + r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler, + prcmu_irq_thread_fn, 0, "prcmu", NULL); + if (r < 0) { + pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n"); + return -EBUSY; + } + return 0; +} + +arch_initcall(db5500_prcmu_init); diff --git a/drivers/mfd/db8500-prcmu-regs.h b/drivers/mfd/db8500-prcmu-regs.h new file mode 100644 index 00000000000..3bbf04d5804 --- /dev/null +++ b/drivers/mfd/db8500-prcmu-regs.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * Author: Sundar Iyer <sundar.iyer@stericsson.com> + * + * License Terms: GNU General Public License v2 + * + * PRCM Unit registers + */ +#ifndef __DB8500_PRCMU_REGS_H +#define __DB8500_PRCMU_REGS_H + +#include <linux/bitops.h> +#include <mach/hardware.h> + +#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) + +#define PRCM_ARM_PLLDIVPS 0x118 +#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5) +#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF + +#define PRCM_PLLARM_LOCKP 0x0A8 +#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1) + +#define PRCM_ARM_CHGCLKREQ 0x114 +#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0) + +#define PRCM_PLLARM_ENABLE 0x98 +#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0) +#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8) + +#define PRCM_ARMCLKFIX_MGT 0x0 +#define PRCM_A9_RESETN_CLR 0x1f4 +#define PRCM_A9_RESETN_SET 0x1f0 +#define PRCM_ARM_LS_CLAMP 0x30C +#define PRCM_SRAM_A9 0x308 + +/* ARM WFI Standby signal register */ +#define PRCM_ARM_WFI_STANDBY 0x130 +#define PRCM_IOCR 0x310 +#define PRCM_IOCR_IOFORCE BIT(0) + +/* CPU mailbox registers */ +#define PRCM_MBOX_CPU_VAL 0x0FC +#define PRCM_MBOX_CPU_SET 0x100 + +/* Dual A9 core interrupt management unit registers */ +#define PRCM_A9_MASK_REQ 0x328 +#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0) + +#define PRCM_A9_MASK_ACK 0x32C +#define PRCM_ARMITMSK31TO0 0x11C +#define PRCM_ARMITMSK63TO32 0x120 +#define PRCM_ARMITMSK95TO64 0x124 +#define PRCM_ARMITMSK127TO96 0x128 +#define PRCM_POWER_STATE_VAL 0x25C +#define PRCM_ARMITVAL31TO0 0x260 +#define PRCM_ARMITVAL63TO32 0x264 +#define PRCM_ARMITVAL95TO64 0x268 +#define PRCM_ARMITVAL127TO96 0x26C + +#define PRCM_HOSTACCESS_REQ 0x334 +#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0) + +#define PRCM_ARM_IT1_CLR 0x48C +#define PRCM_ARM_IT1_VAL 0x494 + +#define PRCM_ITSTATUS0 0x148 +#define PRCM_ITSTATUS1 0x150 +#define PRCM_ITSTATUS2 0x158 +#define PRCM_ITSTATUS3 0x160 +#define PRCM_ITSTATUS4 0x168 +#define PRCM_ITSTATUS5 0x484 +#define PRCM_ITCLEAR5 0x488 +#define PRCM_ARMIT_MASKXP70_IT 0x1018 + +/* System reset register */ +#define PRCM_APE_SOFTRST 0x228 + +/* Level shifter and clamp control registers */ +#define PRCM_MMIP_LS_CLAMP_SET 0x420 +#define PRCM_MMIP_LS_CLAMP_CLR 0x424 + +/* PRCMU HW semaphore */ +#define PRCM_SEM 0x400 +#define PRCM_SEM_PRCM_SEM BIT(0) + +/* PRCMU clock/PLL/reset registers */ +#define PRCM_PLLDSI_FREQ 0x500 +#define PRCM_PLLDSI_ENABLE 0x504 +#define PRCM_PLLDSI_LOCKP 0x508 +#define PRCM_DSI_PLLOUT_SEL 0x530 +#define PRCM_DSITVCLK_DIV 0x52C +#define PRCM_APE_RESETN_SET 0x1E4 +#define PRCM_APE_RESETN_CLR 0x1E8 + +#define PRCM_TCR 0x1C8 +#define PRCM_TCR_TENSEL_MASK BITS(0, 7) +#define PRCM_TCR_STOP_TIMERS BIT(16) +#define PRCM_TCR_DOZE_MODE BIT(17) + +#define PRCM_CLKOCR 0x1CC +#define PRCM_CLKOCR_CLKODIV0_SHIFT 0 +#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) +#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 +#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) +#define PRCM_CLKOCR_CLKODIV1_SHIFT 16 +#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) +#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 +#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) +#define PRCM_CLKOCR_CLK1TYPE BIT(28) + +#define PRCM_SGACLK_MGT 0x014 +#define PRCM_UARTCLK_MGT 0x018 +#define PRCM_MSP02CLK_MGT 0x01C +#define PRCM_MSP1CLK_MGT 0x288 +#define PRCM_I2CCLK_MGT 0x020 +#define PRCM_SDMMCCLK_MGT 0x024 +#define PRCM_SLIMCLK_MGT 0x028 +#define PRCM_PER1CLK_MGT 0x02C +#define PRCM_PER2CLK_MGT 0x030 +#define PRCM_PER3CLK_MGT 0x034 +#define PRCM_PER5CLK_MGT 0x038 +#define PRCM_PER6CLK_MGT 0x03C +#define PRCM_PER7CLK_MGT 0x040 +#define PRCM_LCDCLK_MGT 0x044 +#define PRCM_BMLCLK_MGT 0x04C +#define PRCM_HSITXCLK_MGT 0x050 +#define PRCM_HSIRXCLK_MGT 0x054 +#define PRCM_HDMICLK_MGT 0x058 +#define PRCM_APEATCLK_MGT 0x05C +#define PRCM_APETRACECLK_MGT 0x060 +#define PRCM_MCDECLK_MGT 0x064 +#define PRCM_IPI2CCLK_MGT 0x068 +#define PRCM_DSIALTCLK_MGT 0x06C +#define PRCM_DMACLK_MGT 0x074 +#define PRCM_B2R2CLK_MGT 0x078 +#define PRCM_TVCLK_MGT 0x07C +#define PRCM_UNIPROCLK_MGT 0x278 +#define PRCM_SSPCLK_MGT 0x280 +#define PRCM_RNGCLK_MGT 0x284 +#define PRCM_UICCCLK_MGT 0x27C + +#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) +#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) +#define PRCM_CLK_MGT_CLKEN BIT(8) + +/* ePOD and memory power signal control registers */ +#define PRCM_EPOD_C_SET 0x410 +#define PRCM_SRAM_LS_SLEEP 0x304 + +/* Debug power control unit registers */ +#define PRCM_POWER_STATE_SET 0x254 + +/* Miscellaneous unit registers */ +#define PRCM_DSI_SW_RESET 0x324 +#define PRCM_GPIOCR 0x138 + +/* GPIOCR register */ +#define PRCM_GPIOCR_SPI2_SELECT BIT(23) + +#define PRCM_DDR_SUBSYS_APE_MINBW 0x438 + +#endif /* __DB8500_PRCMU_REGS_H */ diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c new file mode 100644 index 00000000000..e63782107e2 --- /dev/null +++ b/drivers/mfd/db8500-prcmu.c @@ -0,0 +1,2069 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * Author: Sundar Iyer <sundar.iyer@stericsson.com> + * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> + * + * U8500 PRCM Unit interface driver + * + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/completion.h> +#include <linux/irq.h> +#include <linux/jiffies.h> +#include <linux/bitops.h> +#include <linux/fs.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> +#include <linux/mfd/core.h> +#include <linux/mfd/db8500-prcmu.h> +#include <linux/regulator/db8500-prcmu.h> +#include <linux/regulator/machine.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/db8500-regs.h> +#include <mach/id.h> +#include "db8500-prcmu-regs.h" + +/* Offset for the firmware version within the TCPM */ +#define PRCMU_FW_VERSION_OFFSET 0xA4 + +/* PRCMU project numbers, defined by PRCMU FW */ +#define PRCMU_PROJECT_ID_8500V1_0 1 +#define PRCMU_PROJECT_ID_8500V2_0 2 +#define PRCMU_PROJECT_ID_8400V2_0 3 + +/* Index of different voltages to be used when accessing AVSData */ +#define PRCM_AVS_BASE 0x2FC +#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) +#define PRCM_AVS_VBB_MAX_OPP (PRCM_AVS_BASE + 0x1) +#define PRCM_AVS_VBB_100_OPP (PRCM_AVS_BASE + 0x2) +#define PRCM_AVS_VBB_50_OPP (PRCM_AVS_BASE + 0x3) +#define PRCM_AVS_VARM_MAX_OPP (PRCM_AVS_BASE + 0x4) +#define PRCM_AVS_VARM_100_OPP (PRCM_AVS_BASE + 0x5) +#define PRCM_AVS_VARM_50_OPP (PRCM_AVS_BASE + 0x6) +#define PRCM_AVS_VARM_RET (PRCM_AVS_BASE + 0x7) +#define PRCM_AVS_VAPE_100_OPP (PRCM_AVS_BASE + 0x8) +#define PRCM_AVS_VAPE_50_OPP (PRCM_AVS_BASE + 0x9) +#define PRCM_AVS_VMOD_100_OPP (PRCM_AVS_BASE + 0xA) +#define PRCM_AVS_VMOD_50_OPP (PRCM_AVS_BASE + 0xB) +#define PRCM_AVS_VSAFE (PRCM_AVS_BASE + 0xC) + +#define PRCM_AVS_VOLTAGE 0 +#define PRCM_AVS_VOLTAGE_MASK 0x3f +#define PRCM_AVS_ISSLOWSTARTUP 6 +#define PRCM_AVS_ISSLOWSTARTUP_MASK (1 << PRCM_AVS_ISSLOWSTARTUP) +#define PRCM_AVS_ISMODEENABLE 7 +#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE) + +#define PRCM_BOOT_STATUS 0xFFF +#define PRCM_ROMCODE_A2P 0xFFE +#define PRCM_ROMCODE_P2A 0xFFD +#define PRCM_XP70_CUR_PWR_STATE 0xFFC /* 4 BYTES */ + +#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */ + +#define _PRCM_MBOX_HEADER 0xFE8 /* 16 bytes */ +#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0) +#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1) +#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2) +#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3) +#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4) +#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5) +#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8) + +/* Req Mailboxes */ +#define PRCM_REQ_MB0 0xFDC /* 12 bytes */ +#define PRCM_REQ_MB1 0xFD0 /* 12 bytes */ +#define PRCM_REQ_MB2 0xFC0 /* 16 bytes */ +#define PRCM_REQ_MB3 0xE4C /* 372 bytes */ +#define PRCM_REQ_MB4 0xE48 /* 4 bytes */ +#define PRCM_REQ_MB5 0xE44 /* 4 bytes */ + +/* Ack Mailboxes */ +#define PRCM_ACK_MB0 0xE08 /* 52 bytes */ +#define PRCM_ACK_MB1 0xE04 /* 4 bytes */ +#define PRCM_ACK_MB2 0xE00 /* 4 bytes */ +#define PRCM_ACK_MB3 0xDFC /* 4 bytes */ +#define PRCM_ACK_MB4 0xDF8 /* 4 bytes */ +#define PRCM_ACK_MB5 0xDF4 /* 4 bytes */ + +/* Mailbox 0 headers */ +#define MB0H_POWER_STATE_TRANS 0 +#define MB0H_CONFIG_WAKEUPS_EXE 1 +#define MB0H_READ_WAKEUP_ACK 3 +#define MB0H_CONFIG_WAKEUPS_SLEEP 4 + +#define MB0H_WAKEUP_EXE 2 +#define MB0H_WAKEUP_SLEEP 5 + +/* Mailbox 0 REQs */ +#define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0) +#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x1) +#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x2) +#define PRCM_REQ_MB0_DO_NOT_WFI (PRCM_REQ_MB0 + 0x3) +#define PRCM_REQ_MB0_WAKEUP_8500 (PRCM_REQ_MB0 + 0x4) +#define PRCM_REQ_MB0_WAKEUP_4500 (PRCM_REQ_MB0 + 0x8) + +/* Mailbox 0 ACKs */ +#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS (PRCM_ACK_MB0 + 0x0) +#define PRCM_ACK_MB0_READ_POINTER (PRCM_ACK_MB0 + 0x1) +#define PRCM_ACK_MB0_WAKEUP_0_8500 (PRCM_ACK_MB0 + 0x4) +#define PRCM_ACK_MB0_WAKEUP_0_4500 (PRCM_ACK_MB0 + 0x8) +#define PRCM_ACK_MB0_WAKEUP_1_8500 (PRCM_ACK_MB0 + 0x1C) +#define PRCM_ACK_MB0_WAKEUP_1_4500 (PRCM_ACK_MB0 + 0x20) +#define PRCM_ACK_MB0_EVENT_4500_NUMBERS 20 + +/* Mailbox 1 headers */ +#define MB1H_ARM_APE_OPP 0x0 +#define MB1H_RESET_MODEM 0x2 +#define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 +#define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 +#define MB1H_RELEASE_USB_WAKEUP 0x5 + +/* Mailbox 1 Requests */ +#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) +#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) +#define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4) +#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8) + +/* Mailbox 1 ACKs */ +#define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) +#define PRCM_ACK_MB1_CURRENT_APE_OPP (PRCM_ACK_MB1 + 0x1) +#define PRCM_ACK_MB1_APE_VOLTAGE_STATUS (PRCM_ACK_MB1 + 0x2) +#define PRCM_ACK_MB1_DVFS_STATUS (PRCM_ACK_MB1 + 0x3) + +/* Mailbox 2 headers */ +#define MB2H_DPS 0x0 +#define MB2H_AUTO_PWR 0x1 + +/* Mailbox 2 REQs */ +#define PRCM_REQ_MB2_SVA_MMDSP (PRCM_REQ_MB2 + 0x0) +#define PRCM_REQ_MB2_SVA_PIPE (PRCM_REQ_MB2 + 0x1) +#define PRCM_REQ_MB2_SIA_MMDSP (PRCM_REQ_MB2 + 0x2) +#define PRCM_REQ_MB2_SIA_PIPE (PRCM_REQ_MB2 + 0x3) +#define PRCM_REQ_MB2_SGA (PRCM_REQ_MB2 + 0x4) +#define PRCM_REQ_MB2_B2R2_MCDE (PRCM_REQ_MB2 + 0x5) +#define PRCM_REQ_MB2_ESRAM12 (PRCM_REQ_MB2 + 0x6) +#define PRCM_REQ_MB2_ESRAM34 (PRCM_REQ_MB2 + 0x7) +#define PRCM_REQ_MB2_AUTO_PM_SLEEP (PRCM_REQ_MB2 + 0x8) +#define PRCM_REQ_MB2_AUTO_PM_IDLE (PRCM_REQ_MB2 + 0xC) + +/* Mailbox 2 ACKs */ +#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0) +#define HWACC_PWR_ST_OK 0xFE + +/* Mailbox 3 headers */ +#define MB3H_ANC 0x0 +#define MB3H_SIDETONE 0x1 +#define MB3H_SYSCLK 0xE + +/* Mailbox 3 Requests */ +#define PRCM_REQ_MB3_ANC_FIR_COEFF (PRCM_REQ_MB3 + 0x0) +#define PRCM_REQ_MB3_ANC_IIR_COEFF (PRCM_REQ_MB3 + 0x20) +#define PRCM_REQ_MB3_ANC_SHIFTER (PRCM_REQ_MB3 + 0x60) +#define PRCM_REQ_MB3_ANC_WARP (PRCM_REQ_MB3 + 0x64) +#define PRCM_REQ_MB3_SIDETONE_FIR_GAIN (PRCM_REQ_MB3 + 0x68) +#define PRCM_REQ_MB3_SIDETONE_FIR_COEFF (PRCM_REQ_MB3 + 0x6C) +#define PRCM_REQ_MB3_SYSCLK_MGT (PRCM_REQ_MB3 + 0x16C) + +/* Mailbox 4 headers */ +#define MB4H_DDR_INIT 0x0 +#define MB4H_MEM_ST 0x1 +#define MB4H_HOTDOG 0x12 +#define MB4H_HOTMON 0x13 +#define MB4H_HOT_PERIOD 0x14 + +/* Mailbox 4 Requests */ +#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) +#define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE (PRCM_REQ_MB4 + 0x1) +#define PRCM_REQ_MB4_ESRAM0_ST (PRCM_REQ_MB4 + 0x3) +#define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 0x0) +#define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 0x0) +#define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 0x1) +#define PRCM_REQ_MB4_HOTMON_CONFIG (PRCM_REQ_MB4 + 0x2) +#define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) +#define HOTMON_CONFIG_LOW BIT(0) +#define HOTMON_CONFIG_HIGH BIT(1) + +/* Mailbox 5 Requests */ +#define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) +#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1) +#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2) +#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3) +#define PRCMU_I2C_WRITE(slave) \ + (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) +#define PRCMU_I2C_READ(slave) \ + (((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0)) +#define PRCMU_I2C_STOP_EN BIT(3) + +/* Mailbox 5 ACKs */ +#define PRCM_ACK_MB5_I2C_STATUS (PRCM_ACK_MB5 + 0x1) +#define PRCM_ACK_MB5_I2C_VAL (PRCM_ACK_MB5 + 0x3) +#define I2C_WR_OK 0x1 +#define I2C_RD_OK 0x2 + +#define NUM_MB 8 +#define MBOX_BIT BIT +#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1) + +/* + * Wakeups/IRQs + */ + +#define WAKEUP_BIT_RTC BIT(0) +#define WAKEUP_BIT_RTT0 BIT(1) +#define WAKEUP_BIT_RTT1 BIT(2) +#define WAKEUP_BIT_HSI0 BIT(3) +#define WAKEUP_BIT_HSI1 BIT(4) +#define WAKEUP_BIT_CA_WAKE BIT(5) +#define WAKEUP_BIT_USB BIT(6) +#define WAKEUP_BIT_ABB BIT(7) +#define WAKEUP_BIT_ABB_FIFO BIT(8) +#define WAKEUP_BIT_SYSCLK_OK BIT(9) +#define WAKEUP_BIT_CA_SLEEP BIT(10) +#define WAKEUP_BIT_AC_WAKE_ACK BIT(11) +#define WAKEUP_BIT_SIDE_TONE_OK BIT(12) +#define WAKEUP_BIT_ANC_OK BIT(13) +#define WAKEUP_BIT_SW_ERROR BIT(14) +#define WAKEUP_BIT_AC_SLEEP_ACK BIT(15) +#define WAKEUP_BIT_ARM BIT(17) +#define WAKEUP_BIT_HOTMON_LOW BIT(18) +#define WAKEUP_BIT_HOTMON_HIGH BIT(19) +#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20) +#define WAKEUP_BIT_GPIO0 BIT(23) +#define WAKEUP_BIT_GPIO1 BIT(24) +#define WAKEUP_BIT_GPIO2 BIT(25) +#define WAKEUP_BIT_GPIO3 BIT(26) +#define WAKEUP_BIT_GPIO4 BIT(27) +#define WAKEUP_BIT_GPIO5 BIT(28) +#define WAKEUP_BIT_GPIO6 BIT(29) +#define WAKEUP_BIT_GPIO7 BIT(30) +#define WAKEUP_BIT_GPIO8 BIT(31) + +/* + * This vector maps irq numbers to the bits in the bit field used in + * communication with the PRCMU firmware. + * + * The reason for having this is to keep the irq numbers contiguous even though + * the bits in the bit field are not. (The bits also have a tendency to move + * around, to further complicate matters.) + */ +#define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name) - IRQ_PRCMU_BASE) +#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name) +static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = { + IRQ_ENTRY(RTC), + IRQ_ENTRY(RTT0), + IRQ_ENTRY(RTT1), + IRQ_ENTRY(HSI0), + IRQ_ENTRY(HSI1), + IRQ_ENTRY(CA_WAKE), + IRQ_ENTRY(USB), + IRQ_ENTRY(ABB), + IRQ_ENTRY(ABB_FIFO), + IRQ_ENTRY(CA_SLEEP), + IRQ_ENTRY(ARM), + IRQ_ENTRY(HOTMON_LOW), + IRQ_ENTRY(HOTMON_HIGH), + IRQ_ENTRY(MODEM_SW_RESET_REQ), + IRQ_ENTRY(GPIO0), + IRQ_ENTRY(GPIO1), + IRQ_ENTRY(GPIO2), + IRQ_ENTRY(GPIO3), + IRQ_ENTRY(GPIO4), + IRQ_ENTRY(GPIO5), + IRQ_ENTRY(GPIO6), + IRQ_ENTRY(GPIO7), + IRQ_ENTRY(GPIO8) +}; + +#define VALID_WAKEUPS (BIT(NUM_PRCMU_WAKEUP_INDICES) - 1) +#define WAKEUP_ENTRY(_name)[PRCMU_WAKEUP_INDEX_##_name] = (WAKEUP_BIT_##_name) +static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = { + WAKEUP_ENTRY(RTC), + WAKEUP_ENTRY(RTT0), + WAKEUP_ENTRY(RTT1), + WAKEUP_ENTRY(HSI0), + WAKEUP_ENTRY(HSI1), + WAKEUP_ENTRY(USB), + WAKEUP_ENTRY(ABB), + WAKEUP_ENTRY(ABB_FIFO), + WAKEUP_ENTRY(ARM) +}; + +/* + * mb0_transfer - state needed for mailbox 0 communication. + * @lock: The transaction lock. + * @dbb_events_lock: A lock used to handle concurrent access to (parts of) + * the request data. + * @mask_work: Work structure used for (un)masking wakeup interrupts. + * @req: Request data that need to persist between requests. + */ +static struct { + spinlock_t lock; + spinlock_t dbb_irqs_lock; + struct work_struct mask_work; + struct mutex ac_wake_lock; + struct completion ac_wake_work; + struct { + u32 dbb_irqs; + u32 dbb_wakeups; + u32 abb_events; + } req; +} mb0_transfer; + +/* + * mb1_transfer - state needed for mailbox 1 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @ack: Reply ("acknowledge") data. + */ +static struct { + struct mutex lock; + struct completion work; + struct { + u8 header; + u8 arm_opp; + u8 ape_opp; + u8 ape_voltage_status; + } ack; +} mb1_transfer; + +/* + * mb2_transfer - state needed for mailbox 2 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @auto_pm_lock: The autonomous power management configuration lock. + * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled. + * @req: Request data that need to persist between requests. + * @ack: Reply ("acknowledge") data. + */ +static struct { + struct mutex lock; + struct completion work; + spinlock_t auto_pm_lock; + bool auto_pm_enabled; + struct { + u8 status; + } ack; +} mb2_transfer; + +/* + * mb3_transfer - state needed for mailbox 3 communication. + * @lock: The request lock. + * @sysclk_lock: A lock used to handle concurrent sysclk requests. + * @sysclk_work: Work structure used for sysclk requests. + */ +static struct { + spinlock_t lock; + struct mutex sysclk_lock; + struct completion sysclk_work; +} mb3_transfer; + +/* + * mb4_transfer - state needed for mailbox 4 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + */ +static struct { + struct mutex lock; + struct completion work; +} mb4_transfer; + +/* + * mb5_transfer - state needed for mailbox 5 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @ack: Reply ("acknowledge") data. + */ +static struct { + struct mutex lock; + struct completion work; + struct { + u8 status; + u8 value; + } ack; +} mb5_transfer; + +static atomic_t ac_wake_req_state = ATOMIC_INIT(0); + +/* Spinlocks */ +static DEFINE_SPINLOCK(clkout_lock); +static DEFINE_SPINLOCK(gpiocr_lock); + +/* Global var to runtime determine TCDM base for v2 or v1 */ +static __iomem void *tcdm_base; + +struct clk_mgt { + unsigned int offset; + u32 pllsw; +}; + +static DEFINE_SPINLOCK(clk_mgt_lock); + +#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 } +struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { + CLK_MGT_ENTRY(SGACLK), + CLK_MGT_ENTRY(UARTCLK), + CLK_MGT_ENTRY(MSP02CLK), + CLK_MGT_ENTRY(MSP1CLK), + CLK_MGT_ENTRY(I2CCLK), + CLK_MGT_ENTRY(SDMMCCLK), + CLK_MGT_ENTRY(SLIMCLK), + CLK_MGT_ENTRY(PER1CLK), + CLK_MGT_ENTRY(PER2CLK), + CLK_MGT_ENTRY(PER3CLK), + CLK_MGT_ENTRY(PER5CLK), + CLK_MGT_ENTRY(PER6CLK), + CLK_MGT_ENTRY(PER7CLK), + CLK_MGT_ENTRY(LCDCLK), + CLK_MGT_ENTRY(BMLCLK), + CLK_MGT_ENTRY(HSITXCLK), + CLK_MGT_ENTRY(HSIRXCLK), + CLK_MGT_ENTRY(HDMICLK), + CLK_MGT_ENTRY(APEATCLK), + CLK_MGT_ENTRY(APETRACECLK), + CLK_MGT_ENTRY(MCDECLK), + CLK_MGT_ENTRY(IPI2CCLK), + CLK_MGT_ENTRY(DSIALTCLK), + CLK_MGT_ENTRY(DMACLK), + CLK_MGT_ENTRY(B2R2CLK), + CLK_MGT_ENTRY(TVCLK), + CLK_MGT_ENTRY(SSPCLK), + CLK_MGT_ENTRY(RNGCLK), + CLK_MGT_ENTRY(UICCCLK), +}; + +/* +* Used by MCDE to setup all necessary PRCMU registers +*/ +#define PRCMU_RESET_DSIPLL 0x00004000 +#define PRCMU_UNCLAMP_DSIPLL 0x00400800 + +#define PRCMU_CLK_PLL_DIV_SHIFT 0 +#define PRCMU_CLK_PLL_SW_SHIFT 5 +#define PRCMU_CLK_38 (1 << 9) +#define PRCMU_CLK_38_SRC (1 << 10) +#define PRCMU_CLK_38_DIV (1 << 11) + +/* PLLDIV=12, PLLSW=4 (PLLDDR) */ +#define PRCMU_DSI_CLOCK_SETTING 0x0000008C + +/* PLLDIV=8, PLLSW=4 (PLLDDR) */ +#define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088 + +/* DPI 50000000 Hz */ +#define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ + (16 << PRCMU_CLK_PLL_DIV_SHIFT)) +#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000E00 + +/* D=101, N=1, R=4, SELDIV2=0 */ +#define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 + +/* D=70, N=1, R=3, SELDIV2=0 */ +#define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146 + +#define PRCMU_ENABLE_PLLDSI 0x00000001 +#define PRCMU_DISABLE_PLLDSI 0x00000000 +#define PRCMU_RELEASE_RESET_DSS 0x0000400C +#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 +/* ESC clk, div0=1, div1=1, div2=3 */ +#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x07030101 +#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00030101 +#define PRCMU_DSI_RESET_SW 0x00000007 + +#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 + +static struct { + u8 project_number; + u8 api_version; + u8 func_version; + u8 errata; +} prcmu_version; + + +int prcmu_enable_dsipll(void) +{ + int i; + unsigned int plldsifreq; + + /* Clear DSIPLL_RESETN */ + writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR)); + /* Unclamp DSIPLL in/out */ + writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR)); + + if (prcmu_is_u8400()) + plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; + else + plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; + /* Set DSI PLL FREQ */ + writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ)); + writel(PRCMU_DSI_PLLOUT_SEL_SETTING, + (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL)); + /* Enable Escape clocks */ + writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, + (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); + + /* Start DSI PLL */ + writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); + /* Reset DSI PLL */ + writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET)); + for (i = 0; i < 10; i++) { + if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & + PRCMU_PLLDSI_LOCKP_LOCKED) + == PRCMU_PLLDSI_LOCKP_LOCKED) + break; + udelay(100); + } + /* Set DSIPLL_RESETN */ + writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); + return 0; +} + +int prcmu_disable_dsipll(void) +{ + /* Disable dsi pll */ + writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); + /* Disable escapeclock */ + writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, + (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); + return 0; +} + +int prcmu_set_display_clocks(void) +{ + unsigned long flags; + unsigned int dsiclk; + + if (prcmu_is_u8400()) + dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400; + else + dsiclk = PRCMU_DSI_CLOCK_SETTING; + + spin_lock_irqsave(&clk_mgt_lock, flags); + + /* Grab the HW semaphore. */ + while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + cpu_relax(); + + writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT)); + writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT)); + writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT)); + + /* Release the HW semaphore. */ + writel(0, (_PRCMU_BASE + PRCM_SEM)); + + spin_unlock_irqrestore(&clk_mgt_lock, flags); + + return 0; +} + +/** + * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. + */ +void prcmu_enable_spi2(void) +{ + u32 reg; + unsigned long flags; + + spin_lock_irqsave(&gpiocr_lock, flags); + reg = readl(_PRCMU_BASE + PRCM_GPIOCR); + writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); + spin_unlock_irqrestore(&gpiocr_lock, flags); +} + +/** + * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. + */ +void prcmu_disable_spi2(void) +{ + u32 reg; + unsigned long flags; + + spin_lock_irqsave(&gpiocr_lock, flags); + reg = readl(_PRCMU_BASE + PRCM_GPIOCR); + writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); + spin_unlock_irqrestore(&gpiocr_lock, flags); +} + +bool prcmu_has_arm_maxopp(void) +{ + return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & + PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; +} + +bool prcmu_is_u8400(void) +{ + return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0; +} + +/** + * prcmu_get_boot_status - PRCMU boot status checking + * Returns: the current PRCMU boot status + */ +int prcmu_get_boot_status(void) +{ + return readb(tcdm_base + PRCM_BOOT_STATUS); +} + +/** + * prcmu_set_rc_a2p - This function is used to run few power state sequences + * @val: Value to be set, i.e. transition requested + * Returns: 0 on success, -EINVAL on invalid argument + * + * This function is used to run the following power state sequences - + * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep + */ +int prcmu_set_rc_a2p(enum romcode_write val) +{ + if (val < RDY_2_DS || val > RDY_2_XP70_RST) + return -EINVAL; + writeb(val, (tcdm_base + PRCM_ROMCODE_A2P)); + return 0; +} + +/** + * prcmu_get_rc_p2a - This function is used to get power state sequences + * Returns: the power transition that has last happened + * + * This function can return the following transitions- + * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep + */ +enum romcode_read prcmu_get_rc_p2a(void) +{ + return readb(tcdm_base + PRCM_ROMCODE_P2A); +} + +/** + * prcmu_get_current_mode - Return the current XP70 power mode + * Returns: Returns the current AP(ARM) power mode: init, + * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset + */ +enum ap_pwrst prcmu_get_xp70_current_state(void) +{ + return readb(tcdm_base + PRCM_XP70_CUR_PWR_STATE); +} + +/** + * prcmu_config_clkout - Configure one of the programmable clock outputs. + * @clkout: The CLKOUT number (0 or 1). + * @source: The clock to be used (one of the PRCMU_CLKSRC_*). + * @div: The divider to be applied. + * + * Configures one of the programmable clock outputs (CLKOUTs). + * @div should be in the range [1,63] to request a configuration, or 0 to + * inform that the configuration is no longer requested. + */ +int prcmu_config_clkout(u8 clkout, u8 source, u8 div) +{ + static int requests[2]; + int r = 0; + unsigned long flags; + u32 val; + u32 bits; + u32 mask; + u32 div_mask; + + BUG_ON(clkout > 1); + BUG_ON(div > 63); + BUG_ON((clkout == 0) && (source > PRCMU_CLKSRC_CLK009)); + + if (!div && !requests[clkout]) + return -EINVAL; + + switch (clkout) { + case 0: + div_mask = PRCM_CLKOCR_CLKODIV0_MASK; + mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK); + bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) | + (div << PRCM_CLKOCR_CLKODIV0_SHIFT)); + break; + case 1: + div_mask = PRCM_CLKOCR_CLKODIV1_MASK; + mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK | + PRCM_CLKOCR_CLK1TYPE); + bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) | + (div << PRCM_CLKOCR_CLKODIV1_SHIFT)); + break; + } + bits &= mask; + + spin_lock_irqsave(&clkout_lock, flags); + + val = readl(_PRCMU_BASE + PRCM_CLKOCR); + if (val & div_mask) { + if (div) { + if ((val & mask) != bits) { + r = -EBUSY; + goto unlock_and_return; + } + } else { + if ((val & mask & ~div_mask) != bits) { + r = -EINVAL; + goto unlock_and_return; + } + } + } + writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR)); + requests[clkout] += (div ? 1 : -1); + +unlock_and_return: + spin_unlock_irqrestore(&clkout_lock, flags); + + return r; +} + +int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) +{ + unsigned long flags; + + BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state)); + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + cpu_relax(); + + writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); + writeb(state, (tcdm_base + PRCM_REQ_MB0_AP_POWER_STATE)); + writeb((keep_ap_pll ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_AP_PLL_STATE)); + writeb((keep_ulp_clk ? 1 : 0), + (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); + writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); + writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); + + return 0; +} + +/* This function should only be called while mb0_transfer.lock is held. */ +static void config_wakeups(void) +{ + const u8 header[2] = { + MB0H_CONFIG_WAKEUPS_EXE, + MB0H_CONFIG_WAKEUPS_SLEEP + }; + static u32 last_dbb_events; + static u32 last_abb_events; + u32 dbb_events; + u32 abb_events; + unsigned int i; + + dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups; + dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK); + + abb_events = mb0_transfer.req.abb_events; + + if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events)) + return; + + for (i = 0; i < 2; i++) { + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + cpu_relax(); + writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); + writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); + writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); + writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + } + last_dbb_events = dbb_events; + last_abb_events = abb_events; +} + +void prcmu_enable_wakeups(u32 wakeups) +{ + unsigned long flags; + u32 bits; + int i; + + BUG_ON(wakeups != (wakeups & VALID_WAKEUPS)); + + for (i = 0, bits = 0; i < NUM_PRCMU_WAKEUP_INDICES; i++) { + if (wakeups & BIT(i)) + bits |= prcmu_wakeup_bit[i]; + } + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + mb0_transfer.req.dbb_wakeups = bits; + config_wakeups(); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); +} + +void prcmu_config_abb_event_readout(u32 abb_events) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + mb0_transfer.req.abb_events = abb_events; + config_wakeups(); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); +} + +void prcmu_get_abb_event_buffer(void __iomem **buf) +{ + if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) + *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500); + else + *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_0_4500); +} + +/** + * prcmu_set_arm_opp - set the appropriate ARM OPP + * @opp: The new ARM operating point to which transition is to be made + * Returns: 0 on success, non-zero on failure + * + * This function sets the the operating point of the ARM. + */ +int prcmu_set_arm_opp(u8 opp) +{ + int r; + + if (opp < ARM_NO_CHANGE || opp > ARM_EXTCLK) + return -EINVAL; + + r = 0; + + mutex_lock(&mb1_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); + writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); + + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb1_transfer.work); + + if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || + (mb1_transfer.ack.arm_opp != opp)) + r = -EIO; + + mutex_unlock(&mb1_transfer.lock); + + return r; +} + +/** + * prcmu_get_arm_opp - get the current ARM OPP + * + * Returns: the current ARM OPP + */ +int prcmu_get_arm_opp(void) +{ + return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); +} + +/** + * prcmu_get_ddr_opp - get the current DDR OPP + * + * Returns: the current DDR OPP + */ +int prcmu_get_ddr_opp(void) +{ + return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); +} + +/** + * set_ddr_opp - set the appropriate DDR OPP + * @opp: The new DDR operating point to which transition is to be made + * Returns: 0 on success, non-zero on failure + * + * This function sets the operating point of the DDR. + */ +int prcmu_set_ddr_opp(u8 opp) +{ + if (opp < DDR_100_OPP || opp > DDR_25_OPP) + return -EINVAL; + /* Changing the DDR OPP can hang the hardware pre-v21 */ + if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) + writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW)); + + return 0; +} +/** + * set_ape_opp - set the appropriate APE OPP + * @opp: The new APE operating point to which transition is to be made + * Returns: 0 on success, non-zero on failure + * + * This function sets the operating point of the APE. + */ +int prcmu_set_ape_opp(u8 opp) +{ + int r = 0; + + mutex_lock(&mb1_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); + writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); + + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb1_transfer.work); + + if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || + (mb1_transfer.ack.ape_opp != opp)) + r = -EIO; + + mutex_unlock(&mb1_transfer.lock); + + return r; +} + +/** + * prcmu_get_ape_opp - get the current APE OPP + * + * Returns: the current APE OPP + */ +int prcmu_get_ape_opp(void) +{ + return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); +} + +/** + * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage + * @enable: true to request the higher voltage, false to drop a request. + * + * Calls to this function to enable and disable requests must be balanced. + */ +int prcmu_request_ape_opp_100_voltage(bool enable) +{ + int r = 0; + u8 header; + static unsigned int requests; + + mutex_lock(&mb1_transfer.lock); + + if (enable) { + if (0 != requests++) + goto unlock_and_return; + header = MB1H_REQUEST_APE_OPP_100_VOLT; + } else { + if (requests == 0) { + r = -EIO; + goto unlock_and_return; + } else if (1 != requests--) { + goto unlock_and_return; + } + header = MB1H_RELEASE_APE_OPP_100_VOLT; + } + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb1_transfer.work); + + if ((mb1_transfer.ack.header != header) || + ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0)) + r = -EIO; + +unlock_and_return: + mutex_unlock(&mb1_transfer.lock); + + return r; +} + +/** + * prcmu_release_usb_wakeup_state - release the state required by a USB wakeup + * + * This function releases the power state requirements of a USB wakeup. + */ +int prcmu_release_usb_wakeup_state(void) +{ + int r = 0; + + mutex_lock(&mb1_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(MB1H_RELEASE_USB_WAKEUP, + (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb1_transfer.work); + + if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || + ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0)) + r = -EIO; + + mutex_unlock(&mb1_transfer.lock); + + return r; +} + +/** + * prcmu_set_epod - set the state of a EPOD (power domain) + * @epod_id: The EPOD to set + * @epod_state: The new EPOD state + * + * This function sets the state of a EPOD (power domain). It may not be called + * from interrupt context. + */ +int prcmu_set_epod(u16 epod_id, u8 epod_state) +{ + int r = 0; + bool ram_retention = false; + int i; + + /* check argument */ + BUG_ON(epod_id >= NUM_EPOD_ID); + + /* set flag if retention is possible */ + switch (epod_id) { + case EPOD_ID_SVAMMDSP: + case EPOD_ID_SIAMMDSP: + case EPOD_ID_ESRAM12: + case EPOD_ID_ESRAM34: + ram_retention = true; + break; + } + + /* check argument */ + BUG_ON(epod_state > EPOD_STATE_ON); + BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention); + + /* get lock */ + mutex_lock(&mb2_transfer.lock); + + /* wait for mailbox */ + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) + cpu_relax(); + + /* fill in mailbox */ + for (i = 0; i < NUM_EPOD_ID; i++) + writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i)); + writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id)); + + writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); + + writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + /* + * The current firmware version does not handle errors correctly, + * and we cannot recover if there is an error. + * This is expected to change when the firmware is updated. + */ + if (!wait_for_completion_timeout(&mb2_transfer.work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + r = -EIO; + goto unlock_and_return; + } + + if (mb2_transfer.ack.status != HWACC_PWR_ST_OK) + r = -EIO; + +unlock_and_return: + mutex_unlock(&mb2_transfer.lock); + return r; +} + +/** + * prcmu_configure_auto_pm - Configure autonomous power management. + * @sleep: Configuration for ApSleep. + * @idle: Configuration for ApIdle. + */ +void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle) +{ + u32 sleep_cfg; + u32 idle_cfg; + unsigned long flags; + + BUG_ON((sleep == NULL) || (idle == NULL)); + + sleep_cfg = (sleep->sva_auto_pm_enable & 0xF); + sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_auto_pm_enable & 0xF)); + sleep_cfg = ((sleep_cfg << 8) | (sleep->sva_power_on & 0xFF)); + sleep_cfg = ((sleep_cfg << 8) | (sleep->sia_power_on & 0xFF)); + sleep_cfg = ((sleep_cfg << 4) | (sleep->sva_policy & 0xF)); + sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_policy & 0xF)); + + idle_cfg = (idle->sva_auto_pm_enable & 0xF); + idle_cfg = ((idle_cfg << 4) | (idle->sia_auto_pm_enable & 0xF)); + idle_cfg = ((idle_cfg << 8) | (idle->sva_power_on & 0xFF)); + idle_cfg = ((idle_cfg << 8) | (idle->sia_power_on & 0xFF)); + idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF)); + idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF)); + + spin_lock_irqsave(&mb2_transfer.auto_pm_lock, flags); + + /* + * The autonomous power management configuration is done through + * fields in mailbox 2, but these fields are only used as shared + * variables - i.e. there is no need to send a message. + */ + writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP)); + writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE)); + + mb2_transfer.auto_pm_enabled = + ((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) || + (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) || + (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) || + (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON)); + + spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags); +} +EXPORT_SYMBOL(prcmu_configure_auto_pm); + +bool prcmu_is_auto_pm_enabled(void) +{ + return mb2_transfer.auto_pm_enabled; +} + +static int request_sysclk(bool enable) +{ + int r; + unsigned long flags; + + r = 0; + + mutex_lock(&mb3_transfer.sysclk_lock); + + spin_lock_irqsave(&mb3_transfer.lock, flags); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) + cpu_relax(); + + writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); + + writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); + writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + spin_unlock_irqrestore(&mb3_transfer.lock, flags); + + /* + * The firmware only sends an ACK if we want to enable the + * SysClk, and it succeeds. + */ + if (enable && !wait_for_completion_timeout(&mb3_transfer.sysclk_work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + r = -EIO; + } + + mutex_unlock(&mb3_transfer.sysclk_lock); + + return r; +} + +static int request_timclk(bool enable) +{ + u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); + + if (!enable) + val |= PRCM_TCR_STOP_TIMERS; + writel(val, (_PRCMU_BASE + PRCM_TCR)); + + return 0; +} + +static int request_reg_clock(u8 clock, bool enable) +{ + u32 val; + unsigned long flags; + + spin_lock_irqsave(&clk_mgt_lock, flags); + + /* Grab the HW semaphore. */ + while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + cpu_relax(); + + val = readl(_PRCMU_BASE + clk_mgt[clock].offset); + if (enable) { + val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); + } else { + clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); + val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); + } + writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); + + /* Release the HW semaphore. */ + writel(0, (_PRCMU_BASE + PRCM_SEM)); + + spin_unlock_irqrestore(&clk_mgt_lock, flags); + + return 0; +} + +/** + * prcmu_request_clock() - Request for a clock to be enabled or disabled. + * @clock: The clock for which the request is made. + * @enable: Whether the clock should be enabled (true) or disabled (false). + * + * This function should only be used by the clock implementation. + * Do not use it from any other place! + */ +int prcmu_request_clock(u8 clock, bool enable) +{ + if (clock < PRCMU_NUM_REG_CLOCKS) + return request_reg_clock(clock, enable); + else if (clock == PRCMU_TIMCLK) + return request_timclk(enable); + else if (clock == PRCMU_SYSCLK) + return request_sysclk(enable); + else + return -EINVAL; +} + +int prcmu_config_esram0_deep_sleep(u8 state) +{ + if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || + (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) + return -EINVAL; + + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); + writeb(((DDR_PWR_STATE_OFFHIGHLAT << 4) | DDR_PWR_STATE_ON), + (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE)); + writeb(DDR_PWR_STATE_ON, + (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); + writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb4_transfer.work); + + mutex_unlock(&mb4_transfer.lock); + + return 0; +} + +int prcmu_config_hotdog(u8 threshold) +{ + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); + writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb4_transfer.work); + + mutex_unlock(&mb4_transfer.lock); + + return 0; +} + +int prcmu_config_hotmon(u8 low, u8 high) +{ + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); + writeb(high, (tcdm_base + PRCM_REQ_MB4_HOTMON_HIGH)); + writeb((HOTMON_CONFIG_LOW | HOTMON_CONFIG_HIGH), + (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); + writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb4_transfer.work); + + mutex_unlock(&mb4_transfer.lock); + + return 0; +} + +static int config_hot_period(u16 val) +{ + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); + writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb4_transfer.work); + + mutex_unlock(&mb4_transfer.lock); + + return 0; +} + +int prcmu_start_temp_sense(u16 cycles32k) +{ + if (cycles32k == 0xFFFF) + return -EINVAL; + + return config_hot_period(cycles32k); +} + +int prcmu_stop_temp_sense(void) +{ + return config_hot_period(0xFFFF); +} + +/** + * prcmu_set_clock_divider() - Configure the clock divider. + * @clock: The clock for which the request is made. + * @divider: The clock divider. (< 32) + * + * This function should only be used by the clock implementation. + * Do not use it from any other place! + */ +int prcmu_set_clock_divider(u8 clock, u8 divider) +{ + u32 val; + unsigned long flags; + + if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider)) + return -EINVAL; + + spin_lock_irqsave(&clk_mgt_lock, flags); + + /* Grab the HW semaphore. */ + while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + cpu_relax(); + + val = readl(_PRCMU_BASE + clk_mgt[clock].offset); + val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK); + val |= (u32)divider; + writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); + + /* Release the HW semaphore. */ + writel(0, (_PRCMU_BASE + PRCM_SEM)); + + spin_unlock_irqrestore(&clk_mgt_lock, flags); + + return 0; +} + +/** + * prcmu_abb_read() - Read register value(s) from the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The read out value(s). + * @size: The number of registers to read. + * + * Reads register value(s) from the ABB. + * @size has to be 1 for the current firmware version. + */ +int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if (size != 1) + return -EINVAL; + + mutex_lock(&mb5_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + + writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); + writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); + writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); + writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); + + writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + if (!wait_for_completion_timeout(&mb5_transfer.work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + r = -EIO; + } else { + r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO); + } + + if (!r) + *value = mb5_transfer.ack.value; + + mutex_unlock(&mb5_transfer.lock); + + return r; +} + +/** + * prcmu_abb_write() - Write register value(s) to the ABB. + * @slave: The I2C slave address. + * @reg: The (start) register address. + * @value: The value(s) to write. + * @size: The number of registers to write. + * + * Reads register value(s) from the ABB. + * @size has to be 1 for the current firmware version. + */ +int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + int r; + + if (size != 1) + return -EINVAL; + + mutex_lock(&mb5_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + cpu_relax(); + + writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); + writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); + writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); + writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); + + writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + if (!wait_for_completion_timeout(&mb5_transfer.work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + r = -EIO; + } else { + r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO); + } + + mutex_unlock(&mb5_transfer.lock); + + return r; +} + +/** + * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem + */ +void prcmu_ac_wake_req(void) +{ + u32 val; + + mutex_lock(&mb0_transfer.ac_wake_lock); + + val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) + goto unlock_and_return; + + atomic_set(&ac_wake_req_state, 1); + + writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), + (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + + if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + } + +unlock_and_return: + mutex_unlock(&mb0_transfer.ac_wake_lock); +} + +/** + * prcmu_ac_sleep_req - called when ARM no longer needs to talk to modem + */ +void prcmu_ac_sleep_req() +{ + u32 val; + + mutex_lock(&mb0_transfer.ac_wake_lock); + + val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) + goto unlock_and_return; + + writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), + (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + + if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, + msecs_to_jiffies(20000))) { + pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", + __func__); + } + + atomic_set(&ac_wake_req_state, 0); + +unlock_and_return: + mutex_unlock(&mb0_transfer.ac_wake_lock); +} + +bool prcmu_is_ac_wake_requested(void) +{ + return (atomic_read(&ac_wake_req_state) != 0); +} + +/** + * prcmu_system_reset - System reset + * + * Saves the reset reason code and then sets the APE_SOFRST register which + * fires interrupt to fw + */ +void prcmu_system_reset(u16 reset_code) +{ + writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); + writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST)); +} + +/** + * prcmu_reset_modem - ask the PRCMU to reset modem + */ +void prcmu_modem_reset(void) +{ + mutex_lock(&mb1_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb1_transfer.work); + + /* + * No need to check return from PRCMU as modem should go in reset state + * This state is already managed by upper layer + */ + + mutex_unlock(&mb1_transfer.lock); +} + +static void ack_dbb_wakeup(void) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + cpu_relax(); + + writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); + writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); +} + +static inline void print_unknown_header_warning(u8 n, u8 header) +{ + pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n", + header, n); +} + +static bool read_mailbox_0(void) +{ + bool r; + u32 ev; + unsigned int n; + u8 header; + + header = readb(tcdm_base + PRCM_MBOX_HEADER_ACK_MB0); + switch (header) { + case MB0H_WAKEUP_EXE: + case MB0H_WAKEUP_SLEEP: + if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) + ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_1_8500); + else + ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_0_8500); + + if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK)) + complete(&mb0_transfer.ac_wake_work); + if (ev & WAKEUP_BIT_SYSCLK_OK) + complete(&mb3_transfer.sysclk_work); + + ev &= mb0_transfer.req.dbb_irqs; + + for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { + if (ev & prcmu_irq_bit[n]) + generic_handle_irq(IRQ_PRCMU_BASE + n); + } + r = true; + break; + default: + print_unknown_header_warning(0, header); + r = false; + break; + } + writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + return r; +} + +static bool read_mailbox_1(void) +{ + mb1_transfer.ack.header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1); + mb1_transfer.ack.arm_opp = readb(tcdm_base + + PRCM_ACK_MB1_CURRENT_ARM_OPP); + mb1_transfer.ack.ape_opp = readb(tcdm_base + + PRCM_ACK_MB1_CURRENT_APE_OPP); + mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + + PRCM_ACK_MB1_APE_VOLTAGE_STATUS); + writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + complete(&mb1_transfer.work); + return false; +} + +static bool read_mailbox_2(void) +{ + mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); + writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + complete(&mb2_transfer.work); + return false; +} + +static bool read_mailbox_3(void) +{ + writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + return false; +} + +static bool read_mailbox_4(void) +{ + u8 header; + bool do_complete = true; + + header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4); + switch (header) { + case MB4H_MEM_ST: + case MB4H_HOTDOG: + case MB4H_HOTMON: + case MB4H_HOT_PERIOD: + break; + default: + print_unknown_header_warning(4, header); + do_complete = false; + break; + } + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + + if (do_complete) + complete(&mb4_transfer.work); + + return false; +} + +static bool read_mailbox_5(void) +{ + mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); + mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); + writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + complete(&mb5_transfer.work); + return false; +} + +static bool read_mailbox_6(void) +{ + writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + return false; +} + +static bool read_mailbox_7(void) +{ + writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + return false; +} + +static bool (* const read_mailbox[NUM_MB])(void) = { + read_mailbox_0, + read_mailbox_1, + read_mailbox_2, + read_mailbox_3, + read_mailbox_4, + read_mailbox_5, + read_mailbox_6, + read_mailbox_7 +}; + +static irqreturn_t prcmu_irq_handler(int irq, void *data) +{ + u32 bits; + u8 n; + irqreturn_t r; + + bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); + if (unlikely(!bits)) + return IRQ_NONE; + + r = IRQ_HANDLED; + for (n = 0; bits; n++) { + if (bits & MBOX_BIT(n)) { + bits -= MBOX_BIT(n); + if (read_mailbox[n]()) + r = IRQ_WAKE_THREAD; + } + } + return r; +} + +static irqreturn_t prcmu_irq_thread_fn(int irq, void *data) +{ + ack_dbb_wakeup(); + return IRQ_HANDLED; +} + +static void prcmu_mask_work(struct work_struct *work) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + config_wakeups(); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); +} + +static void prcmu_irq_mask(struct irq_data *d) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); + + mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; + + spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); + + if (d->irq != IRQ_PRCMU_CA_SLEEP) + schedule_work(&mb0_transfer.mask_work); +} + +static void prcmu_irq_unmask(struct irq_data *d) +{ + unsigned long flags; + + spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); + + mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; + + spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); + + if (d->irq != IRQ_PRCMU_CA_SLEEP) + schedule_work(&mb0_transfer.mask_work); +} + +static void noop(struct irq_data *d) +{ +} + +static struct irq_chip prcmu_irq_chip = { + .name = "prcmu", + .irq_disable = prcmu_irq_mask, + .irq_ack = noop, + .irq_mask = prcmu_irq_mask, + .irq_unmask = prcmu_irq_unmask, +}; + +void __init prcmu_early_init(void) +{ + unsigned int i; + + if (cpu_is_u8500v1()) { + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1); + } else if (cpu_is_u8500v2()) { + void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); + + if (tcpm_base != NULL) { + int version; + version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); + prcmu_version.project_number = version & 0xFF; + prcmu_version.api_version = (version >> 8) & 0xFF; + prcmu_version.func_version = (version >> 16) & 0xFF; + prcmu_version.errata = (version >> 24) & 0xFF; + pr_info("PRCMU firmware version %d.%d.%d\n", + (version >> 8) & 0xFF, (version >> 16) & 0xFF, + (version >> 24) & 0xFF); + iounmap(tcpm_base); + } + + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); + } else { + pr_err("prcmu: Unsupported chip version\n"); + BUG(); + } + + spin_lock_init(&mb0_transfer.lock); + spin_lock_init(&mb0_transfer.dbb_irqs_lock); + mutex_init(&mb0_transfer.ac_wake_lock); + init_completion(&mb0_transfer.ac_wake_work); + mutex_init(&mb1_transfer.lock); + init_completion(&mb1_transfer.work); + mutex_init(&mb2_transfer.lock); + init_completion(&mb2_transfer.work); + spin_lock_init(&mb2_transfer.auto_pm_lock); + spin_lock_init(&mb3_transfer.lock); + mutex_init(&mb3_transfer.sysclk_lock); + init_completion(&mb3_transfer.sysclk_work); + mutex_init(&mb4_transfer.lock); + init_completion(&mb4_transfer.work); + mutex_init(&mb5_transfer.lock); + init_completion(&mb5_transfer.work); + + INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); + + /* Initalize irqs. */ + for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) { + unsigned int irq; + + irq = IRQ_PRCMU_BASE + i; + irq_set_chip_and_handler(irq, &prcmu_irq_chip, + handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + } +} + +/* + * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC + */ +static struct regulator_consumer_supply db8500_vape_consumers[] = { + REGULATOR_SUPPLY("v-ape", NULL), + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"), + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"), + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"), + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"), + /* "v-mmc" changed to "vcore" in the mainline kernel */ + REGULATOR_SUPPLY("vcore", "sdi0"), + REGULATOR_SUPPLY("vcore", "sdi1"), + REGULATOR_SUPPLY("vcore", "sdi2"), + REGULATOR_SUPPLY("vcore", "sdi3"), + REGULATOR_SUPPLY("vcore", "sdi4"), + REGULATOR_SUPPLY("v-dma", "dma40.0"), + REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"), + /* "v-uart" changed to "vcore" in the mainline kernel */ + REGULATOR_SUPPLY("vcore", "uart0"), + REGULATOR_SUPPLY("vcore", "uart1"), + REGULATOR_SUPPLY("vcore", "uart2"), + REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), +}; + +static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { + /* CG2900 and CW1200 power to off-chip peripherals */ + REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), + REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"), + REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), + /* AV8100 regulator */ + REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), +}; + +static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { + REGULATOR_SUPPLY("vsupply", "b2r2.0"), + REGULATOR_SUPPLY("vsupply", "mcde.0"), +}; + +static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { + [DB8500_REGULATOR_VAPE] = { + .constraints = { + .name = "db8500-vape", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = db8500_vape_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers), + }, + [DB8500_REGULATOR_VARM] = { + .constraints = { + .name = "db8500-varm", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_VMODEM] = { + .constraints = { + .name = "db8500-vmodem", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_VPLL] = { + .constraints = { + .name = "db8500-vpll", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_VSMPS1] = { + .constraints = { + .name = "db8500-vsmps1", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_VSMPS2] = { + .constraints = { + .name = "db8500-vsmps2", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = db8500_vsmps2_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers), + }, + [DB8500_REGULATOR_VSMPS3] = { + .constraints = { + .name = "db8500-vsmps3", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_VRF1] = { + .constraints = { + .name = "db8500-vrf1", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-sva-mmdsp", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { + .constraints = { + /* "ret" means "retention" */ + .name = "db8500-sva-mmdsp-ret", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SVAPIPE] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-sva-pipe", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-sia-mmdsp", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { + .constraints = { + .name = "db8500-sia-mmdsp-ret", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SIAPIPE] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-sia-pipe", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_SGA] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-sga", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-b2r2-mcde", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = db8500_b2r2_mcde_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), + }, + [DB8500_REGULATOR_SWITCH_ESRAM12] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-esram12", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { + .constraints = { + .name = "db8500-esram12-ret", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_ESRAM34] = { + .supply_regulator = "db8500-vape", + .constraints = { + .name = "db8500-esram34", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, + [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { + .constraints = { + .name = "db8500-esram34-ret", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + }, +}; + +static struct mfd_cell db8500_prcmu_devs[] = { + { + .name = "db8500-prcmu-regulators", + .mfd_data = &db8500_regulators, + }, + { + .name = "cpufreq-u8500", + }, +}; + +/** + * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic + * + */ +static int __init db8500_prcmu_probe(struct platform_device *pdev) +{ + int err = 0; + + if (ux500_is_svp()) + return -ENODEV; + + /* Clean up the mailbox interrupts after pre-kernel code. */ + writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + + err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, + prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); + if (err < 0) { + pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n"); + err = -EBUSY; + goto no_irq_return; + } + + if (cpu_is_u8500v20_or_later()) + prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); + + err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, + ARRAY_SIZE(db8500_prcmu_devs), NULL, + 0); + + if (err) + pr_err("prcmu: Failed to add subdevices\n"); + else + pr_info("DB8500 PRCMU initialized\n"); + +no_irq_return: + return err; +} + +static struct platform_driver db8500_prcmu_driver = { + .driver = { + .name = "db8500-prcmu", + .owner = THIS_MODULE, + }, +}; + +static int __init db8500_prcmu_init(void) +{ + return platform_driver_probe(&db8500_prcmu_driver, db8500_prcmu_probe); +} + +arch_initcall(db8500_prcmu_init); + +MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>"); +MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c index 1e980fdd9d7..1e2af96fc29 100644 --- a/drivers/net/tile/tilepro.c +++ b/drivers/net/tile/tilepro.c @@ -1658,11 +1658,9 @@ static int tile_net_stop(struct net_device *dev) while (tile_net_lepp_free_comps(dev, true)) /* loop */; - /* Wipe the EPP queue. */ + /* Wipe the EPP queue, and wait till the stores hit the EPP. */ memset(priv->eq, 0, sizeof(lepp_queue_t)); - - /* Evict the EPP queue. */ - finv_buffer(priv->eq, EQ_SIZE); + mb(); return 0; } @@ -2398,7 +2396,7 @@ static void tile_net_cleanup(void) struct net_device *dev = tile_net_devs[i]; struct tile_net_priv *priv = netdev_priv(dev); unregister_netdev(dev); - finv_buffer(priv->eq, EQ_SIZE); + finv_buffer_remote(priv->eq, EQ_SIZE, 0); __free_pages(priv->eq_pages, EQ_ORDER); free_netdev(dev); } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b9f29e0d429..f0b13a0d185 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -274,6 +274,13 @@ config REGULATOR_AB8500 This driver supports the regulators found on the ST-Ericsson mixed signal AB8500 PMIC +config REGULATOR_DB8500_PRCMU + bool "ST-Ericsson DB8500 Voltage Domain Regulators" + depends on MFD_DB8500_PRCMU + help + This driver supports the voltage domain regulators controlled by the + DB8500 PRCMU + config REGULATOR_TPS6586X tristate "TI TPS6586X Power regulators" depends on MFD_TPS6586X diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d72a4275677..165ff5371e9 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -41,5 +41,6 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o +obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c new file mode 100644 index 00000000000..1089a961616 --- /dev/null +++ b/drivers/regulator/db8500-prcmu.c @@ -0,0 +1,558 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson + * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson + * + * Power domain regulators on DB8500 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/platform_device.h> +#include <linux/mfd/core.h> +#include <linux/mfd/db8500-prcmu.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/db8500-prcmu.h> + +/* + * power state reference count + */ +static int power_state_active_cnt; /* will initialize to zero */ +static DEFINE_SPINLOCK(power_state_active_lock); + +static void power_state_active_enable(void) +{ + unsigned long flags; + + spin_lock_irqsave(&power_state_active_lock, flags); + power_state_active_cnt++; + spin_unlock_irqrestore(&power_state_active_lock, flags); +} + +static int power_state_active_disable(void) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&power_state_active_lock, flags); + if (power_state_active_cnt <= 0) { + pr_err("power state: unbalanced enable/disable calls\n"); + ret = -EINVAL; + goto out; + } + + power_state_active_cnt--; +out: + spin_unlock_irqrestore(&power_state_active_lock, flags); + return ret; +} + +/* + * Exported interface for CPUIdle only. This function is called when interrupts + * are turned off. Hence, no locking. + */ +int power_state_active_is_enabled(void) +{ + return (power_state_active_cnt > 0); +} + +/** + * struct db8500_regulator_info - db8500 regulator information + * @dev: device pointer + * @desc: regulator description + * @rdev: regulator device pointer + * @is_enabled: status of the regulator + * @epod_id: id for EPOD (power domain) + * @is_ramret: RAM retention switch for EPOD (power domain) + * @operating_point: operating point (only for vape, to be removed) + * + */ +struct db8500_regulator_info { + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + bool is_enabled; + u16 epod_id; + bool is_ramret; + bool exclude_from_power_state; + unsigned int operating_point; +}; + +static int db8500_regulator_enable(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n", + info->desc.name); + + info->is_enabled = true; + if (!info->exclude_from_power_state) + power_state_active_enable(); + + return 0; +} + +static int db8500_regulator_disable(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + int ret = 0; + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n", + info->desc.name); + + info->is_enabled = false; + if (!info->exclude_from_power_state) + ret = power_state_active_disable(); + + return ret; +} + +static int db8500_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):" + " %i\n", info->desc.name, info->is_enabled); + + return info->is_enabled; +} + +/* db8500 regulator operations */ +static struct regulator_ops db8500_regulator_ops = { + .enable = db8500_regulator_enable, + .disable = db8500_regulator_disable, + .is_enabled = db8500_regulator_is_enabled, +}; + +/* + * EPOD control + */ +static bool epod_on[NUM_EPOD_ID]; +static bool epod_ramret[NUM_EPOD_ID]; + +static int enable_epod(u16 epod_id, bool ramret) +{ + int ret; + + if (ramret) { + if (!epod_on[epod_id]) { + ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET); + if (ret < 0) + return ret; + } + epod_ramret[epod_id] = true; + } else { + ret = prcmu_set_epod(epod_id, EPOD_STATE_ON); + if (ret < 0) + return ret; + epod_on[epod_id] = true; + } + + return 0; +} + +static int disable_epod(u16 epod_id, bool ramret) +{ + int ret; + + if (ramret) { + if (!epod_on[epod_id]) { + ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF); + if (ret < 0) + return ret; + } + epod_ramret[epod_id] = false; + } else { + if (epod_ramret[epod_id]) { + ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET); + if (ret < 0) + return ret; + } else { + ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF); + if (ret < 0) + return ret; + } + epod_on[epod_id] = false; + } + + return 0; +} + +/* + * Regulator switch + */ +static int db8500_regulator_switch_enable(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + int ret; + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n", + info->desc.name); + + ret = enable_epod(info->epod_id, info->is_ramret); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "regulator-switch-%s-enable: prcmu call failed\n", + info->desc.name); + goto out; + } + + info->is_enabled = true; +out: + return ret; +} + +static int db8500_regulator_switch_disable(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + int ret; + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n", + info->desc.name); + + ret = disable_epod(info->epod_id, info->is_ramret); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "regulator_switch-%s-disable: prcmu call failed\n", + info->desc.name); + goto out; + } + + info->is_enabled = 0; +out: + return ret; +} + +static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev) +{ + struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) + return -EINVAL; + + dev_vdbg(rdev_get_dev(rdev), + "regulator-switch-%s-is_enabled (is_enabled): %i\n", + info->desc.name, info->is_enabled); + + return info->is_enabled; +} + +static struct regulator_ops db8500_regulator_switch_ops = { + .enable = db8500_regulator_switch_enable, + .disable = db8500_regulator_switch_disable, + .is_enabled = db8500_regulator_switch_is_enabled, +}; + +/* + * Regulator information + */ +static struct db8500_regulator_info + db8500_regulator_info[DB8500_NUM_REGULATORS] = { + [DB8500_REGULATOR_VAPE] = { + .desc = { + .name = "db8500-vape", + .id = DB8500_REGULATOR_VAPE, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VARM] = { + .desc = { + .name = "db8500-varm", + .id = DB8500_REGULATOR_VARM, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VMODEM] = { + .desc = { + .name = "db8500-vmodem", + .id = DB8500_REGULATOR_VMODEM, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VPLL] = { + .desc = { + .name = "db8500-vpll", + .id = DB8500_REGULATOR_VPLL, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VSMPS1] = { + .desc = { + .name = "db8500-vsmps1", + .id = DB8500_REGULATOR_VSMPS1, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VSMPS2] = { + .desc = { + .name = "db8500-vsmps2", + .id = DB8500_REGULATOR_VSMPS2, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .exclude_from_power_state = true, + }, + [DB8500_REGULATOR_VSMPS3] = { + .desc = { + .name = "db8500-vsmps3", + .id = DB8500_REGULATOR_VSMPS3, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_VRF1] = { + .desc = { + .name = "db8500-vrf1", + .id = DB8500_REGULATOR_VRF1, + .ops = &db8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + }, + [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { + .desc = { + .name = "db8500-sva-mmdsp", + .id = DB8500_REGULATOR_SWITCH_SVAMMDSP, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SVAMMDSP, + }, + [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { + .desc = { + .name = "db8500-sva-mmdsp-ret", + .id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SVAMMDSP, + .is_ramret = true, + }, + [DB8500_REGULATOR_SWITCH_SVAPIPE] = { + .desc = { + .name = "db8500-sva-pipe", + .id = DB8500_REGULATOR_SWITCH_SVAPIPE, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SVAPIPE, + }, + [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { + .desc = { + .name = "db8500-sia-mmdsp", + .id = DB8500_REGULATOR_SWITCH_SIAMMDSP, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SIAMMDSP, + }, + [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { + .desc = { + .name = "db8500-sia-mmdsp-ret", + .id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SIAMMDSP, + .is_ramret = true, + }, + [DB8500_REGULATOR_SWITCH_SIAPIPE] = { + .desc = { + .name = "db8500-sia-pipe", + .id = DB8500_REGULATOR_SWITCH_SIAPIPE, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SIAPIPE, + }, + [DB8500_REGULATOR_SWITCH_SGA] = { + .desc = { + .name = "db8500-sga", + .id = DB8500_REGULATOR_SWITCH_SGA, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_SGA, + }, + [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { + .desc = { + .name = "db8500-b2r2-mcde", + .id = DB8500_REGULATOR_SWITCH_B2R2_MCDE, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_B2R2_MCDE, + }, + [DB8500_REGULATOR_SWITCH_ESRAM12] = { + .desc = { + .name = "db8500-esram12", + .id = DB8500_REGULATOR_SWITCH_ESRAM12, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_ESRAM12, + .is_enabled = true, + }, + [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { + .desc = { + .name = "db8500-esram12-ret", + .id = DB8500_REGULATOR_SWITCH_ESRAM12RET, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_ESRAM12, + .is_ramret = true, + }, + [DB8500_REGULATOR_SWITCH_ESRAM34] = { + .desc = { + .name = "db8500-esram34", + .id = DB8500_REGULATOR_SWITCH_ESRAM34, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_ESRAM34, + .is_enabled = true, + }, + [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { + .desc = { + .name = "db8500-esram34-ret", + .id = DB8500_REGULATOR_SWITCH_ESRAM34RET, + .ops = &db8500_regulator_switch_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .epod_id = EPOD_ID_ESRAM34, + .is_ramret = true, + }, +}; + +static int __devinit db8500_regulator_probe(struct platform_device *pdev) +{ + struct regulator_init_data *db8500_init_data = mfd_get_data(pdev); + int i, err; + + /* register all regulators */ + for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { + struct db8500_regulator_info *info; + struct regulator_init_data *init_data = &db8500_init_data[i]; + + /* assign per-regulator data */ + info = &db8500_regulator_info[i]; + info->dev = &pdev->dev; + + /* register with the regulator framework */ + info->rdev = regulator_register(&info->desc, &pdev->dev, + init_data, info); + if (IS_ERR(info->rdev)) { + err = PTR_ERR(info->rdev); + dev_err(&pdev->dev, "failed to register %s: err %i\n", + info->desc.name, err); + + /* if failing, unregister all earlier regulators */ + i--; + while (i >= 0) { + info = &db8500_regulator_info[i]; + regulator_unregister(info->rdev); + i--; + } + return err; + } + + dev_dbg(rdev_get_dev(info->rdev), + "regulator-%s-probed\n", info->desc.name); + } + + return 0; +} + +static int __exit db8500_regulator_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { + struct db8500_regulator_info *info; + info = &db8500_regulator_info[i]; + + dev_vdbg(rdev_get_dev(info->rdev), + "regulator-%s-remove\n", info->desc.name); + + regulator_unregister(info->rdev); + } + + return 0; +} + +static struct platform_driver db8500_regulator_driver = { + .driver = { + .name = "db8500-prcmu-regulators", + .owner = THIS_MODULE, + }, + .probe = db8500_regulator_probe, + .remove = __exit_p(db8500_regulator_remove), +}; + +static int __init db8500_regulator_init(void) +{ + int ret; + + ret = platform_driver_register(&db8500_regulator_driver); + if (ret < 0) + return -ENODEV; + + return 0; +} + +static void __exit db8500_regulator_exit(void) +{ + platform_driver_unregister(&db8500_regulator_driver); +} + +arch_initcall(db8500_regulator_init); +module_exit(db8500_regulator_exit); + +MODULE_AUTHOR("STMicroelectronics/ST-Ericsson"); +MODULE_DESCRIPTION("DB8500 regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 42891726ea7..b8f4e9e66cd 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -992,4 +992,11 @@ config RTC_DRV_TEGRA This drive can also be built as a module. If so, the module will be called rtc-tegra. +config RTC_DRV_TILE + tristate "Tilera hypervisor RTC support" + depends on TILE + help + Enable support for the Linux driver side of the Tilera + hypervisor's real-time clock interface. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ca91c3c42e9..9574748d1c7 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o +obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c new file mode 100644 index 00000000000..eb65dafee66 --- /dev/null +++ b/drivers/rtc/rtc-tile.c @@ -0,0 +1,162 @@ +/* + * Copyright 2011 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Tilera-specific RTC driver. + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> + +/* Platform device pointer. */ +static struct platform_device *tile_rtc_platform_device; + +/* + * RTC read routine. Gets time info from RTC chip via hypervisor syscall. + */ +static int read_rtc_time(struct device *dev, struct rtc_time *tm) +{ + HV_RTCTime hvtm = hv_get_rtc(); + + tm->tm_sec = hvtm.tm_sec; + tm->tm_min = hvtm.tm_min; + tm->tm_hour = hvtm.tm_hour; + tm->tm_mday = hvtm.tm_mday; + tm->tm_mon = hvtm.tm_mon; + tm->tm_year = hvtm.tm_year; + tm->tm_wday = 0; + tm->tm_yday = 0; + tm->tm_isdst = 0; + + if (rtc_valid_tm(tm) < 0) + dev_warn(dev, "Read invalid date/time from RTC\n"); + + return 0; +} + +/* + * RTC write routine. Sends time info to hypervisor via syscall, to be + * written to RTC chip. + */ +static int set_rtc_time(struct device *dev, struct rtc_time *tm) +{ + HV_RTCTime hvtm; + + hvtm.tm_sec = tm->tm_sec; + hvtm.tm_min = tm->tm_min; + hvtm.tm_hour = tm->tm_hour; + hvtm.tm_mday = tm->tm_mday; + hvtm.tm_mon = tm->tm_mon; + hvtm.tm_year = tm->tm_year; + + hv_set_rtc(hvtm); + + return 0; +} + +/* + * RTC read/write ops. + */ +static const struct rtc_class_ops tile_rtc_ops = { + .read_time = read_rtc_time, + .set_time = set_rtc_time, +}; + +/* + * Device probe routine. + */ +static int __devinit tile_rtc_probe(struct platform_device *dev) +{ + struct rtc_device *rtc; + + rtc = rtc_device_register("tile", + &dev->dev, &tile_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + platform_set_drvdata(dev, rtc); + + return 0; +} + +/* + * Device cleanup routine. + */ +static int __devexit tile_rtc_remove(struct platform_device *dev) +{ + struct rtc_device *rtc = platform_get_drvdata(dev); + + if (rtc) + rtc_device_unregister(rtc); + + platform_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver tile_rtc_platform_driver = { + .driver = { + .name = "rtc-tile", + .owner = THIS_MODULE, + }, + .probe = tile_rtc_probe, + .remove = __devexit_p(tile_rtc_remove), +}; + +/* + * Driver init routine. + */ +static int __init tile_rtc_driver_init(void) +{ + int err; + + err = platform_driver_register(&tile_rtc_platform_driver); + if (err) + return err; + + tile_rtc_platform_device = platform_device_alloc("rtc-tile", 0); + if (tile_rtc_platform_device == NULL) { + err = -ENOMEM; + goto exit_driver_unregister; + } + + err = platform_device_add(tile_rtc_platform_device); + if (err) + goto exit_device_put; + + return 0; + +exit_device_put: + platform_device_put(tile_rtc_platform_device); + +exit_driver_unregister: + platform_driver_unregister(&tile_rtc_platform_driver); + return err; +} + +/* + * Driver cleanup routine. + */ +static void __exit tile_rtc_driver_exit(void) +{ + platform_driver_unregister(&tile_rtc_platform_driver); +} + +module_init(tile_rtc_driver_init); +module_exit(tile_rtc_driver_exit); + +MODULE_DESCRIPTION("Tilera-specific Real Time Clock Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rtc-tile"); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 95019c747cc..4778e270716 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -636,7 +636,7 @@ static int sr_probe(struct device *dev) disk->first_minor = minor; sprintf(disk->disk_name, "sr%d", minor); disk->fops = &sr_bdops; - disk->flags = GENHD_FL_CD; + disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST; blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); diff --git a/fs/9p/Kconfig b/fs/9p/Kconfig index 814ac4e213a..0a93dc1cb4a 100644 --- a/fs/9p/Kconfig +++ b/fs/9p/Kconfig @@ -1,6 +1,6 @@ config 9P_FS - tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" - depends on INET && NET_9P && EXPERIMENTAL + tristate "Plan 9 Resource Sharing Support (9P2000)" + depends on INET && NET_9P help If you say Y here, you will get experimental support for Plan 9 resource sharing via the 9P2000 protocol. @@ -10,7 +10,6 @@ config 9P_FS If unsure, say N. if 9P_FS - config 9P_FSCACHE bool "Enable 9P client caching support (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 82a7c38ddad..691c78f58be 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -259,7 +259,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); mutex_unlock(&v9inode->v_mutex); - goto error; + goto err_clunk_old_fid; } v9inode->writeback_fid = (void *) inode_fid; } @@ -267,8 +267,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, /* Since we are opening a file, assign the open fid to the file */ filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { - p9_client_clunk(ofid); - return PTR_ERR(filp); + err = PTR_ERR(filp); + goto err_clunk_old_fid; } filp->private_data = ofid; #ifdef CONFIG_9P_FSCACHE @@ -278,10 +278,11 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, return 0; error: - if (ofid) - p9_client_clunk(ofid); if (fid) p9_client_clunk(fid); +err_clunk_old_fid: + if (ofid) + p9_client_clunk(ofid); return err; } diff --git a/fs/block_dev.c b/fs/block_dev.c index bf9c7a72037..1f2b1997833 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1238,6 +1238,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) res = __blkdev_get(bdev, mode, 0); if (whole) { + struct gendisk *disk = whole->bd_disk; + /* finish claiming */ mutex_lock(&bdev->bd_mutex); spin_lock(&bdev_lock); @@ -1264,15 +1266,16 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) spin_unlock(&bdev_lock); /* - * Block event polling for write claims. Any write - * holder makes the write_holder state stick until all - * are released. This is good enough and tracking - * individual writeable reference is too fragile given - * the way @mode is used in blkdev_get/put(). + * Block event polling for write claims if requested. Any + * write holder makes the write_holder state stick until + * all are released. This is good enough and tracking + * individual writeable reference is too fragile given the + * way @mode is used in blkdev_get/put(). */ - if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { + if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) && + !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { bdev->bd_write_holder = true; - disk_block_events(bdev->bd_disk); + disk_block_events(disk); } mutex_unlock(&bdev->bd_mutex); diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 38b8ab55492..33da49dc3cc 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -848,7 +848,8 @@ get_more_pages: op->payload_len = cpu_to_le32(len); req->r_request->hdr.data_len = cpu_to_le32(len); - ceph_osdc_start_request(&fsc->client->osdc, req, true); + rc = ceph_osdc_start_request(&fsc->client->osdc, req, true); + BUG_ON(rc); req = NULL; /* continue? */ @@ -880,8 +881,6 @@ release_pvec_pages: out: if (req) ceph_osdc_put_request(req); - if (rc > 0) - rc = 0; /* vfs expects us to return 0 */ ceph_put_snap_context(snapc); dout("writepages done, rc = %d\n", rc); return rc; diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 2a5404c1c42..1f72b00447c 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -569,7 +569,8 @@ retry: list_add_tail(&cap->session_caps, &session->s_caps); session->s_nr_caps++; spin_unlock(&session->s_cap_lock); - } + } else if (new_cap) + ceph_put_cap(mdsc, new_cap); if (!ci->i_snap_realm) { /* @@ -2634,6 +2635,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, struct ceph_mds_session *session, int *open_target_sessions) { + struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; unsigned mseq = le32_to_cpu(ex->migrate_seq); @@ -2670,6 +2672,19 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, * export targets, so that we get the matching IMPORT */ *open_target_sessions = 1; + + /* + * we can't flush dirty caps that we've seen the + * EXPORT but no IMPORT for + */ + spin_lock(&mdsc->cap_dirty_lock); + if (!list_empty(&ci->i_dirty_item)) { + dout(" moving %p to cap_dirty_migrating\n", + inode); + list_move(&ci->i_dirty_item, + &mdsc->cap_dirty_migrating); + } + spin_unlock(&mdsc->cap_dirty_lock); } __ceph_remove_cap(cap); } @@ -2707,6 +2722,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, ci->i_cap_exporting_issued = 0; ci->i_cap_exporting_mseq = 0; ci->i_cap_exporting_mds = -1; + + spin_lock(&mdsc->cap_dirty_lock); + if (!list_empty(&ci->i_dirty_item)) { + dout(" moving %p back to cap_dirty\n", inode); + list_move(&ci->i_dirty_item, &mdsc->cap_dirty); + } + spin_unlock(&mdsc->cap_dirty_lock); } else { dout("handle_cap_import inode %p ci %p mds%d mseq %d\n", inode, ci, mds, mseq); @@ -2910,38 +2932,16 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc) */ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) { - struct ceph_inode_info *ci, *nci = NULL; - struct inode *inode, *ninode = NULL; - struct list_head *p, *n; + struct ceph_inode_info *ci; + struct inode *inode; dout("flush_dirty_caps\n"); spin_lock(&mdsc->cap_dirty_lock); - list_for_each_safe(p, n, &mdsc->cap_dirty) { - if (nci) { - ci = nci; - inode = ninode; - ci->i_ceph_flags &= ~CEPH_I_NOFLUSH; - dout("flush_dirty_caps inode %p (was next inode)\n", - inode); - } else { - ci = list_entry(p, struct ceph_inode_info, - i_dirty_item); - inode = igrab(&ci->vfs_inode); - BUG_ON(!inode); - dout("flush_dirty_caps inode %p\n", inode); - } - if (n != &mdsc->cap_dirty) { - nci = list_entry(n, struct ceph_inode_info, - i_dirty_item); - ninode = igrab(&nci->vfs_inode); - BUG_ON(!ninode); - nci->i_ceph_flags |= CEPH_I_NOFLUSH; - dout("flush_dirty_caps next inode %p, noflush\n", - ninode); - } else { - nci = NULL; - ninode = NULL; - } + while (!list_empty(&mdsc->cap_dirty)) { + ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info, + i_dirty_item); + inode = igrab(&ci->vfs_inode); + dout("flush_dirty_caps %p\n", inode); spin_unlock(&mdsc->cap_dirty_lock); if (inode) { ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, @@ -2951,6 +2951,7 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) spin_lock(&mdsc->cap_dirty_lock); } spin_unlock(&mdsc->cap_dirty_lock); + dout("flush_dirty_caps done\n"); } /* diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 1a867a3601a..33729e822bb 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -360,7 +360,7 @@ more: rinfo = &fi->last_readdir->r_reply_info; dout("readdir frag %x num %d off %d chunkoff %d\n", frag, rinfo->dir_nr, off, fi->offset); - while (off - fi->offset >= 0 && off - fi->offset < rinfo->dir_nr) { + while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { u64 pos = ceph_make_fpos(frag, off); struct ceph_mds_reply_inode *in = rinfo->dir_in[off - fi->offset].in; @@ -1066,16 +1066,17 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size, struct inode *inode = file->f_dentry->d_inode; struct ceph_inode_info *ci = ceph_inode(inode); int left; + const int bufsize = 1024; if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT)) return -EISDIR; if (!cf->dir_info) { - cf->dir_info = kmalloc(1024, GFP_NOFS); + cf->dir_info = kmalloc(bufsize, GFP_NOFS); if (!cf->dir_info) return -ENOMEM; cf->dir_info_len = - sprintf(cf->dir_info, + snprintf(cf->dir_info, bufsize, "entries: %20lld\n" " files: %20lld\n" " subdirs: %20lld\n" diff --git a/fs/ceph/export.c b/fs/ceph/export.c index e41056174bf..a610d3d6748 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -86,6 +86,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, static struct dentry *__fh_to_dentry(struct super_block *sb, struct ceph_nfs_fh *fh) { + struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; struct dentry *dentry; struct ceph_vino vino; @@ -95,8 +96,24 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, vino.ino = fh->ino; vino.snap = CEPH_NOSNAP; inode = ceph_find_inode(sb, vino); - if (!inode) - return ERR_PTR(-ESTALE); + if (!inode) { + struct ceph_mds_request *req; + + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO, + USE_ANY_MDS); + if (IS_ERR(req)) + return ERR_CAST(req); + + req->r_ino1 = vino; + req->r_num_caps = 1; + err = ceph_mdsc_do_request(mdsc, NULL, req); + inode = req->r_target_inode; + if (inode) + igrab(inode); + ceph_mdsc_put_request(req); + if (!inode) + return ERR_PTR(-ESTALE); + } dentry = d_obtain_alias(inode); if (IS_ERR(dentry)) { @@ -148,8 +165,10 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, snprintf(req->r_path2, 16, "%d", cfh->parent_name_hash); req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, NULL, req); + inode = req->r_target_inode; + if (inode) + igrab(inode); ceph_mdsc_put_request(req); - inode = ceph_find_inode(sb, vino); if (!inode) return ERR_PTR(err ? err : -ESTALE); } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index d0fae4ce9ba..79743d146be 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -578,6 +578,7 @@ static void __register_request(struct ceph_mds_client *mdsc, if (dir) { struct ceph_inode_info *ci = ceph_inode(dir); + ihold(dir); spin_lock(&ci->i_unsafe_lock); req->r_unsafe_dir = dir; list_add_tail(&req->r_unsafe_dir_item, &ci->i_unsafe_dirops); @@ -598,6 +599,9 @@ static void __unregister_request(struct ceph_mds_client *mdsc, spin_lock(&ci->i_unsafe_lock); list_del_init(&req->r_unsafe_dir_item); spin_unlock(&ci->i_unsafe_lock); + + iput(req->r_unsafe_dir); + req->r_unsafe_dir = NULL; } ceph_mdsc_put_request(req); @@ -2691,7 +2695,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, { struct super_block *sb = mdsc->fsc->sb; struct inode *inode; - struct ceph_inode_info *ci; struct dentry *parent, *dentry; struct ceph_dentry_info *di; int mds = session->s_mds; @@ -2728,7 +2731,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, dout("handle_lease no inode %llx\n", vino.ino); goto release; } - ci = ceph_inode(inode); /* dentry */ parent = d_find_alias(inode); @@ -3002,6 +3004,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) spin_lock_init(&mdsc->snap_flush_lock); mdsc->cap_flush_seq = 0; INIT_LIST_HEAD(&mdsc->cap_dirty); + INIT_LIST_HEAD(&mdsc->cap_dirty_migrating); mdsc->num_cap_flushing = 0; spin_lock_init(&mdsc->cap_dirty_lock); init_waitqueue_head(&mdsc->cap_flushing_wq); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 4e3a9cc0bba..7d8a0d662d5 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -278,6 +278,7 @@ struct ceph_mds_client { u64 cap_flush_seq; struct list_head cap_dirty; /* inodes with dirty caps */ + struct list_head cap_dirty_migrating; /* ...that are migration... */ int num_cap_flushing; /* # caps we are flushing */ spinlock_t cap_dirty_lock; /* protects above items */ wait_queue_head_t cap_flushing_wq; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index d545e97d99c..8ed4d343319 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -255,7 +255,11 @@ ssize_t part_discard_alignment_show(struct device *dev, struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); - return sprintf(buf, "%u\n", p->discard_alignment); + struct gendisk *disk = dev_to_disk(dev); + + return sprintf(buf, "%u\n", + queue_limit_discard_alignment(&disk->queue->limits, + p->start_sect)); } ssize_t part_stat_show(struct device *dev, @@ -449,8 +453,6 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, p->start_sect = start; p->alignment_offset = queue_limit_alignment_offset(&disk->queue->limits, start); - p->discard_alignment = - queue_limit_discard_alignment(&disk->queue->limits, start); p->nr_sects = len; p->partno = partno; p->policy = get_disk_ro(disk); diff --git a/fs/splice.c b/fs/splice.c index 50a5d978da1..aa866d30969 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -162,6 +162,14 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = { .get = generic_pipe_buf_get, }; +static void wakeup_pipe_readers(struct pipe_inode_info *pipe) +{ + smp_mb(); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible(&pipe->wait); + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); +} + /** * splice_to_pipe - fill passed data into a pipe * @pipe: pipe to fill @@ -247,12 +255,8 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, pipe_unlock(pipe); - if (do_wakeup) { - smp_mb(); - if (waitqueue_active(&pipe->wait)) - wake_up_interruptible(&pipe->wait); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); - } + if (do_wakeup) + wakeup_pipe_readers(pipe); while (page_nr < spd_pages) spd->spd_release(spd, page_nr++); @@ -1892,12 +1896,9 @@ retry: /* * If we put data in the output pipe, wakeup any potential readers. */ - if (ret > 0) { - smp_mb(); - if (waitqueue_active(&opipe->wait)) - wake_up_interruptible(&opipe->wait); - kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN); - } + if (ret > 0) + wakeup_pipe_readers(opipe); + if (input_wakeup) wakeup_pipe_writers(ipipe); @@ -1976,12 +1977,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, /* * If we put data in the output pipe, wakeup any potential readers. */ - if (ret > 0) { - smp_mb(); - if (waitqueue_active(&opipe->wait)) - wake_up_interruptible(&opipe->wait); - kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN); - } + if (ret > 0) + wakeup_pipe_readers(opipe); return ret; } diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h index bcbab3e4a3b..89b73e5d0fd 100644 --- a/include/asm-generic/audit_change_attr.h +++ b/include/asm-generic/audit_change_attr.h @@ -1,4 +1,6 @@ +#ifdef __NR_chmod __NR_chmod, +#endif __NR_fchmod, #ifdef __NR_chown __NR_chown, @@ -20,7 +22,9 @@ __NR_chown32, __NR_fchown32, __NR_lchown32, #endif +#ifdef __NR_link __NR_link, +#endif #ifdef __NR_linkat __NR_linkat, #endif diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h index 6621bd82cbe..7b61db4fe72 100644 --- a/include/asm-generic/audit_dir_write.h +++ b/include/asm-generic/audit_dir_write.h @@ -1,13 +1,27 @@ +#ifdef __NR_rename __NR_rename, +#endif +#ifdef __NR_mkdir __NR_mkdir, +#endif +#ifdef __NR_rmdir __NR_rmdir, +#endif #ifdef __NR_creat __NR_creat, #endif +#ifdef __NR_link __NR_link, +#endif +#ifdef __NR_unlink __NR_unlink, +#endif +#ifdef __NR_symlink __NR_symlink, +#endif +#ifdef __NR_mknod __NR_mknod, +#endif #ifdef __NR_mkdirat __NR_mkdirat, __NR_mknodat, diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h index 0e87464d984..3b249cb857d 100644 --- a/include/asm-generic/audit_read.h +++ b/include/asm-generic/audit_read.h @@ -1,4 +1,6 @@ +#ifdef __NR_readlink __NR_readlink, +#endif __NR_quotactl, __NR_listxattr, __NR_llistxattr, @@ -6,3 +8,6 @@ __NR_flistxattr, __NR_getxattr, __NR_lgetxattr, __NR_fgetxattr, +#ifdef __NR_readlinkat +__NR_readlinkat, +#endif diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h index c5f1c2c920e..e7020c57b13 100644 --- a/include/asm-generic/audit_write.h +++ b/include/asm-generic/audit_write.h @@ -4,7 +4,9 @@ __NR_acct, __NR_swapon, #endif __NR_quotactl, +#ifdef __NR_truncate __NR_truncate, +#endif #ifdef __NR_truncate64 __NR_truncate64, #endif diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index 07c40d5149d..33d52470488 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -24,16 +24,24 @@ #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64) #endif +#ifdef __SYSCALL_COMPAT +#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _comp) +#define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp) +#else +#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys) +#define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64) +#endif + #define __NR_io_setup 0 -__SYSCALL(__NR_io_setup, sys_io_setup) +__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup) #define __NR_io_destroy 1 __SYSCALL(__NR_io_destroy, sys_io_destroy) #define __NR_io_submit 2 -__SYSCALL(__NR_io_submit, sys_io_submit) +__SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit) #define __NR_io_cancel 3 __SYSCALL(__NR_io_cancel, sys_io_cancel) #define __NR_io_getevents 4 -__SYSCALL(__NR_io_getevents, sys_io_getevents) +__SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents) /* fs/xattr.c */ #define __NR_setxattr 5 @@ -67,7 +75,7 @@ __SYSCALL(__NR_getcwd, sys_getcwd) /* fs/cookies.c */ #define __NR_lookup_dcookie 18 -__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) +__SC_COMP(__NR_lookup_dcookie, sys_lookup_dcookie, compat_sys_lookup_dcookie) /* fs/eventfd.c */ #define __NR_eventfd2 19 @@ -79,7 +87,7 @@ __SYSCALL(__NR_epoll_create1, sys_epoll_create1) #define __NR_epoll_ctl 21 __SYSCALL(__NR_epoll_ctl, sys_epoll_ctl) #define __NR_epoll_pwait 22 -__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait) +__SC_COMP(__NR_epoll_pwait, sys_epoll_pwait, compat_sys_epoll_pwait) /* fs/fcntl.c */ #define __NR_dup 23 @@ -87,7 +95,7 @@ __SYSCALL(__NR_dup, sys_dup) #define __NR_dup3 24 __SYSCALL(__NR_dup3, sys_dup3) #define __NR3264_fcntl 25 -__SC_3264(__NR3264_fcntl, sys_fcntl64, sys_fcntl) +__SC_COMP_3264(__NR3264_fcntl, sys_fcntl64, sys_fcntl, compat_sys_fcntl64) /* fs/inotify_user.c */ #define __NR_inotify_init1 26 @@ -99,7 +107,7 @@ __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) /* fs/ioctl.c */ #define __NR_ioctl 29 -__SYSCALL(__NR_ioctl, sys_ioctl) +__SC_COMP(__NR_ioctl, sys_ioctl, compat_sys_ioctl) /* fs/ioprio.c */ #define __NR_ioprio_set 30 @@ -129,26 +137,30 @@ __SYSCALL(__NR_renameat, sys_renameat) #define __NR_umount2 39 __SYSCALL(__NR_umount2, sys_umount) #define __NR_mount 40 -__SYSCALL(__NR_mount, sys_mount) +__SC_COMP(__NR_mount, sys_mount, compat_sys_mount) #define __NR_pivot_root 41 __SYSCALL(__NR_pivot_root, sys_pivot_root) /* fs/nfsctl.c */ #define __NR_nfsservctl 42 -__SYSCALL(__NR_nfsservctl, sys_nfsservctl) +__SC_COMP(__NR_nfsservctl, sys_nfsservctl, compat_sys_nfsservctl) /* fs/open.c */ #define __NR3264_statfs 43 -__SC_3264(__NR3264_statfs, sys_statfs64, sys_statfs) +__SC_COMP_3264(__NR3264_statfs, sys_statfs64, sys_statfs, \ + compat_sys_statfs64) #define __NR3264_fstatfs 44 -__SC_3264(__NR3264_fstatfs, sys_fstatfs64, sys_fstatfs) +__SC_COMP_3264(__NR3264_fstatfs, sys_fstatfs64, sys_fstatfs, \ + compat_sys_fstatfs64) #define __NR3264_truncate 45 -__SC_3264(__NR3264_truncate, sys_truncate64, sys_truncate) +__SC_COMP_3264(__NR3264_truncate, sys_truncate64, sys_truncate, \ + compat_sys_truncate64) #define __NR3264_ftruncate 46 -__SC_3264(__NR3264_ftruncate, sys_ftruncate64, sys_ftruncate) +__SC_COMP_3264(__NR3264_ftruncate, sys_ftruncate64, sys_ftruncate, \ + compat_sys_ftruncate64) #define __NR_fallocate 47 -__SYSCALL(__NR_fallocate, sys_fallocate) +__SC_COMP(__NR_fallocate, sys_fallocate, compat_sys_fallocate) #define __NR_faccessat 48 __SYSCALL(__NR_faccessat, sys_faccessat) #define __NR_chdir 49 @@ -166,7 +178,7 @@ __SYSCALL(__NR_fchownat, sys_fchownat) #define __NR_fchown 55 __SYSCALL(__NR_fchown, sys_fchown) #define __NR_openat 56 -__SYSCALL(__NR_openat, sys_openat) +__SC_COMP(__NR_openat, sys_openat, compat_sys_openat) #define __NR_close 57 __SYSCALL(__NR_close, sys_close) #define __NR_vhangup 58 @@ -182,7 +194,7 @@ __SYSCALL(__NR_quotactl, sys_quotactl) /* fs/readdir.c */ #define __NR_getdents64 61 -__SYSCALL(__NR_getdents64, sys_getdents64) +__SC_COMP(__NR_getdents64, sys_getdents64, compat_sys_getdents64) /* fs/read_write.c */ #define __NR3264_lseek 62 @@ -192,17 +204,17 @@ __SYSCALL(__NR_read, sys_read) #define __NR_write 64 __SYSCALL(__NR_write, sys_write) #define __NR_readv 65 -__SYSCALL(__NR_readv, sys_readv) +__SC_COMP(__NR_readv, sys_readv, compat_sys_readv) #define __NR_writev 66 -__SYSCALL(__NR_writev, sys_writev) +__SC_COMP(__NR_writev, sys_writev, compat_sys_writev) #define __NR_pread64 67 -__SYSCALL(__NR_pread64, sys_pread64) +__SC_COMP(__NR_pread64, sys_pread64, compat_sys_pread64) #define __NR_pwrite64 68 -__SYSCALL(__NR_pwrite64, sys_pwrite64) +__SC_COMP(__NR_pwrite64, sys_pwrite64, compat_sys_pwrite64) #define __NR_preadv 69 -__SYSCALL(__NR_preadv, sys_preadv) +__SC_COMP(__NR_preadv, sys_preadv, compat_sys_preadv) #define __NR_pwritev 70 -__SYSCALL(__NR_pwritev, sys_pwritev) +__SC_COMP(__NR_pwritev, sys_pwritev, compat_sys_pwritev) /* fs/sendfile.c */ #define __NR3264_sendfile 71 @@ -210,17 +222,17 @@ __SC_3264(__NR3264_sendfile, sys_sendfile64, sys_sendfile) /* fs/select.c */ #define __NR_pselect6 72 -__SYSCALL(__NR_pselect6, sys_pselect6) +__SC_COMP(__NR_pselect6, sys_pselect6, compat_sys_pselect6) #define __NR_ppoll 73 -__SYSCALL(__NR_ppoll, sys_ppoll) +__SC_COMP(__NR_ppoll, sys_ppoll, compat_sys_ppoll) /* fs/signalfd.c */ #define __NR_signalfd4 74 -__SYSCALL(__NR_signalfd4, sys_signalfd4) +__SC_COMP(__NR_signalfd4, sys_signalfd4, compat_sys_signalfd4) /* fs/splice.c */ #define __NR_vmsplice 75 -__SYSCALL(__NR_vmsplice, sys_vmsplice) +__SC_COMP(__NR_vmsplice, sys_vmsplice, compat_sys_vmsplice) #define __NR_splice 76 __SYSCALL(__NR_splice, sys_splice) #define __NR_tee 77 @@ -243,23 +255,27 @@ __SYSCALL(__NR_fsync, sys_fsync) __SYSCALL(__NR_fdatasync, sys_fdatasync) #ifdef __ARCH_WANT_SYNC_FILE_RANGE2 #define __NR_sync_file_range2 84 -__SYSCALL(__NR_sync_file_range2, sys_sync_file_range2) +__SC_COMP(__NR_sync_file_range2, sys_sync_file_range2, \ + compat_sys_sync_file_range2) #else #define __NR_sync_file_range 84 -__SYSCALL(__NR_sync_file_range, sys_sync_file_range) +__SC_COMP(__NR_sync_file_range, sys_sync_file_range, \ + compat_sys_sync_file_range) #endif /* fs/timerfd.c */ #define __NR_timerfd_create 85 __SYSCALL(__NR_timerfd_create, sys_timerfd_create) #define __NR_timerfd_settime 86 -__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) +__SC_COMP(__NR_timerfd_settime, sys_timerfd_settime, \ + compat_sys_timerfd_settime) #define __NR_timerfd_gettime 87 -__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) +__SC_COMP(__NR_timerfd_gettime, sys_timerfd_gettime, \ + compat_sys_timerfd_gettime) /* fs/utimes.c */ #define __NR_utimensat 88 -__SYSCALL(__NR_utimensat, sys_utimensat) +__SC_COMP(__NR_utimensat, sys_utimensat, compat_sys_utimensat) /* kernel/acct.c */ #define __NR_acct 89 @@ -281,7 +297,7 @@ __SYSCALL(__NR_exit, sys_exit) #define __NR_exit_group 94 __SYSCALL(__NR_exit_group, sys_exit_group) #define __NR_waitid 95 -__SYSCALL(__NR_waitid, sys_waitid) +__SC_COMP(__NR_waitid, sys_waitid, compat_sys_waitid) /* kernel/fork.c */ #define __NR_set_tid_address 96 @@ -291,25 +307,27 @@ __SYSCALL(__NR_unshare, sys_unshare) /* kernel/futex.c */ #define __NR_futex 98 -__SYSCALL(__NR_futex, sys_futex) +__SC_COMP(__NR_futex, sys_futex, compat_sys_futex) #define __NR_set_robust_list 99 -__SYSCALL(__NR_set_robust_list, sys_set_robust_list) +__SC_COMP(__NR_set_robust_list, sys_set_robust_list, \ + compat_sys_set_robust_list) #define __NR_get_robust_list 100 -__SYSCALL(__NR_get_robust_list, sys_get_robust_list) +__SC_COMP(__NR_get_robust_list, sys_get_robust_list, \ + compat_sys_get_robust_list) /* kernel/hrtimer.c */ #define __NR_nanosleep 101 -__SYSCALL(__NR_nanosleep, sys_nanosleep) +__SC_COMP(__NR_nanosleep, sys_nanosleep, compat_sys_nanosleep) /* kernel/itimer.c */ #define __NR_getitimer 102 -__SYSCALL(__NR_getitimer, sys_getitimer) +__SC_COMP(__NR_getitimer, sys_getitimer, compat_sys_getitimer) #define __NR_setitimer 103 -__SYSCALL(__NR_setitimer, sys_setitimer) +__SC_COMP(__NR_setitimer, sys_setitimer, compat_sys_setitimer) /* kernel/kexec.c */ #define __NR_kexec_load 104 -__SYSCALL(__NR_kexec_load, sys_kexec_load) +__SC_COMP(__NR_kexec_load, sys_kexec_load, compat_sys_kexec_load) /* kernel/module.c */ #define __NR_init_module 105 @@ -319,23 +337,24 @@ __SYSCALL(__NR_delete_module, sys_delete_module) /* kernel/posix-timers.c */ #define __NR_timer_create 107 -__SYSCALL(__NR_timer_create, sys_timer_create) +__SC_COMP(__NR_timer_create, sys_timer_create, compat_sys_timer_create) #define __NR_timer_gettime 108 -__SYSCALL(__NR_timer_gettime, sys_timer_gettime) +__SC_COMP(__NR_timer_gettime, sys_timer_gettime, compat_sys_timer_gettime) #define __NR_timer_getoverrun 109 __SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) #define __NR_timer_settime 110 -__SYSCALL(__NR_timer_settime, sys_timer_settime) +__SC_COMP(__NR_timer_settime, sys_timer_settime, compat_sys_timer_settime) #define __NR_timer_delete 111 __SYSCALL(__NR_timer_delete, sys_timer_delete) #define __NR_clock_settime 112 -__SYSCALL(__NR_clock_settime, sys_clock_settime) +__SC_COMP(__NR_clock_settime, sys_clock_settime, compat_sys_clock_settime) #define __NR_clock_gettime 113 -__SYSCALL(__NR_clock_gettime, sys_clock_gettime) +__SC_COMP(__NR_clock_gettime, sys_clock_gettime, compat_sys_clock_gettime) #define __NR_clock_getres 114 -__SYSCALL(__NR_clock_getres, sys_clock_getres) +__SC_COMP(__NR_clock_getres, sys_clock_getres, compat_sys_clock_getres) #define __NR_clock_nanosleep 115 -__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep) +__SC_COMP(__NR_clock_nanosleep, sys_clock_nanosleep, \ + compat_sys_clock_nanosleep) /* kernel/printk.c */ #define __NR_syslog 116 @@ -355,9 +374,11 @@ __SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler) #define __NR_sched_getparam 121 __SYSCALL(__NR_sched_getparam, sys_sched_getparam) #define __NR_sched_setaffinity 122 -__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity) +__SC_COMP(__NR_sched_setaffinity, sys_sched_setaffinity, \ + compat_sys_sched_setaffinity) #define __NR_sched_getaffinity 123 -__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity) +__SC_COMP(__NR_sched_getaffinity, sys_sched_getaffinity, \ + compat_sys_sched_getaffinity) #define __NR_sched_yield 124 __SYSCALL(__NR_sched_yield, sys_sched_yield) #define __NR_sched_get_priority_max 125 @@ -365,7 +386,8 @@ __SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) #define __NR_sched_get_priority_min 126 __SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) #define __NR_sched_rr_get_interval 127 -__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval) +__SC_COMP(__NR_sched_rr_get_interval, sys_sched_rr_get_interval, \ + compat_sys_sched_rr_get_interval) /* kernel/signal.c */ #define __NR_restart_syscall 128 @@ -377,21 +399,23 @@ __SYSCALL(__NR_tkill, sys_tkill) #define __NR_tgkill 131 __SYSCALL(__NR_tgkill, sys_tgkill) #define __NR_sigaltstack 132 -__SYSCALL(__NR_sigaltstack, sys_sigaltstack) +__SC_COMP(__NR_sigaltstack, sys_sigaltstack, compat_sys_sigaltstack) #define __NR_rt_sigsuspend 133 -__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend) /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ +__SC_COMP(__NR_rt_sigsuspend, sys_rt_sigsuspend, compat_sys_rt_sigsuspend) #define __NR_rt_sigaction 134 -__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction) /* __ARCH_WANT_SYS_RT_SIGACTION */ +__SC_COMP(__NR_rt_sigaction, sys_rt_sigaction, compat_sys_rt_sigaction) #define __NR_rt_sigprocmask 135 __SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask) #define __NR_rt_sigpending 136 __SYSCALL(__NR_rt_sigpending, sys_rt_sigpending) #define __NR_rt_sigtimedwait 137 -__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait) +__SC_COMP(__NR_rt_sigtimedwait, sys_rt_sigtimedwait, \ + compat_sys_rt_sigtimedwait) #define __NR_rt_sigqueueinfo 138 -__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo) +__SC_COMP(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo, \ + compat_sys_rt_sigqueueinfo) #define __NR_rt_sigreturn 139 -__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn) /* sys_rt_sigreturn_wrapper, */ +__SC_COMP(__NR_rt_sigreturn, sys_rt_sigreturn, compat_sys_rt_sigreturn) /* kernel/sys.c */ #define __NR_setpriority 140 @@ -421,7 +445,7 @@ __SYSCALL(__NR_setfsuid, sys_setfsuid) #define __NR_setfsgid 152 __SYSCALL(__NR_setfsgid, sys_setfsgid) #define __NR_times 153 -__SYSCALL(__NR_times, sys_times) +__SC_COMP(__NR_times, sys_times, compat_sys_times) #define __NR_setpgid 154 __SYSCALL(__NR_setpgid, sys_setpgid) #define __NR_getpgid 155 @@ -441,11 +465,11 @@ __SYSCALL(__NR_sethostname, sys_sethostname) #define __NR_setdomainname 162 __SYSCALL(__NR_setdomainname, sys_setdomainname) #define __NR_getrlimit 163 -__SYSCALL(__NR_getrlimit, sys_getrlimit) +__SC_COMP(__NR_getrlimit, sys_getrlimit, compat_sys_getrlimit) #define __NR_setrlimit 164 -__SYSCALL(__NR_setrlimit, sys_setrlimit) +__SC_COMP(__NR_setrlimit, sys_setrlimit, compat_sys_setrlimit) #define __NR_getrusage 165 -__SYSCALL(__NR_getrusage, sys_getrusage) +__SC_COMP(__NR_getrusage, sys_getrusage, compat_sys_getrusage) #define __NR_umask 166 __SYSCALL(__NR_umask, sys_umask) #define __NR_prctl 167 @@ -455,11 +479,11 @@ __SYSCALL(__NR_getcpu, sys_getcpu) /* kernel/time.c */ #define __NR_gettimeofday 169 -__SYSCALL(__NR_gettimeofday, sys_gettimeofday) +__SC_COMP(__NR_gettimeofday, sys_gettimeofday, compat_sys_gettimeofday) #define __NR_settimeofday 170 -__SYSCALL(__NR_settimeofday, sys_settimeofday) +__SC_COMP(__NR_settimeofday, sys_settimeofday, compat_sys_settimeofday) #define __NR_adjtimex 171 -__SYSCALL(__NR_adjtimex, sys_adjtimex) +__SC_COMP(__NR_adjtimex, sys_adjtimex, compat_sys_adjtimex) /* kernel/timer.c */ #define __NR_getpid 172 @@ -477,39 +501,40 @@ __SYSCALL(__NR_getegid, sys_getegid) #define __NR_gettid 178 __SYSCALL(__NR_gettid, sys_gettid) #define __NR_sysinfo 179 -__SYSCALL(__NR_sysinfo, sys_sysinfo) +__SC_COMP(__NR_sysinfo, sys_sysinfo, compat_sys_sysinfo) /* ipc/mqueue.c */ #define __NR_mq_open 180 -__SYSCALL(__NR_mq_open, sys_mq_open) +__SC_COMP(__NR_mq_open, sys_mq_open, compat_sys_mq_open) #define __NR_mq_unlink 181 __SYSCALL(__NR_mq_unlink, sys_mq_unlink) #define __NR_mq_timedsend 182 -__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend) +__SC_COMP(__NR_mq_timedsend, sys_mq_timedsend, compat_sys_mq_timedsend) #define __NR_mq_timedreceive 183 -__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive) +__SC_COMP(__NR_mq_timedreceive, sys_mq_timedreceive, \ + compat_sys_mq_timedreceive) #define __NR_mq_notify 184 -__SYSCALL(__NR_mq_notify, sys_mq_notify) +__SC_COMP(__NR_mq_notify, sys_mq_notify, compat_sys_mq_notify) #define __NR_mq_getsetattr 185 -__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr) +__SC_COMP(__NR_mq_getsetattr, sys_mq_getsetattr, compat_sys_mq_getsetattr) /* ipc/msg.c */ #define __NR_msgget 186 __SYSCALL(__NR_msgget, sys_msgget) #define __NR_msgctl 187 -__SYSCALL(__NR_msgctl, sys_msgctl) +__SC_COMP(__NR_msgctl, sys_msgctl, compat_sys_msgctl) #define __NR_msgrcv 188 -__SYSCALL(__NR_msgrcv, sys_msgrcv) +__SC_COMP(__NR_msgrcv, sys_msgrcv, compat_sys_msgrcv) #define __NR_msgsnd 189 -__SYSCALL(__NR_msgsnd, sys_msgsnd) +__SC_COMP(__NR_msgsnd, sys_msgsnd, compat_sys_msgsnd) /* ipc/sem.c */ #define __NR_semget 190 __SYSCALL(__NR_semget, sys_semget) #define __NR_semctl 191 -__SYSCALL(__NR_semctl, sys_semctl) +__SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl) #define __NR_semtimedop 192 -__SYSCALL(__NR_semtimedop, sys_semtimedop) +__SC_COMP(__NR_semtimedop, sys_semtimedop, compat_sys_semtimedop) #define __NR_semop 193 __SYSCALL(__NR_semop, sys_semop) @@ -517,9 +542,9 @@ __SYSCALL(__NR_semop, sys_semop) #define __NR_shmget 194 __SYSCALL(__NR_shmget, sys_shmget) #define __NR_shmctl 195 -__SYSCALL(__NR_shmctl, sys_shmctl) +__SC_COMP(__NR_shmctl, sys_shmctl, compat_sys_shmctl) #define __NR_shmat 196 -__SYSCALL(__NR_shmat, sys_shmat) +__SC_COMP(__NR_shmat, sys_shmat, compat_sys_shmat) #define __NR_shmdt 197 __SYSCALL(__NR_shmdt, sys_shmdt) @@ -543,21 +568,21 @@ __SYSCALL(__NR_getpeername, sys_getpeername) #define __NR_sendto 206 __SYSCALL(__NR_sendto, sys_sendto) #define __NR_recvfrom 207 -__SYSCALL(__NR_recvfrom, sys_recvfrom) +__SC_COMP(__NR_recvfrom, sys_recvfrom, compat_sys_recvfrom) #define __NR_setsockopt 208 -__SYSCALL(__NR_setsockopt, sys_setsockopt) +__SC_COMP(__NR_setsockopt, sys_setsockopt, compat_sys_setsockopt) #define __NR_getsockopt 209 -__SYSCALL(__NR_getsockopt, sys_getsockopt) +__SC_COMP(__NR_getsockopt, sys_getsockopt, compat_sys_getsockopt) #define __NR_shutdown 210 __SYSCALL(__NR_shutdown, sys_shutdown) #define __NR_sendmsg 211 -__SYSCALL(__NR_sendmsg, sys_sendmsg) +__SC_COMP(__NR_sendmsg, sys_sendmsg, compat_sys_sendmsg) #define __NR_recvmsg 212 -__SYSCALL(__NR_recvmsg, sys_recvmsg) +__SC_COMP(__NR_recvmsg, sys_recvmsg, compat_sys_recvmsg) /* mm/filemap.c */ #define __NR_readahead 213 -__SYSCALL(__NR_readahead, sys_readahead) +__SC_COMP(__NR_readahead, sys_readahead, compat_sys_readahead) /* mm/nommu.c, also with MMU */ #define __NR_brk 214 @@ -573,19 +598,19 @@ __SYSCALL(__NR_add_key, sys_add_key) #define __NR_request_key 218 __SYSCALL(__NR_request_key, sys_request_key) #define __NR_keyctl 219 -__SYSCALL(__NR_keyctl, sys_keyctl) +__SC_COMP(__NR_keyctl, sys_keyctl, compat_sys_keyctl) /* arch/example/kernel/sys_example.c */ #define __NR_clone 220 -__SYSCALL(__NR_clone, sys_clone) /* .long sys_clone_wrapper */ +__SYSCALL(__NR_clone, sys_clone) #define __NR_execve 221 -__SYSCALL(__NR_execve, sys_execve) /* .long sys_execve_wrapper */ +__SC_COMP(__NR_execve, sys_execve, compat_sys_execve) #define __NR3264_mmap 222 __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap) /* mm/fadvise.c */ #define __NR3264_fadvise64 223 -__SYSCALL(__NR3264_fadvise64, sys_fadvise64_64) +__SC_COMP(__NR3264_fadvise64, sys_fadvise64_64, compat_sys_fadvise64_64) /* mm/, CONFIG_MMU only */ #ifndef __ARCH_NOMMU @@ -612,25 +637,26 @@ __SYSCALL(__NR_madvise, sys_madvise) #define __NR_remap_file_pages 234 __SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) #define __NR_mbind 235 -__SYSCALL(__NR_mbind, sys_mbind) +__SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind) #define __NR_get_mempolicy 236 -__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) +__SC_COMP(__NR_get_mempolicy, sys_get_mempolicy, compat_sys_get_mempolicy) #define __NR_set_mempolicy 237 -__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) +__SC_COMP(__NR_set_mempolicy, sys_set_mempolicy, compat_sys_set_mempolicy) #define __NR_migrate_pages 238 -__SYSCALL(__NR_migrate_pages, sys_migrate_pages) +__SC_COMP(__NR_migrate_pages, sys_migrate_pages, compat_sys_migrate_pages) #define __NR_move_pages 239 -__SYSCALL(__NR_move_pages, sys_move_pages) +__SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages) #endif #define __NR_rt_tgsigqueueinfo 240 -__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) +__SC_COMP(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, \ + compat_sys_rt_tgsigqueueinfo) #define __NR_perf_event_open 241 __SYSCALL(__NR_perf_event_open, sys_perf_event_open) #define __NR_accept4 242 __SYSCALL(__NR_accept4, sys_accept4) #define __NR_recvmmsg 243 -__SYSCALL(__NR_recvmmsg, sys_recvmmsg) +__SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg) /* * Architectures may provide up to 16 syscalls of their own @@ -639,19 +665,20 @@ __SYSCALL(__NR_recvmmsg, sys_recvmmsg) #define __NR_arch_specific_syscall 244 #define __NR_wait4 260 -__SYSCALL(__NR_wait4, sys_wait4) +__SC_COMP(__NR_wait4, sys_wait4, compat_sys_wait4) #define __NR_prlimit64 261 __SYSCALL(__NR_prlimit64, sys_prlimit64) #define __NR_fanotify_init 262 __SYSCALL(__NR_fanotify_init, sys_fanotify_init) #define __NR_fanotify_mark 263 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) -#define __NR_name_to_handle_at 264 +#define __NR_name_to_handle_at 264 __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) -#define __NR_open_by_handle_at 265 -__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) +#define __NR_open_by_handle_at 265 +__SC_COMP(__NR_open_by_handle_at, sys_open_by_handle_at, \ + compat_sys_open_by_handle_at) #define __NR_clock_adjtime 266 -__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) +__SC_COMP(__NR_clock_adjtime, sys_clock_adjtime, compat_sys_clock_adjtime) #define __NR_syncfs 267 __SYSCALL(__NR_syncfs, sys_syncfs) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index be50d9e70a7..2a7cea53ca0 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -151,7 +151,6 @@ enum rq_flag_bits { __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ - __REQ_ON_PLUG, /* on plug list */ __REQ_NR_BITS, /* stops here */ }; @@ -192,6 +191,5 @@ enum rq_flag_bits { #define REQ_IO_STAT (1 << __REQ_IO_STAT) #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) #define REQ_SECURE (1 << __REQ_SECURE) -#define REQ_ON_PLUG (1 << __REQ_ON_PLUG) #endif /* __LINUX_BLK_TYPES_H */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 2ad95fa1d13..ae9091a6848 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -257,7 +257,7 @@ struct queue_limits { unsigned char misaligned; unsigned char discard_misaligned; unsigned char cluster; - signed char discard_zeroes_data; + unsigned char discard_zeroes_data; }; struct request_queue @@ -364,6 +364,8 @@ struct request_queue * for flush operations */ unsigned int flush_flags; + unsigned int flush_not_queueable:1; + unsigned int flush_queue_delayed:1; unsigned int flush_pending_idx:1; unsigned int flush_running_idx:1; unsigned long flush_pending_since; @@ -843,6 +845,7 @@ extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern void blk_queue_flush(struct request_queue *q, unsigned int flush); +extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); @@ -1066,13 +1069,16 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector { unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1); + if (!lim->max_discard_sectors) + return 0; + return (lim->discard_granularity + lim->discard_alignment - alignment) & (lim->discard_granularity - 1); } static inline unsigned int queue_discard_zeroes_data(struct request_queue *q) { - if (q->limits.discard_zeroes_data == 1) + if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1) return 1; return 0; @@ -1111,6 +1117,11 @@ static inline unsigned int block_size(struct block_device *bdev) return bdev->bd_block_size; } +static inline bool queue_flush_queueable(struct request_queue *q) +{ + return !q->flush_not_queueable; +} + typedef struct {struct page *v;} Sector; unsigned char *read_dev_sector(struct block_device *, sector_t, Sector *); diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index b8e995fbd86..b8c60694b2b 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h @@ -313,6 +313,7 @@ enum { CEPH_MDS_OP_GETATTR = 0x00101, CEPH_MDS_OP_LOOKUPHASH = 0x00102, CEPH_MDS_OP_LOOKUPPARENT = 0x00103, + CEPH_MDS_OP_LOOKUPINO = 0x00104, CEPH_MDS_OP_SETXATTR = 0x01105, CEPH_MDS_OP_RMXATTR = 0x01106, diff --git a/include/linux/compat.h b/include/linux/compat.h index 5778b559d59..ddcb7db38e6 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -12,6 +12,8 @@ #include <linux/sem.h> #include <linux/socket.h> #include <linux/if.h> +#include <linux/fs.h> +#include <linux/aio_abi.h> /* for aio_context_t */ #include <asm/compat.h> #include <asm/siginfo.h> @@ -26,7 +28,7 @@ typedef __compat_gid32_t compat_gid_t; struct compat_sel_arg_struct; struct rusage; -struct compat_itimerspec { +struct compat_itimerspec { struct compat_timespec it_interval; struct compat_timespec it_value; }; @@ -70,9 +72,9 @@ struct compat_timex { compat_long_t stbcnt; compat_int_t tai; - compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; - compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; - compat_int_t :32; compat_int_t :32; compat_int_t :32; + compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32; + compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32; + compat_int_t:32; compat_int_t:32; compat_int_t:32; }; #define _COMPAT_NSIG_WORDS (_COMPAT_NSIG / _COMPAT_NSIG_BPW) @@ -81,8 +83,10 @@ typedef struct { compat_sigset_word sig[_COMPAT_NSIG_WORDS]; } compat_sigset_t; -extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); -extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); +extern int get_compat_timespec(struct timespec *, + const struct compat_timespec __user *); +extern int put_compat_timespec(const struct timespec *, + struct compat_timespec __user *); struct compat_iovec { compat_uptr_t iov_base; @@ -113,7 +117,8 @@ struct compat_rusage { compat_long_t ru_nivcsw; }; -extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *); +extern int put_compat_rusage(const struct rusage *, + struct compat_rusage __user *); struct compat_siginfo; @@ -166,8 +171,7 @@ struct compat_ifmap { unsigned char port; }; -struct compat_if_settings -{ +struct compat_if_settings { unsigned int type; /* Type of physical device or protocol */ unsigned int size; /* Size of the data allocated by the caller */ compat_uptr_t ifs_ifsu; /* union of pointers */ @@ -195,8 +199,8 @@ struct compat_ifreq { }; struct compat_ifconf { - compat_int_t ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; + compat_int_t ifc_len; /* size of buffer */ + compat_caddr_t ifcbuf; }; struct compat_robust_list { @@ -209,6 +213,18 @@ struct compat_robust_list_head { compat_uptr_t list_op_pending; }; +struct compat_statfs; +struct compat_statfs64; +struct compat_old_linux_dirent; +struct compat_linux_dirent; +struct linux_dirent64; +struct compat_msghdr; +struct compat_mmsghdr; +struct compat_sysinfo; +struct compat_sysctl_args; +struct compat_kexec_segment; +struct compat_mq_attr; + extern void compat_exit_robust_list(struct task_struct *curr); asmlinkage long @@ -243,8 +259,8 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen, u32 pos_low, u32 pos_high); -int compat_do_execve(char * filename, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs * regs); +int compat_do_execve(char *filename, compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs *regs); asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, @@ -331,12 +347,18 @@ asmlinkage long compat_sys_epoll_pwait(int epfd, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize); -asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, - struct compat_timespec __user *t, int flags); +asmlinkage long compat_sys_utime(const char __user *filename, + struct compat_utimbuf __user *t); +asmlinkage long compat_sys_utimensat(unsigned int dfd, + const char __user *filename, + struct compat_timespec __user *t, + int flags); +asmlinkage long compat_sys_time(compat_time_t __user *tloc); +asmlinkage long compat_sys_stime(compat_time_t __user *tptr); asmlinkage long compat_sys_signalfd(int ufd, - const compat_sigset_t __user *sigmask, - compat_size_t sigsetsize); + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize); asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, const struct compat_itimerspec __user *utmr, struct compat_itimerspec __user *otmr); @@ -348,16 +370,190 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page, const int __user *nodes, int __user *status, int flags); -asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, +asmlinkage long compat_sys_futimesat(unsigned int dfd, + const char __user *filename, struct compat_timeval __user *t); -asmlinkage long compat_sys_newfstatat(unsigned int dfd, const char __user * filename, +asmlinkage long compat_sys_utimes(const char __user *filename, + struct compat_timeval __user *t); +asmlinkage long compat_sys_newstat(const char __user *filename, + struct compat_stat __user *statbuf); +asmlinkage long compat_sys_newlstat(const char __user *filename, + struct compat_stat __user *statbuf); +asmlinkage long compat_sys_newfstatat(unsigned int dfd, + const char __user *filename, struct compat_stat __user *statbuf, int flag); +asmlinkage long compat_sys_newfstat(unsigned int fd, + struct compat_stat __user *statbuf); +asmlinkage long compat_sys_statfs(const char __user *pathname, + struct compat_statfs __user *buf); +asmlinkage long compat_sys_fstatfs(unsigned int fd, + struct compat_statfs __user *buf); +asmlinkage long compat_sys_statfs64(const char __user *pathname, + compat_size_t sz, + struct compat_statfs64 __user *buf); +asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, + struct compat_statfs64 __user *buf); +asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, + unsigned long arg); +asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, + unsigned long arg); +asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p); +asmlinkage long compat_sys_io_getevents(aio_context_t ctx_id, + unsigned long min_nr, + unsigned long nr, + struct io_event __user *events, + struct compat_timespec __user *timeout); +asmlinkage long compat_sys_io_submit(aio_context_t ctx_id, int nr, + u32 __user *iocb); +asmlinkage long compat_sys_mount(const char __user *dev_name, + const char __user *dir_name, + const char __user *type, unsigned long flags, + const void __user *data); +asmlinkage long compat_sys_old_readdir(unsigned int fd, + struct compat_old_linux_dirent __user *, + unsigned int count); +asmlinkage long compat_sys_getdents(unsigned int fd, + struct compat_linux_dirent __user *dirent, + unsigned int count); +asmlinkage long compat_sys_getdents64(unsigned int fd, + struct linux_dirent64 __user *dirent, + unsigned int count); +asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *, + unsigned int nr_segs, unsigned int flags); +asmlinkage long compat_sys_open(const char __user *filename, int flags, + int mode); asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode); +asmlinkage long compat_sys_open_by_handle_at(int mountdirfd, + struct file_handle __user *handle, + int flags); +asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, + compat_ulong_t __user *exp, + struct compat_timespec __user *tsp, + void __user *sig); +asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, + unsigned int nfds, + struct compat_timespec __user *tsp, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize); +#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && \ + !defined(CONFIG_NFSD_DEPRECATED) +union compat_nfsctl_res; +struct compat_nfsctl_arg; +asmlinkage long compat_sys_nfsservctl(int cmd, + struct compat_nfsctl_arg __user *arg, + union compat_nfsctl_res __user *res); +#else +asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2); +#endif +asmlinkage long compat_sys_signalfd4(int ufd, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize, int flags); +asmlinkage long compat_sys_get_mempolicy(int __user *policy, + compat_ulong_t __user *nmask, + compat_ulong_t maxnode, + compat_ulong_t addr, + compat_ulong_t flags); +asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask, + compat_ulong_t maxnode); +asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, + compat_ulong_t mode, + compat_ulong_t __user *nmask, + compat_ulong_t maxnode, compat_ulong_t flags); + +asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, + char __user *optval, unsigned int optlen); +asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, + unsigned flags); +asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, + unsigned int flags); +asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, + unsigned flags); +asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, + unsigned flags, struct sockaddr __user *addr, + int __user *addrlen); +asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned vlen, unsigned int flags, + struct compat_timespec __user *timeout); +asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, + struct compat_timespec __user *rmtp); +asmlinkage long compat_sys_getitimer(int which, + struct compat_itimerval __user *it); +asmlinkage long compat_sys_setitimer(int which, + struct compat_itimerval __user *in, + struct compat_itimerval __user *out); +asmlinkage long compat_sys_times(struct compat_tms __user *tbuf); +asmlinkage long compat_sys_setrlimit(unsigned int resource, + struct compat_rlimit __user *rlim); +asmlinkage long compat_sys_getrlimit(unsigned int resource, + struct compat_rlimit __user *rlim); +asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru); +asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, + unsigned int len, + compat_ulong_t __user *user_mask_ptr); +asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, + unsigned int len, + compat_ulong_t __user *user_mask_ptr); +asmlinkage long compat_sys_timer_create(clockid_t which_clock, + struct compat_sigevent __user *timer_event_spec, + timer_t __user *created_timer_id); +asmlinkage long compat_sys_timer_settime(timer_t timer_id, int flags, + struct compat_itimerspec __user *new, + struct compat_itimerspec __user *old); +asmlinkage long compat_sys_timer_gettime(timer_t timer_id, + struct compat_itimerspec __user *setting); +asmlinkage long compat_sys_clock_settime(clockid_t which_clock, + struct compat_timespec __user *tp); +asmlinkage long compat_sys_clock_gettime(clockid_t which_clock, + struct compat_timespec __user *tp); +asmlinkage long compat_sys_clock_adjtime(clockid_t which_clock, + struct compat_timex __user *tp); +asmlinkage long compat_sys_clock_getres(clockid_t which_clock, + struct compat_timespec __user *tp); +asmlinkage long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, + struct compat_timespec __user *rqtp, + struct compat_timespec __user *rmtp); +asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese, + struct compat_siginfo __user *uinfo, + struct compat_timespec __user *uts, compat_size_t sigsetsize); +asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, + compat_size_t sigsetsize); +asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); +asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg); +asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, + struct compat_timespec __user *utime, u32 __user *uaddr2, + u32 val3); +asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, + char __user *optval, int __user *optlen); +asmlinkage long compat_sys_kexec_load(unsigned long entry, + unsigned long nr_segments, + struct compat_kexec_segment __user *, + unsigned long flags); +asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, + const struct compat_mq_attr __user *u_mqstat, + struct compat_mq_attr __user *u_omqstat); +asmlinkage long compat_sys_mq_notify(mqd_t mqdes, + const struct compat_sigevent __user *u_notification); +asmlinkage long compat_sys_mq_open(const char __user *u_name, + int oflag, compat_mode_t mode, + struct compat_mq_attr __user *u_attr); +asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes, + const char __user *u_msg_ptr, + size_t msg_len, unsigned int msg_prio, + const struct compat_timespec __user *u_abs_timeout); +asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, + char __user *u_msg_ptr, + size_t msg_len, unsigned int __user *u_msg_prio, + const struct compat_timespec __user *u_abs_timeout); +asmlinkage long compat_sys_socketcall(int call, u32 __user *args); +asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args); extern ssize_t compat_rw_copy_check_uvector(int type, - const struct compat_iovec __user *uvector, unsigned long nr_segs, + const struct compat_iovec __user *uvector, + unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer); diff --git a/include/linux/drbd.h b/include/linux/drbd.h index cec467f5d67..9e5f5607eba 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -38,7 +38,7 @@ /* Although the Linux source code makes a difference between generic endianness and the bitfields' endianness, there is no - architecture as of Linux-2.6.24-rc4 where the bitfileds' endianness + architecture as of Linux-2.6.24-rc4 where the bitfields' endianness does not match the generic endianness. */ #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -53,7 +53,7 @@ extern const char *drbd_buildtag(void); -#define REL_VERSION "8.3.10" +#define REL_VERSION "8.3.11" #define API_VERSION 88 #define PRO_VERSION_MIN 86 #define PRO_VERSION_MAX 96 @@ -195,7 +195,7 @@ enum drbd_conns { C_WF_REPORT_PARAMS, /* we have a socket */ C_CONNECTED, /* we have introduced each other */ C_STARTING_SYNC_S, /* starting full sync by admin request. */ - C_STARTING_SYNC_T, /* stariing full sync by admin request. */ + C_STARTING_SYNC_T, /* starting full sync by admin request. */ C_WF_BITMAP_S, C_WF_BITMAP_T, C_WF_SYNC_UUID, @@ -236,7 +236,7 @@ union drbd_state { * pointed out by Maxim Uvarov q<muvarov@ru.mvista.com> * even though we transmit as "cpu_to_be32(state)", * the offsets of the bitfields still need to be swapped - * on different endianess. + * on different endianness. */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) @@ -266,7 +266,7 @@ union drbd_state { unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned role:2 ; /* 3/4 primary/secondary/unknown */ #else -# error "this endianess is not supported" +# error "this endianness is not supported" #endif }; unsigned int i; diff --git a/include/linux/drbd_tag_magic.h b/include/linux/drbd_tag_magic.h index f14a165e82d..06954319051 100644 --- a/include/linux/drbd_tag_magic.h +++ b/include/linux/drbd_tag_magic.h @@ -30,7 +30,7 @@ enum packet_types { int tag_and_len ## member; #include "linux/drbd_nl.h" -/* declate tag-list-sizes */ +/* declare tag-list-sizes */ static const int tag_list_sizes[] = { #define NL_PACKET(name, number, fields) 2 fields , #define NL_INTEGER(pn, pr, member) + 4 + 4 diff --git a/include/linux/genhd.h b/include/linux/genhd.h index d764a426e9f..b78956b3c2e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -100,7 +100,6 @@ struct hd_struct { sector_t start_sect; sector_t nr_sects; sector_t alignment_offset; - unsigned int discard_alignment; struct device __dev; struct kobject *holder_dir; int policy, partno; @@ -127,6 +126,7 @@ struct hd_struct { #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ #define GENHD_FL_NATIVE_CAPACITY 128 +#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256 enum { DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index f1e3ff5880a..a6c652ef516 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -409,7 +409,7 @@ void i2c_unlock_adapter(struct i2c_adapter *); /* i2c adapter classes (bitmask) */ #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ -#define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */ +#define I2C_CLASS_SPD (1<<7) /* Memory modules */ /* Internal numbers to terminate lists */ #define I2C_CLIENT_END 0xfffeU diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h index 6a4fab7c6e0..7a71ffad037 100644 --- a/include/linux/lru_cache.h +++ b/include/linux/lru_cache.h @@ -139,9 +139,9 @@ write intent log information, three of which are mentioned here. * .list is on one of three lists: * in_use: currently in use (refcnt > 0, lc_number != LC_FREE) * lru: unused but ready to be reused or recycled - * (ts_refcnt == 0, lc_number != LC_FREE), + * (lc_refcnt == 0, lc_number != LC_FREE), * free: unused but ready to be recycled - * (ts_refcnt == 0, lc_number == LC_FREE), + * (lc_refcnt == 0, lc_number == LC_FREE), * * an element is said to be "in the active set", * if either on "in_use" or "lru", i.e. lc_number != LC_FREE. @@ -160,8 +160,8 @@ struct lc_element { struct hlist_node colision; struct list_head list; /* LRU list or free list */ unsigned refcnt; - /* back "pointer" into ts_cache->element[index], - * for paranoia, and for "ts_element_to_index" */ + /* back "pointer" into lc_cache->element[index], + * for paranoia, and for "lc_element_to_index" */ unsigned lc_index; /* if we want to track a larger set of objects, * it needs to become arch independend u64 */ @@ -190,8 +190,8 @@ struct lru_cache { /* Arbitrary limit on maximum tracked objects. Practical limit is much * lower due to allocation failures, probably. For typical use cases, * nr_elements should be a few thousand at most. - * This also limits the maximum value of ts_element.ts_index, allowing the - * 8 high bits of .ts_index to be overloaded with flags in the future. */ + * This also limits the maximum value of lc_element.lc_index, allowing the + * 8 high bits of .lc_index to be overloaded with flags in the future. */ #define LC_MAX_ACTIVE (1<<24) /* statistics */ diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h new file mode 100644 index 00000000000..f0977986402 --- /dev/null +++ b/include/linux/mfd/db5500-prcmu.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * U5500 PRCMU API. + */ +#ifndef __MACH_PRCMU_U5500_H +#define __MACH_PRCMU_U5500_H + +#ifdef CONFIG_UX500_SOC_DB5500 + +void db5500_prcmu_early_init(void); + +int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); +int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); + +#else /* !CONFIG_UX500_SOC_DB5500 */ + +static inline void db5500_prcmu_early_init(void) +{ +} + +static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + return -ENOSYS; +} + +static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + return -ENOSYS; +} + +#endif /* CONFIG_UX500_SOC_DB5500 */ + +static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events) +{ +#ifdef CONFIG_MACH_U5500_SIMULATOR + return 0; +#else + return -1; +#endif +} + +#endif /* __MACH_PRCMU_U5500_H */ diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h new file mode 100644 index 00000000000..917dbcab701 --- /dev/null +++ b/include/linux/mfd/db8500-prcmu.h @@ -0,0 +1,978 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * + * PRCMU f/w APIs + */ +#ifndef __MFD_DB8500_PRCMU_H +#define __MFD_DB8500_PRCMU_H + +#include <linux/interrupt.h> +#include <linux/notifier.h> + +/* This portion previously known as <mach/prcmu-fw-defs_v1.h> */ + +/** + * enum state - ON/OFF state definition + * @OFF: State is ON + * @ON: State is OFF + * + */ +enum state { + OFF = 0x0, + ON = 0x1, +}; + +/** + * enum ret_state - general purpose On/Off/Retention states + * + */ +enum ret_state { + OFFST = 0, + ONST = 1, + RETST = 2 +}; + +/** + * enum clk_arm - ARM Cortex A9 clock schemes + * @A9_OFF: + * @A9_BOOT: + * @A9_OPPT1: + * @A9_OPPT2: + * @A9_EXTCLK: + */ +enum clk_arm { + A9_OFF, + A9_BOOT, + A9_OPPT1, + A9_OPPT2, + A9_EXTCLK +}; + +/** + * enum clk_gen - GEN#0/GEN#1 clock schemes + * @GEN_OFF: + * @GEN_BOOT: + * @GEN_OPPT1: + */ +enum clk_gen { + GEN_OFF, + GEN_BOOT, + GEN_OPPT1, +}; + +/* some information between arm and xp70 */ + +/** + * enum romcode_write - Romcode message written by A9 AND read by XP70 + * @RDY_2_DS: Value set when ApDeepSleep state can be executed by XP70 + * @RDY_2_XP70_RST: Value set when 0x0F has been successfully polled by the + * romcode. The xp70 will go into self-reset + */ +enum romcode_write { + RDY_2_DS = 0x09, + RDY_2_XP70_RST = 0x10 +}; + +/** + * enum romcode_read - Romcode message written by XP70 and read by A9 + * @INIT: Init value when romcode field is not used + * @FS_2_DS: Value set when power state is going from ApExecute to + * ApDeepSleep + * @END_DS: Value set when ApDeepSleep power state is reached coming from + * ApExecute state + * @DS_TO_FS: Value set when power state is going from ApDeepSleep to + * ApExecute + * @END_FS: Value set when ApExecute power state is reached coming from + * ApDeepSleep state + * @SWR: Value set when power state is going to ApReset + * @END_SWR: Value set when the xp70 finished executing ApReset actions and + * waits for romcode acknowledgment to go to self-reset + */ +enum romcode_read { + INIT = 0x00, + FS_2_DS = 0x0A, + END_DS = 0x0B, + DS_TO_FS = 0x0C, + END_FS = 0x0D, + SWR = 0x0E, + END_SWR = 0x0F +}; + +/** + * enum ap_pwrst - current power states defined in PRCMU firmware + * @NO_PWRST: Current power state init + * @AP_BOOT: Current power state is apBoot + * @AP_EXECUTE: Current power state is apExecute + * @AP_DEEP_SLEEP: Current power state is apDeepSleep + * @AP_SLEEP: Current power state is apSleep + * @AP_IDLE: Current power state is apIdle + * @AP_RESET: Current power state is apReset + */ +enum ap_pwrst { + NO_PWRST = 0x00, + AP_BOOT = 0x01, + AP_EXECUTE = 0x02, + AP_DEEP_SLEEP = 0x03, + AP_SLEEP = 0x04, + AP_IDLE = 0x05, + AP_RESET = 0x06 +}; + +/** + * enum ap_pwrst_trans - Transition states defined in PRCMU firmware + * @NO_TRANSITION: No power state transition + * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep + * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep + * @APBOOT_TO_APEXECUTE: Power state transition from ApBoot to ApExecute + * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to + * ApDeepSleep + * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle + */ +enum ap_pwrst_trans { + NO_TRANSITION = 0x00, + APEXECUTE_TO_APSLEEP = 0x01, + APIDLE_TO_APSLEEP = 0x02, /* To be removed */ + PRCMU_AP_SLEEP = 0x01, + APBOOT_TO_APEXECUTE = 0x03, + APEXECUTE_TO_APDEEPSLEEP = 0x04, /* To be removed */ + PRCMU_AP_DEEP_SLEEP = 0x04, + APEXECUTE_TO_APIDLE = 0x05, /* To be removed */ + PRCMU_AP_IDLE = 0x05, + PRCMU_AP_DEEP_IDLE = 0x07, +}; + +/** + * enum ddr_pwrst - DDR power states definition + * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged + * @DDR_PWR_STATE_ON: + * @DDR_PWR_STATE_OFFLOWLAT: + * @DDR_PWR_STATE_OFFHIGHLAT: + */ +enum ddr_pwrst { + DDR_PWR_STATE_UNCHANGED = 0x00, + DDR_PWR_STATE_ON = 0x01, + DDR_PWR_STATE_OFFLOWLAT = 0x02, + DDR_PWR_STATE_OFFHIGHLAT = 0x03 +}; + +/** + * enum arm_opp - ARM OPP states definition + * @ARM_OPP_INIT: + * @ARM_NO_CHANGE: The ARM operating point is unchanged + * @ARM_100_OPP: The new ARM operating point is arm100opp + * @ARM_50_OPP: The new ARM operating point is arm50opp + * @ARM_MAX_OPP: Operating point is "max" (more than 100) + * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100 + * @ARM_EXTCLK: The new ARM operating point is armExtClk + */ +enum arm_opp { + ARM_OPP_INIT = 0x00, + ARM_NO_CHANGE = 0x01, + ARM_100_OPP = 0x02, + ARM_50_OPP = 0x03, + ARM_MAX_OPP = 0x04, + ARM_MAX_FREQ100OPP = 0x05, + ARM_EXTCLK = 0x07 +}; + +/** + * enum ape_opp - APE OPP states definition + * @APE_OPP_INIT: + * @APE_NO_CHANGE: The APE operating point is unchanged + * @APE_100_OPP: The new APE operating point is ape100opp + * @APE_50_OPP: 50% + */ +enum ape_opp { + APE_OPP_INIT = 0x00, + APE_NO_CHANGE = 0x01, + APE_100_OPP = 0x02, + APE_50_OPP = 0x03 +}; + +/** + * enum hw_acc_state - State definition for hardware accelerator + * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged + * @HW_OFF: The hardware accelerator must be switched off + * @HW_OFF_RAMRET: The hardware accelerator must be switched off with its + * internal RAM in retention + * @HW_ON: The hwa hardware accelerator hwa must be switched on + * + * NOTE! Deprecated, to be removed when all users switched over to use the + * regulator API. + */ +enum hw_acc_state { + HW_NO_CHANGE = 0x00, + HW_OFF = 0x01, + HW_OFF_RAMRET = 0x02, + HW_ON = 0x04 +}; + +/** + * enum mbox_2_arm_stat - Status messages definition for mbox_arm + * @BOOT_TO_EXECUTEOK: The apBoot to apExecute state transition has been + * completed + * @DEEPSLEEPOK: The apExecute to apDeepSleep state transition has been + * completed + * @SLEEPOK: The apExecute to apSleep state transition has been completed + * @IDLEOK: The apExecute to apIdle state transition has been completed + * @SOFTRESETOK: The A9 watchdog/ SoftReset state has been completed + * @SOFTRESETGO : The A9 watchdog/SoftReset state is on going + * @BOOT_TO_EXECUTE: The apBoot to apExecute state transition is on going + * @EXECUTE_TO_DEEPSLEEP: The apExecute to apDeepSleep state transition is on + * going + * @DEEPSLEEP_TO_EXECUTE: The apDeepSleep to apExecute state transition is on + * going + * @DEEPSLEEP_TO_EXECUTEOK: The apDeepSleep to apExecute state transition has + * been completed + * @EXECUTE_TO_SLEEP: The apExecute to apSleep state transition is on going + * @SLEEP_TO_EXECUTE: The apSleep to apExecute state transition is on going + * @SLEEP_TO_EXECUTEOK: The apSleep to apExecute state transition has been + * completed + * @EXECUTE_TO_IDLE: The apExecute to apIdle state transition is on going + * @IDLE_TO_EXECUTE: The apIdle to apExecute state transition is on going + * @IDLE_TO_EXECUTEOK: The apIdle to apExecute state transition has been + * completed + * @INIT_STATUS: Status init + */ +enum ap_pwrsttr_status { + BOOT_TO_EXECUTEOK = 0xFF, + DEEPSLEEPOK = 0xFE, + SLEEPOK = 0xFD, + IDLEOK = 0xFC, + SOFTRESETOK = 0xFB, + SOFTRESETGO = 0xFA, + BOOT_TO_EXECUTE = 0xF9, + EXECUTE_TO_DEEPSLEEP = 0xF8, + DEEPSLEEP_TO_EXECUTE = 0xF7, + DEEPSLEEP_TO_EXECUTEOK = 0xF6, + EXECUTE_TO_SLEEP = 0xF5, + SLEEP_TO_EXECUTE = 0xF4, + SLEEP_TO_EXECUTEOK = 0xF3, + EXECUTE_TO_IDLE = 0xF2, + IDLE_TO_EXECUTE = 0xF1, + IDLE_TO_EXECUTEOK = 0xF0, + RDYTODS_RETURNTOEXE = 0xEF, + NORDYTODS_RETURNTOEXE = 0xEE, + EXETOSLEEP_RETURNTOEXE = 0xED, + EXETOIDLE_RETURNTOEXE = 0xEC, + INIT_STATUS = 0xEB, + + /*error messages */ + INITERROR = 0x00, + PLLARMLOCKP_ER = 0x01, + PLLDDRLOCKP_ER = 0x02, + PLLSOCLOCKP_ER = 0x03, + PLLSOCK1LOCKP_ER = 0x04, + ARMWFI_ER = 0x05, + SYSCLKOK_ER = 0x06, + I2C_NACK_DATA_ER = 0x07, + BOOT_ER = 0x08, + I2C_STATUS_ALWAYS_1 = 0x0A, + I2C_NACK_REG_ADDR_ER = 0x0B, + I2C_NACK_DATA0123_ER = 0x1B, + I2C_NACK_ADDR_ER = 0x1F, + CURAPPWRSTISNOT_BOOT = 0x20, + CURAPPWRSTISNOT_EXECUTE = 0x21, + CURAPPWRSTISNOT_SLEEPMODE = 0x22, + CURAPPWRSTISNOT_CORRECTFORIT10 = 0x23, + FIFO4500WUISNOT_WUPEVENT = 0x24, + PLL32KLOCKP_ER = 0x29, + DDRDEEPSLEEPOK_ER = 0x2A, + ROMCODEREADY_ER = 0x50, + WUPBEFOREDS = 0x51, + DDRCONFIG_ER = 0x52, + WUPBEFORESLEEP = 0x53, + WUPBEFOREIDLE = 0x54 +}; /* earlier called as mbox_2_arm_stat */ + +/** + * enum dvfs_stat - DVFS status messages definition + * @DVFS_GO: A state transition DVFS is on going + * @DVFS_ARM100OPPOK: The state transition DVFS has been completed for 100OPP + * @DVFS_ARM50OPPOK: The state transition DVFS has been completed for 50OPP + * @DVFS_ARMEXTCLKOK: The state transition DVFS has been completed for EXTCLK + * @DVFS_NOCHGTCLKOK: The state transition DVFS has been completed for + * NOCHGCLK + * @DVFS_INITSTATUS: Value init + */ +enum dvfs_stat { + DVFS_GO = 0xFF, + DVFS_ARM100OPPOK = 0xFE, + DVFS_ARM50OPPOK = 0xFD, + DVFS_ARMEXTCLKOK = 0xFC, + DVFS_NOCHGTCLKOK = 0xFB, + DVFS_INITSTATUS = 0x00 +}; + +/** + * enum sva_mmdsp_stat - SVA MMDSP status messages + * @SVA_MMDSP_GO: SVAMMDSP interrupt has happened + * @SVA_MMDSP_INIT: Status init + */ +enum sva_mmdsp_stat { + SVA_MMDSP_GO = 0xFF, + SVA_MMDSP_INIT = 0x00 +}; + +/** + * enum sia_mmdsp_stat - SIA MMDSP status messages + * @SIA_MMDSP_GO: SIAMMDSP interrupt has happened + * @SIA_MMDSP_INIT: Status init + */ +enum sia_mmdsp_stat { + SIA_MMDSP_GO = 0xFF, + SIA_MMDSP_INIT = 0x00 +}; + +/** + * enum mbox_to_arm_err - Error messages definition + * @INIT_ERR: Init value + * @PLLARMLOCKP_ERR: PLLARM has not been correctly locked in given time + * @PLLDDRLOCKP_ERR: PLLDDR has not been correctly locked in the given time + * @PLLSOC0LOCKP_ERR: PLLSOC0 has not been correctly locked in the given time + * @PLLSOC1LOCKP_ERR: PLLSOC1 has not been correctly locked in the given time + * @ARMWFI_ERR: The ARM WFI has not been correctly executed in the given time + * @SYSCLKOK_ERR: The SYSCLK is not available in the given time + * @BOOT_ERR: Romcode has not validated the XP70 self reset in the given time + * @ROMCODESAVECONTEXT: The Romcode didn.t correctly save it secure context + * @VARMHIGHSPEEDVALTO_ERR: The ARM high speed supply value transfered + * through I2C has not been correctly executed in the given time + * @VARMHIGHSPEEDACCESS_ERR: The command value of VarmHighSpeedVal transfered + * through I2C has not been correctly executed in the given time + * @VARMLOWSPEEDVALTO_ERR:The ARM low speed supply value transfered through + * I2C has not been correctly executed in the given time + * @VARMLOWSPEEDACCESS_ERR: The command value of VarmLowSpeedVal transfered + * through I2C has not been correctly executed in the given time + * @VARMRETENTIONVALTO_ERR: The ARM retention supply value transfered through + * I2C has not been correctly executed in the given time + * @VARMRETENTIONACCESS_ERR: The command value of VarmRetentionVal transfered + * through I2C has not been correctly executed in the given time + * @VAPEHIGHSPEEDVALTO_ERR: The APE highspeed supply value transfered through + * I2C has not been correctly executed in the given time + * @VSAFEHPVALTO_ERR: The SAFE high power supply value transfered through I2C + * has not been correctly executed in the given time + * @VMODSEL1VALTO_ERR: The MODEM sel1 supply value transfered through I2C has + * not been correctly executed in the given time + * @VMODSEL2VALTO_ERR: The MODEM sel2 supply value transfered through I2C has + * not been correctly executed in the given time + * @VARMOFFACCESS_ERR: The command value of Varm ON/OFF transfered through + * I2C has not been correctly executed in the given time + * @VAPEOFFACCESS_ERR: The command value of Vape ON/OFF transfered through + * I2C has not been correctly executed in the given time + * @VARMRETACCES_ERR: The command value of Varm retention ON/OFF transfered + * through I2C has not been correctly executed in the given time + * @CURAPPWRSTISNOTBOOT:Generated when Arm want to do power state transition + * ApBoot to ApExecute but the power current state is not Apboot + * @CURAPPWRSTISNOTEXECUTE: Generated when Arm want to do power state + * transition from ApExecute to others power state but the + * power current state is not ApExecute + * @CURAPPWRSTISNOTSLEEPMODE: Generated when wake up events are transmitted + * but the power current state is not ApDeepSleep/ApSleep/ApIdle + * @CURAPPWRSTISNOTCORRECTDBG: Generated when wake up events are transmitted + * but the power current state is not correct + * @ARMREGU1VALTO_ERR:The ArmRegu1 value transferred through I2C has not + * been correctly executed in the given time + * @ARMREGU2VALTO_ERR: The ArmRegu2 value transferred through I2C has not + * been correctly executed in the given time + * @VAPEREGUVALTO_ERR: The VApeRegu value transfered through I2C has not + * been correctly executed in the given time + * @VSMPS3REGUVALTO_ERR: The VSmps3Regu value transfered through I2C has not + * been correctly executed in the given time + * @VMODREGUVALTO_ERR: The VModemRegu value transfered through I2C has not + * been correctly executed in the given time + */ +enum mbox_to_arm_err { + INIT_ERR = 0x00, + PLLARMLOCKP_ERR = 0x01, + PLLDDRLOCKP_ERR = 0x02, + PLLSOC0LOCKP_ERR = 0x03, + PLLSOC1LOCKP_ERR = 0x04, + ARMWFI_ERR = 0x05, + SYSCLKOK_ERR = 0x06, + BOOT_ERR = 0x07, + ROMCODESAVECONTEXT = 0x08, + VARMHIGHSPEEDVALTO_ERR = 0x10, + VARMHIGHSPEEDACCESS_ERR = 0x11, + VARMLOWSPEEDVALTO_ERR = 0x12, + VARMLOWSPEEDACCESS_ERR = 0x13, + VARMRETENTIONVALTO_ERR = 0x14, + VARMRETENTIONACCESS_ERR = 0x15, + VAPEHIGHSPEEDVALTO_ERR = 0x16, + VSAFEHPVALTO_ERR = 0x17, + VMODSEL1VALTO_ERR = 0x18, + VMODSEL2VALTO_ERR = 0x19, + VARMOFFACCESS_ERR = 0x1A, + VAPEOFFACCESS_ERR = 0x1B, + VARMRETACCES_ERR = 0x1C, + CURAPPWRSTISNOTBOOT = 0x20, + CURAPPWRSTISNOTEXECUTE = 0x21, + CURAPPWRSTISNOTSLEEPMODE = 0x22, + CURAPPWRSTISNOTCORRECTDBG = 0x23, + ARMREGU1VALTO_ERR = 0x24, + ARMREGU2VALTO_ERR = 0x25, + VAPEREGUVALTO_ERR = 0x26, + VSMPS3REGUVALTO_ERR = 0x27, + VMODREGUVALTO_ERR = 0x28 +}; + +enum hw_acc { + SVAMMDSP = 0, + SVAPIPE = 1, + SIAMMDSP = 2, + SIAPIPE = 3, + SGA = 4, + B2R2MCDE = 5, + ESRAM12 = 6, + ESRAM34 = 7, +}; + +enum cs_pwrmgt { + PWRDNCS0 = 0, + WKUPCS0 = 1, + PWRDNCS1 = 2, + WKUPCS1 = 3 +}; + +/* Defs related to autonomous power management */ + +/** + * enum sia_sva_pwr_policy - Power policy + * @NO_CHGT: No change + * @DSPOFF_HWPOFF: + * @DSPOFFRAMRET_HWPOFF: + * @DSPCLKOFF_HWPOFF: + * @DSPCLKOFF_HWPCLKOFF: + * + */ +enum sia_sva_pwr_policy { + NO_CHGT = 0x0, + DSPOFF_HWPOFF = 0x1, + DSPOFFRAMRET_HWPOFF = 0x2, + DSPCLKOFF_HWPOFF = 0x3, + DSPCLKOFF_HWPCLKOFF = 0x4, +}; + +/** + * enum auto_enable - Auto Power enable + * @AUTO_OFF: + * @AUTO_ON: + * + */ +enum auto_enable { + AUTO_OFF = 0x0, + AUTO_ON = 0x1, +}; + +/* End of file previously known as prcmu-fw-defs_v1.h */ + +/* PRCMU Wakeup defines */ +enum prcmu_wakeup_index { + PRCMU_WAKEUP_INDEX_RTC, + PRCMU_WAKEUP_INDEX_RTT0, + PRCMU_WAKEUP_INDEX_RTT1, + PRCMU_WAKEUP_INDEX_HSI0, + PRCMU_WAKEUP_INDEX_HSI1, + PRCMU_WAKEUP_INDEX_USB, + PRCMU_WAKEUP_INDEX_ABB, + PRCMU_WAKEUP_INDEX_ABB_FIFO, + PRCMU_WAKEUP_INDEX_ARM, + NUM_PRCMU_WAKEUP_INDICES +}; +#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name)) + +/* PRCMU QoS APE OPP class */ +#define PRCMU_QOS_APE_OPP 1 +#define PRCMU_QOS_DDR_OPP 2 +#define PRCMU_QOS_DEFAULT_VALUE -1 + +/** + * enum hw_acc_dev - enum for hw accelerators + * @HW_ACC_SVAMMDSP: for SVAMMDSP + * @HW_ACC_SVAPIPE: for SVAPIPE + * @HW_ACC_SIAMMDSP: for SIAMMDSP + * @HW_ACC_SIAPIPE: for SIAPIPE + * @HW_ACC_SGA: for SGA + * @HW_ACC_B2R2: for B2R2 + * @HW_ACC_MCDE: for MCDE + * @HW_ACC_ESRAM1: for ESRAM1 + * @HW_ACC_ESRAM2: for ESRAM2 + * @HW_ACC_ESRAM3: for ESRAM3 + * @HW_ACC_ESRAM4: for ESRAM4 + * @NUM_HW_ACC: number of hardware accelerators + * + * Different hw accelerators which can be turned ON/ + * OFF or put into retention (MMDSPs and ESRAMs). + * Used with EPOD API. + * + * NOTE! Deprecated, to be removed when all users switched over to use the + * regulator API. + */ +enum hw_acc_dev { + HW_ACC_SVAMMDSP, + HW_ACC_SVAPIPE, + HW_ACC_SIAMMDSP, + HW_ACC_SIAPIPE, + HW_ACC_SGA, + HW_ACC_B2R2, + HW_ACC_MCDE, + HW_ACC_ESRAM1, + HW_ACC_ESRAM2, + HW_ACC_ESRAM3, + HW_ACC_ESRAM4, + NUM_HW_ACC +}; + +/* + * Ids for all EPODs (power domains) + * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP + * - EPOD_ID_SVAPIPE: power domain for SVA pipe + * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP + * - EPOD_ID_SIAPIPE: power domain for SIA pipe + * - EPOD_ID_SGA: power domain for SGA + * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE + * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2 + * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4 + * - NUM_EPOD_ID: number of power domains + */ +#define EPOD_ID_SVAMMDSP 0 +#define EPOD_ID_SVAPIPE 1 +#define EPOD_ID_SIAMMDSP 2 +#define EPOD_ID_SIAPIPE 3 +#define EPOD_ID_SGA 4 +#define EPOD_ID_B2R2_MCDE 5 +#define EPOD_ID_ESRAM12 6 +#define EPOD_ID_ESRAM34 7 +#define NUM_EPOD_ID 8 + +/* + * state definition for EPOD (power domain) + * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged + * - EPOD_STATE_OFF: The EPOD is switched off + * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in + * retention + * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off + * - EPOD_STATE_ON: Same as above, but with clock enabled + */ +#define EPOD_STATE_NO_CHANGE 0x00 +#define EPOD_STATE_OFF 0x01 +#define EPOD_STATE_RAMRET 0x02 +#define EPOD_STATE_ON_CLK_OFF 0x03 +#define EPOD_STATE_ON 0x04 + +/* + * CLKOUT sources + */ +#define PRCMU_CLKSRC_CLK38M 0x00 +#define PRCMU_CLKSRC_ACLK 0x01 +#define PRCMU_CLKSRC_SYSCLK 0x02 +#define PRCMU_CLKSRC_LCDCLK 0x03 +#define PRCMU_CLKSRC_SDMMCCLK 0x04 +#define PRCMU_CLKSRC_TVCLK 0x05 +#define PRCMU_CLKSRC_TIMCLK 0x06 +#define PRCMU_CLKSRC_CLK009 0x07 +/* These are only valid for CLKOUT1: */ +#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40 +#define PRCMU_CLKSRC_I2CCLK 0x41 +#define PRCMU_CLKSRC_MSP02CLK 0x42 +#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43 +#define PRCMU_CLKSRC_HSIRXCLK 0x44 +#define PRCMU_CLKSRC_HSITXCLK 0x45 +#define PRCMU_CLKSRC_ARMCLKFIX 0x46 +#define PRCMU_CLKSRC_HDMICLK 0x47 + +/* + * Definitions for autonomous power management configuration. + */ + +#define PRCMU_AUTO_PM_OFF 0 +#define PRCMU_AUTO_PM_ON 1 + +#define PRCMU_AUTO_PM_POWER_ON_HSEM BIT(0) +#define PRCMU_AUTO_PM_POWER_ON_ABB_FIFO_IT BIT(1) + +enum prcmu_auto_pm_policy { + PRCMU_AUTO_PM_POLICY_NO_CHANGE, + PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, + PRCMU_AUTO_PM_POLICY_DSP_OFF_RAMRET_HWP_OFF, + PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_OFF, + PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_CLK_OFF, +}; + +/** + * struct prcmu_auto_pm_config - Autonomous power management configuration. + * @sia_auto_pm_enable: SIA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON}) + * @sia_power_on: SIA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask) + * @sia_policy: SIA power policy. (enum prcmu_auto_pm_policy) + * @sva_auto_pm_enable: SVA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON}) + * @sva_power_on: SVA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask) + * @sva_policy: SVA power policy. (enum prcmu_auto_pm_policy) + */ +struct prcmu_auto_pm_config { + u8 sia_auto_pm_enable; + u8 sia_power_on; + u8 sia_policy; + u8 sva_auto_pm_enable; + u8 sva_power_on; + u8 sva_policy; +}; + +/** + * enum ddr_opp - DDR OPP states definition + * @DDR_100_OPP: The new DDR operating point is ddr100opp + * @DDR_50_OPP: The new DDR operating point is ddr50opp + * @DDR_25_OPP: The new DDR operating point is ddr25opp + */ +enum ddr_opp { + DDR_100_OPP = 0x00, + DDR_50_OPP = 0x01, + DDR_25_OPP = 0x02, +}; + +/* + * Clock identifiers. + */ +enum prcmu_clock { + PRCMU_SGACLK, + PRCMU_UARTCLK, + PRCMU_MSP02CLK, + PRCMU_MSP1CLK, + PRCMU_I2CCLK, + PRCMU_SDMMCCLK, + PRCMU_SLIMCLK, + PRCMU_PER1CLK, + PRCMU_PER2CLK, + PRCMU_PER3CLK, + PRCMU_PER5CLK, + PRCMU_PER6CLK, + PRCMU_PER7CLK, + PRCMU_LCDCLK, + PRCMU_BMLCLK, + PRCMU_HSITXCLK, + PRCMU_HSIRXCLK, + PRCMU_HDMICLK, + PRCMU_APEATCLK, + PRCMU_APETRACECLK, + PRCMU_MCDECLK, + PRCMU_IPI2CCLK, + PRCMU_DSIALTCLK, + PRCMU_DMACLK, + PRCMU_B2R2CLK, + PRCMU_TVCLK, + PRCMU_SSPCLK, + PRCMU_RNGCLK, + PRCMU_UICCCLK, + PRCMU_NUM_REG_CLOCKS, + PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, + PRCMU_TIMCLK, +}; + +/* + * Definitions for controlling ESRAM0 in deep sleep. + */ +#define ESRAM0_DEEP_SLEEP_STATE_OFF 1 +#define ESRAM0_DEEP_SLEEP_STATE_RET 2 + +#ifdef CONFIG_MFD_DB8500_PRCMU +void __init prcmu_early_init(void); +int prcmu_set_display_clocks(void); +int prcmu_disable_dsipll(void); +int prcmu_enable_dsipll(void); +#else +static inline void __init prcmu_early_init(void) {} +#endif + +#ifdef CONFIG_MFD_DB8500_PRCMU + +int prcmu_set_rc_a2p(enum romcode_write); +enum romcode_read prcmu_get_rc_p2a(void); +enum ap_pwrst prcmu_get_xp70_current_state(void); +int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); + +void prcmu_enable_wakeups(u32 wakeups); +static inline void prcmu_disable_wakeups(void) +{ + prcmu_enable_wakeups(0); +} + +void prcmu_config_abb_event_readout(u32 abb_events); +void prcmu_get_abb_event_buffer(void __iomem **buf); +int prcmu_set_arm_opp(u8 opp); +int prcmu_get_arm_opp(void); +bool prcmu_has_arm_maxopp(void); +bool prcmu_is_u8400(void); +int prcmu_set_ape_opp(u8 opp); +int prcmu_get_ape_opp(void); +int prcmu_request_ape_opp_100_voltage(bool enable); +int prcmu_release_usb_wakeup_state(void); +int prcmu_set_ddr_opp(u8 opp); +int prcmu_get_ddr_opp(void); +unsigned long prcmu_qos_get_cpufreq_opp_delay(void); +void prcmu_qos_set_cpufreq_opp_delay(unsigned long); +/* NOTE! Use regulator framework instead */ +int prcmu_set_hwacc(u16 hw_acc_dev, u8 state); +int prcmu_set_epod(u16 epod_id, u8 epod_state); +void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle); +bool prcmu_is_auto_pm_enabled(void); + +int prcmu_config_clkout(u8 clkout, u8 source, u8 div); +int prcmu_request_clock(u8 clock, bool enable); +int prcmu_set_clock_divider(u8 clock, u8 divider); +int prcmu_config_esram0_deep_sleep(u8 state); +int prcmu_config_hotdog(u8 threshold); +int prcmu_config_hotmon(u8 low, u8 high); +int prcmu_start_temp_sense(u16 cycles32k); +int prcmu_stop_temp_sense(void); +int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); +int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); + +void prcmu_ac_wake_req(void); +void prcmu_ac_sleep_req(void); +void prcmu_system_reset(u16 reset_code); +void prcmu_modem_reset(void); +bool prcmu_is_ac_wake_requested(void); +void prcmu_enable_spi2(void); +void prcmu_disable_spi2(void); + +#else /* !CONFIG_MFD_DB8500_PRCMU */ + +static inline int prcmu_set_rc_a2p(enum romcode_write code) +{ + return 0; +} + +static inline enum romcode_read prcmu_get_rc_p2a(void) +{ + return INIT; +} + +static inline enum ap_pwrst prcmu_get_xp70_current_state(void) +{ + return AP_EXECUTE; +} + +static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) +{ + return 0; +} + +static inline void prcmu_enable_wakeups(u32 wakeups) {} + +static inline void prcmu_disable_wakeups(void) {} + +static inline void prcmu_config_abb_event_readout(u32 abb_events) {} + +static inline int prcmu_set_arm_opp(u8 opp) +{ + return 0; +} + +static inline int prcmu_get_arm_opp(void) +{ + return ARM_100_OPP; +} + +static bool prcmu_has_arm_maxopp(void) +{ + return false; +} + +static bool prcmu_is_u8400(void) +{ + return false; +} + +static inline int prcmu_set_ape_opp(u8 opp) +{ + return 0; +} + +static inline int prcmu_get_ape_opp(void) +{ + return APE_100_OPP; +} + +static inline int prcmu_request_ape_opp_100_voltage(bool enable) +{ + return 0; +} + +static inline int prcmu_release_usb_wakeup_state(void) +{ + return 0; +} + +static inline int prcmu_set_ddr_opp(u8 opp) +{ + return 0; +} + +static inline int prcmu_get_ddr_opp(void) +{ + return DDR_100_OPP; +} + +static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void) +{ + return 0; +} + +static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {} + +static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state) +{ + return 0; +} + +static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, + struct prcmu_auto_pm_config *idle) +{ +} + +static inline bool prcmu_is_auto_pm_enabled(void) +{ + return false; +} + +static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) +{ + return 0; +} + +static inline int prcmu_request_clock(u8 clock, bool enable) +{ + return 0; +} + +static inline int prcmu_set_clock_divider(u8 clock, u8 divider) +{ + return 0; +} + +int prcmu_config_esram0_deep_sleep(u8 state) +{ + return 0; +} + +static inline int prcmu_config_hotdog(u8 threshold) +{ + return 0; +} + +static inline int prcmu_config_hotmon(u8 low, u8 high) +{ + return 0; +} + +static inline int prcmu_start_temp_sense(u16 cycles32k) +{ + return 0; +} + +static inline int prcmu_stop_temp_sense(void) +{ + return 0; +} + +static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) +{ + return -ENOSYS; +} + +static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) +{ + return -ENOSYS; +} + +static inline void prcmu_ac_wake_req(void) {} + +static inline void prcmu_ac_sleep_req(void) {} + +static inline void prcmu_system_reset(u16 reset_code) {} + +static inline void prcmu_modem_reset(void) {} + +static inline bool prcmu_is_ac_wake_requested(void) +{ + return false; +} + +#ifndef CONFIG_UX500_SOC_DB5500 +static inline int prcmu_set_display_clocks(void) +{ + return 0; +} + +static inline int prcmu_disable_dsipll(void) +{ + return 0; +} + +static inline int prcmu_enable_dsipll(void) +{ + return 0; +} +#endif + +static inline int prcmu_enable_spi2(void) +{ + return 0; +} + +static inline int prcmu_disable_spi2(void) +{ + return 0; +} + +#endif /* !CONFIG_MFD_DB8500_PRCMU */ + +#ifdef CONFIG_UX500_PRCMU_QOS_POWER +int prcmu_qos_requirement(int pm_qos_class); +int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value); +int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value); +void prcmu_qos_remove_requirement(int pm_qos_class, char *name); +int prcmu_qos_add_notifier(int prcmu_qos_class, + struct notifier_block *notifier); +int prcmu_qos_remove_notifier(int prcmu_qos_class, + struct notifier_block *notifier); +#else +static inline int prcmu_qos_requirement(int prcmu_qos_class) +{ + return 0; +} + +static inline int prcmu_qos_add_requirement(int prcmu_qos_class, + char *name, s32 value) +{ + return 0; +} + +static inline int prcmu_qos_update_requirement(int prcmu_qos_class, + char *name, s32 new_value) +{ + return 0; +} + +static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) +{ +} + +static inline int prcmu_qos_add_notifier(int prcmu_qos_class, + struct notifier_block *notifier) +{ + return 0; +} +static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, + struct notifier_block *notifier) +{ + return 0; +} + +#endif + +#endif /* __MFD_DB8500_PRCMU_H */ diff --git a/include/linux/regulator/db8500-prcmu.h b/include/linux/regulator/db8500-prcmu.h new file mode 100644 index 00000000000..612062313b6 --- /dev/null +++ b/include/linux/regulator/db8500-prcmu.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson + * + * Interface to power domain regulators on DB8500 + */ + +#ifndef __REGULATOR_H__ +#define __REGULATOR_H__ + +/* Number of DB8500 regulators and regulator enumeration */ +enum db8500_regulator_id { + DB8500_REGULATOR_VAPE, + DB8500_REGULATOR_VARM, + DB8500_REGULATOR_VMODEM, + DB8500_REGULATOR_VPLL, + DB8500_REGULATOR_VSMPS1, + DB8500_REGULATOR_VSMPS2, + DB8500_REGULATOR_VSMPS3, + DB8500_REGULATOR_VRF1, + DB8500_REGULATOR_SWITCH_SVAMMDSP, + DB8500_REGULATOR_SWITCH_SVAMMDSPRET, + DB8500_REGULATOR_SWITCH_SVAPIPE, + DB8500_REGULATOR_SWITCH_SIAMMDSP, + DB8500_REGULATOR_SWITCH_SIAMMDSPRET, + DB8500_REGULATOR_SWITCH_SIAPIPE, + DB8500_REGULATOR_SWITCH_SGA, + DB8500_REGULATOR_SWITCH_B2R2_MCDE, + DB8500_REGULATOR_SWITCH_ESRAM12, + DB8500_REGULATOR_SWITCH_ESRAM12RET, + DB8500_REGULATOR_SWITCH_ESRAM34, + DB8500_REGULATOR_SWITCH_ESRAM34RET, + DB8500_NUM_REGULATORS +}; + +/* + * Exported interface for CPUIdle only. This function is called with all + * interrupts turned off. + */ +int power_state_active_is_enabled(void); + +#endif diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index d2df55b0c21..008711e8e78 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -241,10 +241,10 @@ enum p9_open_mode_t { /** * enum p9_perm_t - 9P permissions - * @P9_DMDIR: mode bite for directories + * @P9_DMDIR: mode bit for directories * @P9_DMAPPEND: mode bit for is append-only * @P9_DMEXCL: mode bit for excluse use (only one open handle allowed) - * @P9_DMMOUNT: mode bite for mount points + * @P9_DMMOUNT: mode bit for mount points * @P9_DMAUTH: mode bit for authentication file * @P9_DMTMP: mode bit for non-backed-up files * @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u) @@ -362,7 +362,7 @@ struct p9_qid { }; /** - * struct p9_stat - file system metadata information + * struct p9_wstat - file system metadata information * @size: length prefix for this stat structure instance * @type: the type of the server (equivalent to a major number) * @dev: the sub-type of the server (equivalent to a minor number) @@ -687,10 +687,10 @@ struct p9_rwstat { * @size: prefixed length of the structure * @id: protocol operating identifier of type &p9_msg_t * @tag: transaction id of the request - * @offset: used by marshalling routines to track currentposition in buffer + * @offset: used by marshalling routines to track current position in buffer * @capacity: used by marshalling routines to track total malloc'd capacity * @pubuf: Payload user buffer given by the caller - * @pubuf: Payload kernel buffer given by the caller + * @pkbuf: Payload kernel buffer given by the caller * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write. * @private: For transport layer's use. * @sdata: payload @@ -714,7 +714,7 @@ struct p9_fcall { size_t pbuf_size; void *private; - uint8_t *sdata; + u8 *sdata; }; struct p9_idpool; @@ -728,7 +728,6 @@ void p9_idpool_put(int id, struct p9_idpool *p); int p9_idpool_check(int id, struct p9_idpool *p); int p9_error_init(void); -int p9_errstr2errno(char *, int); int p9_trans_fd_init(void); void p9_trans_fd_exit(void); #endif /* NET_9P_H */ diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 051a99f7976..d26d5e98a17 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -60,7 +60,7 @@ enum p9_trans_status { }; /** - * enum p9_req_status_t - virtio request status + * enum p9_req_status_t - status of a request * @REQ_STATUS_IDLE: request slot unused * @REQ_STATUS_ALLOC: request has been allocated but not sent * @REQ_STATUS_UNSENT: request waiting to be sent diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 8f08c736c4c..d8549fb9c74 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -41,6 +41,7 @@ * @pref: Preferences of this transport * @def: set if this transport should be considered the default * @create: member function to create a new connection on this transport + * @close: member function to discard a connection on this transport * @request: member function to issue a request to the transport * @cancel: member function to cancel a request (if it hasn't been sent) * @@ -48,7 +49,7 @@ * transport module with the 9P core network module and used by the client * to instantiate a new connection on a transport. * - * BUGS: the transport module list isn't protected. + * The transport module list is protected by v9fs_trans_lock. */ struct p9_trans_module { diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index 61e523af3c4..3d5d6db864f 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h @@ -45,6 +45,19 @@ typedef uint64_t blkif_sector_t; #define BLKIF_OP_WRITE_BARRIER 2 /* + * Recognised if "feature-flush-cache" is present in backend xenbus + * info. A flush will ask the underlying storage hardware to flush its + * non-volatile caches as appropriate. The "feature-flush-cache" node + * contains a boolean indicating whether flush requests are likely to + * succeed or fail. Either way, a flush request may fail at any time + * with BLKIF_RSP_EOPNOTSUPP if it is unsupported by the underlying + * block-device hardware. The boolean simply indicates whether or not it + * is worthwhile for the frontend to attempt flushes. If a backend does + * not recognise BLKIF_OP_WRITE_FLUSH_CACHE, it should *not* create the + * "feature-flush-cache" node! + */ +#define BLKIF_OP_FLUSH_DISKCACHE 3 +/* * Maximum scatter/gather segments per request. * This is carefully chosen so that sizeof(struct blkif_ring) <= PAGE_SIZE. * NB. This could be 12 if the ring indexes weren't stored in the same page. diff --git a/kernel/compat.c b/kernel/compat.c index 9214dcd087b..fc9eb093acd 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -293,6 +293,8 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) return compat_jiffies_to_clock_t(jiffies); } +#ifdef __ARCH_WANT_SYS_SIGPENDING + /* * Assumption: old_sigset_t and compat_old_sigset_t are both * types that can be passed to put_user()/get_user(). @@ -312,6 +314,10 @@ asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set) return ret; } +#endif + +#ifdef __ARCH_WANT_SYS_SIGPROCMASK + asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, compat_old_sigset_t __user *oset) { @@ -333,6 +339,8 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, return ret; } +#endif + asmlinkage long compat_sys_setrlimit(unsigned int resource, struct compat_rlimit __user *rlim) { diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index c541ee527ec..a9205e32a05 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -748,7 +748,7 @@ static inline void retrigger_next_event(void *arg) { } */ void clock_was_set(void) { -#ifdef CONFIG_HIGHRES_TIMERS +#ifdef CONFIG_HIGH_RES_TIMERS /* Retrigger the CPU local events everywhere */ on_each_cpu(retrigger_next_event, NULL, 1); #endif diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4bffd62c2f1..4fc92445a29 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1506,7 +1506,7 @@ static struct ctl_table fs_table[] = { static struct ctl_table debug_table[] = { #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \ - defined(CONFIG_S390) + defined(CONFIG_S390) || defined(CONFIG_TILE) { .procname = "exception-trace", .data = &show_unhandled_signals, diff --git a/lib/audit.c b/lib/audit.c index 8e7dc1c63aa..76bbed4a20e 100644 --- a/lib/audit.c +++ b/lib/audit.c @@ -36,8 +36,10 @@ int audit_classify_arch(int arch) int audit_classify_syscall(int abi, unsigned syscall) { switch(syscall) { +#ifdef __NR_open case __NR_open: return 2; +#endif #ifdef __NR_openat case __NR_openat: return 3; diff --git a/mm/backing-dev.c b/mm/backing-dev.c index befc87531e4..f032e6e1e09 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -63,10 +63,10 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) unsigned long background_thresh; unsigned long dirty_thresh; unsigned long bdi_thresh; - unsigned long nr_dirty, nr_io, nr_more_io, nr_wb; + unsigned long nr_dirty, nr_io, nr_more_io; struct inode *inode; - nr_wb = nr_dirty = nr_io = nr_more_io = 0; + nr_dirty = nr_io = nr_more_io = 0; spin_lock(&inode_wb_list_lock); list_for_each_entry(inode, &wb->b_dirty, i_wb_list) nr_dirty++; diff --git a/net/9p/Kconfig b/net/9p/Kconfig index 7ed75c7bd5d..d9ea09b11cf 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig @@ -3,8 +3,8 @@ # menuconfig NET_9P - depends on NET && EXPERIMENTAL - tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" + depends on NET + tristate "Plan 9 Resource Sharing Support (9P2000)" help If you say Y here, you will get experimental support for Plan 9 resource sharing via the 9P2000 protocol. @@ -16,8 +16,8 @@ menuconfig NET_9P if NET_9P config NET_9P_VIRTIO - depends on EXPERIMENTAL && VIRTIO - tristate "9P Virtio Transport (Experimental)" + depends on VIRTIO + tristate "9P Virtio Transport" help This builds support for a transports between guest partitions and a host partition. diff --git a/net/9p/client.c b/net/9p/client.c index ceab943dfc4..9e3b0e640da 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -92,9 +92,6 @@ static int get_protocol_version(const substring_t *name) return version; } -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); - /** * parse_options - parse mount options into client structure * @opts: options string passed from mount @@ -307,12 +304,13 @@ static int p9_tag_init(struct p9_client *c) c->tagpool = p9_idpool_create(); if (IS_ERR(c->tagpool)) { err = PTR_ERR(c->tagpool); - c->tagpool = NULL; goto error; } - - p9_idpool_get(c->tagpool); /* reserve tag 0 */ - + err = p9_idpool_get(c->tagpool); /* reserve tag 0 */ + if (err < 0) { + p9_idpool_destroy(c->tagpool); + goto error; + } c->max_tag = 0; error: return err; @@ -518,12 +516,15 @@ out_err: return err; } +static struct p9_req_t * +p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); + /** * p9_client_flush - flush (cancel) a request * @c: client state * @oldreq: request to cancel * - * This sents a flush for a particular requests and links + * This sents a flush for a particular request and links * the flush request to the original request. The current * code only supports a single flush request although the protocol * allows for multiple flush requests to be sent for a single request. @@ -789,11 +790,13 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) spin_lock_init(&clnt->lock); INIT_LIST_HEAD(&clnt->fidlist); - p9_tag_init(clnt); + err = p9_tag_init(clnt); + if (err < 0) + goto free_client; err = parse_opts(options, clnt); if (err < 0) - goto free_client; + goto destroy_tagpool; if (!clnt->trans_mod) clnt->trans_mod = v9fs_get_default_trans(); @@ -802,13 +805,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) err = -EPROTONOSUPPORT; P9_DPRINTK(P9_DEBUG_ERROR, "No transport defined or default transport\n"); - goto free_client; + goto destroy_tagpool; } clnt->fidpool = p9_idpool_create(); if (IS_ERR(clnt->fidpool)) { err = PTR_ERR(clnt->fidpool); - clnt->fidpool = NULL; goto put_trans; } @@ -834,6 +836,8 @@ destroy_fidpool: p9_idpool_destroy(clnt->fidpool); put_trans: v9fs_put_trans(clnt->trans_mod); +destroy_tagpool: + p9_idpool_destroy(clnt->tagpool); free_client: kfree(clnt); return ERR_PTR(err); @@ -1298,7 +1302,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, if (count < rsize) rsize = count; - /* Don't bother zerocopy form small IO (< 1024) */ + /* Don't bother zerocopy for small IO (< 1024) */ if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) { req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset, diff --git a/net/9p/mod.c b/net/9p/mod.c index cf8a4128cd5..72c39827505 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -139,7 +139,7 @@ void v9fs_put_trans(struct p9_trans_module *m) } /** - * v9fs_init - Initialize module + * init_p9 - Initialize module * */ static int __init init_p9(void) @@ -154,7 +154,7 @@ static int __init init_p9(void) } /** - * v9fs_init - shutdown module + * exit_p9 - shutdown module * */ diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 4a9084395d3..fdfdb5747f6 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -916,8 +916,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) sin_server.sin_family = AF_INET; sin_server.sin_addr.s_addr = in_aton(addr); sin_server.sin_port = htons(opts.port); - err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); - + err = __sock_create(read_pnet(¤t->nsproxy->net_ns), PF_INET, + SOCK_STREAM, IPPROTO_TCP, &csocket, 1); if (err) { P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); return err; @@ -954,7 +954,8 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) sun_server.sun_family = PF_UNIX; strcpy(sun_server.sun_path, addr); - err = sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); + err = __sock_create(read_pnet(¤t->nsproxy->net_ns), PF_UNIX, + SOCK_STREAM, 0, &csocket, 1); if (err < 0) { P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem creating socket\n"); return err; diff --git a/net/9p/util.c b/net/9p/util.c index da6af81e59d..9c1c9348ac3 100644 --- a/net/9p/util.c +++ b/net/9p/util.c @@ -93,7 +93,7 @@ int p9_idpool_get(struct p9_idpool *p) retry: if (idr_pre_get(&p->pool, GFP_NOFS) == 0) - return 0; + return -1; spin_lock_irqsave(&p->lock, flags); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e15a82ccc05..78b55f49de7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -76,7 +76,8 @@ const char *ceph_pr_addr(const struct sockaddr_storage *ss) break; default: - sprintf(s, "(unknown sockaddr family %d)", (int)ss->ss_family); + snprintf(s, MAX_ADDR_STR_LEN, "(unknown sockaddr family %d)", + (int)ss->ss_family); } return s; @@ -598,7 +599,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) * Connection negotiation. */ -static void prepare_connect_authorizer(struct ceph_connection *con) +static int prepare_connect_authorizer(struct ceph_connection *con) { void *auth_buf; int auth_len = 0; @@ -612,13 +613,20 @@ static void prepare_connect_authorizer(struct ceph_connection *con) con->auth_retry); mutex_lock(&con->mutex); + if (test_bit(CLOSED, &con->state) || + test_bit(OPENING, &con->state)) + return -EAGAIN; + con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); con->out_connect.authorizer_len = cpu_to_le32(auth_len); - con->out_kvec[con->out_kvec_left].iov_base = auth_buf; - con->out_kvec[con->out_kvec_left].iov_len = auth_len; - con->out_kvec_left++; - con->out_kvec_bytes += auth_len; + if (auth_len) { + con->out_kvec[con->out_kvec_left].iov_base = auth_buf; + con->out_kvec[con->out_kvec_left].iov_len = auth_len; + con->out_kvec_left++; + con->out_kvec_bytes += auth_len; + } + return 0; } /* @@ -640,9 +648,9 @@ static void prepare_write_banner(struct ceph_messenger *msgr, set_bit(WRITE_PENDING, &con->state); } -static void prepare_write_connect(struct ceph_messenger *msgr, - struct ceph_connection *con, - int after_banner) +static int prepare_write_connect(struct ceph_messenger *msgr, + struct ceph_connection *con, + int after_banner) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; @@ -683,7 +691,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr, con->out_more = 0; set_bit(WRITE_PENDING, &con->state); - prepare_connect_authorizer(con); + return prepare_connect_authorizer(con); } @@ -1065,8 +1073,10 @@ static void addr_set_port(struct sockaddr_storage *ss, int p) switch (ss->ss_family) { case AF_INET: ((struct sockaddr_in *)ss)->sin_port = htons(p); + break; case AF_INET6: ((struct sockaddr_in6 *)ss)->sin6_port = htons(p); + break; } } @@ -1216,6 +1226,7 @@ static int process_connect(struct ceph_connection *con) u64 sup_feat = con->msgr->supported_features; u64 req_feat = con->msgr->required_features; u64 server_feat = le64_to_cpu(con->in_reply.features); + int ret; dout("process_connect on %p tag %d\n", con, (int)con->in_tag); @@ -1250,7 +1261,9 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - prepare_write_connect(con->msgr, con, 0); + ret = prepare_write_connect(con->msgr, con, 0); + if (ret < 0) + return ret; prepare_read_connect(con); break; @@ -1277,6 +1290,9 @@ static int process_connect(struct ceph_connection *con) if (con->ops->peer_reset) con->ops->peer_reset(con); mutex_lock(&con->mutex); + if (test_bit(CLOSED, &con->state) || + test_bit(OPENING, &con->state)) + return -EAGAIN; break; case CEPH_MSGR_TAG_RETRY_SESSION: @@ -1341,7 +1357,9 @@ static int process_connect(struct ceph_connection *con) * to WAIT. This shouldn't happen if we are the * client. */ - pr_err("process_connect peer connecting WAIT\n"); + pr_err("process_connect got WAIT as client\n"); + con->error_msg = "protocol error, got WAIT as client"; + return -1; default: pr_err("connect protocol error, will retry\n"); @@ -1810,6 +1828,17 @@ static int try_read(struct ceph_connection *con) more: dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag, con->in_base_pos); + + /* + * process_connect and process_message drop and re-take + * con->mutex. make sure we handle a racing close or reopen. + */ + if (test_bit(CLOSED, &con->state) || + test_bit(OPENING, &con->state)) { + ret = -EAGAIN; + goto out; + } + if (test_bit(CONNECTING, &con->state)) { if (!test_bit(NEGOTIATING, &con->state)) { dout("try_read connecting\n"); @@ -1938,8 +1967,10 @@ static void con_work(struct work_struct *work) { struct ceph_connection *con = container_of(work, struct ceph_connection, work.work); + int ret; mutex_lock(&con->mutex); +restart: if (test_and_clear_bit(BACKOFF, &con->state)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, @@ -1969,18 +2000,31 @@ static void con_work(struct work_struct *work) con_close_socket(con); } - if (test_and_clear_bit(SOCK_CLOSED, &con->state) || - try_read(con) < 0 || - try_write(con) < 0) { - mutex_unlock(&con->mutex); - ceph_fault(con); /* error/fault path */ - goto done_unlocked; - } + if (test_and_clear_bit(SOCK_CLOSED, &con->state)) + goto fault; + + ret = try_read(con); + if (ret == -EAGAIN) + goto restart; + if (ret < 0) + goto fault; + + ret = try_write(con); + if (ret == -EAGAIN) + goto restart; + if (ret < 0) + goto fault; done: mutex_unlock(&con->mutex); done_unlocked: con->ops->put(con); + return; + +fault: + mutex_unlock(&con->mutex); + ceph_fault(con); /* error/fault path */ + goto done_unlocked; } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6b5dda1cb5d..6ea2b892f44 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -124,7 +124,7 @@ static void calc_layout(struct ceph_osd_client *osdc, ceph_calc_raw_layout(osdc, layout, vino.snap, off, plen, &bno, req, op); - sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno); + snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); req->r_oid_len = strlen(req->r_oid); } @@ -1421,6 +1421,15 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) done: downgrade_write(&osdc->map_sem); ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch); + + /* + * subscribe to subsequent osdmap updates if full to ensure + * we find out when we are no longer full and stop returning + * ENOSPC. + */ + if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL)) + ceph_monc_request_next_osdmap(&osdc->client->monc); + send_queued(osdc); up_read(&osdc->map_sem); wake_up_all(&osdc->client->auth_wq); @@ -1677,8 +1686,14 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, */ if (req->r_sent == 0) { rc = __map_request(osdc, req); - if (rc < 0) + if (rc < 0) { + if (nofail) { + dout("osdc_start_request failed map, " + " will retry %lld\n", req->r_tid); + rc = 0; + } goto out_unlock; + } if (req->r_osd == NULL) { dout("send_request %p no up osds in pg\n", req); ceph_monc_request_next_osdmap(&osdc->client->monc); diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 71603ac3dff..e97c3588c3e 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -765,7 +765,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, } map->epoch++; - map->modified = map->modified; + map->modified = modified; if (newcrush) { if (map->crush) crush_destroy(map->crush); @@ -830,15 +830,20 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, map->osd_addr[osd] = addr; } - /* new_down */ + /* new_state */ ceph_decode_32_safe(p, end, len, bad); while (len--) { u32 osd; + u8 xorstate; ceph_decode_32_safe(p, end, osd, bad); + xorstate = **(u8 **)p; (*p)++; /* clean flag */ - pr_info("osd%d down\n", osd); + if (xorstate == 0) + xorstate = CEPH_OSD_UP; + if (xorstate & CEPH_OSD_UP) + pr_info("osd%d down\n", osd); if (osd < map->max_osd) - map->osd_state[osd] &= ~CEPH_OSD_UP; + map->osd_state[osd] ^= xorstate; } /* new_weight */ diff --git a/scripts/checkversion.pl b/scripts/checkversion.pl index b444e89a009..5e490a8ceca 100755 --- a/scripts/checkversion.pl +++ b/scripts/checkversion.pl @@ -12,6 +12,7 @@ $| = 1; my $debugging; foreach my $file (@ARGV) { + next if $file =~ "include/linux/version\.h"; # Open this file. open( my $f, '<', $file ) or die "Can't open $file: $!\n"; diff --git a/scripts/export_report.pl b/scripts/export_report.pl index 04dce7c15f8..8f79b701de8 100644 --- a/scripts/export_report.pl +++ b/scripts/export_report.pl @@ -25,11 +25,12 @@ sub alphabetically { sub print_depends_on { my ($href) = @_; print "\n"; - while (my ($mod, $list) = each %$href) { + for my $mod (sort keys %$href) { + my $list = $href->{$mod}; print "\t$mod:\n"; foreach my $sym (sort numerically @{$list}) { my ($symbol, $no) = split /\s+/, $sym; - printf("\t\t%-25s\t%-25d\n", $symbol, $no); + printf("\t\t%-25s\n", $symbol); } print "\n"; } @@ -49,8 +50,14 @@ sub usage { } sub collectcfiles { - my @file - = `cat .tmp_versions/*.mod | grep '.*\.ko\$' | sed s/\.ko$/.mod.c/`; + my @file; + while (<.tmp_versions/*.mod>) { + open my $fh, '<', $_ or die "cannot open $_: $!\n"; + push (@file, + grep s/\.ko/.mod.c/, # change the suffix + grep m/.+\.ko/, # find the .ko path + <$fh>); # lines in opened file + } chomp @file; return @file; } @@ -95,6 +102,8 @@ close($module_symvers); # # collect the usage count of each symbol. # +my $modversion_warnings = 0; + foreach my $thismod (@allcfiles) { my $module; @@ -125,7 +134,8 @@ foreach my $thismod (@allcfiles) { } } if ($state != 2) { - print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n"; + warn "WARNING:$thismod is not built with CONFIG_MODVERSIONS enabled\n"; + $modversion_warnings++; } close($module); } @@ -159,8 +169,12 @@ printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel modules. Each module lists the modules, and the symbols from that module that it uses. Each listed symbol reports the number of modules using it\n"); +print "\nNOTE: Got $modversion_warnings CONFIG_MODVERSIONS warnings\n\n" + if $modversion_warnings; + print "~"x80 , "\n"; -while (my ($thismod, $list) = each %MODULE) { +for my $thismod (sort keys %MODULE) { + my $list = $MODULE{$thismod}; my %depends; $thismod =~ s/\.mod\.c/.ko/; print "\t\t\t$thismod\n"; diff --git a/scripts/package/Makefile b/scripts/package/Makefile index a834b935f53..006960ebbce 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -26,9 +26,9 @@ RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ else echo rpm; fi) # Remove hyphens since they have special meaning in RPM filenames -KERNELPATH := kernel-$(subst -,,$(KERNELRELEASE)) +KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE)) MKSPEC := $(srctree)/scripts/package/mkspec -PREV := set -e; cd ..; +PREV := set -e; cd -P ..; # rpm-pkg # --------------------------------------------------------------------------- diff --git a/scripts/package/mkspec b/scripts/package/mkspec index e1c1d5b8ca7..4bf17ddf7c7 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -22,7 +22,7 @@ if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then fi PROVIDES="$PROVIDES kernel-$KERNELRELEASE" -__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-//g"` +__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-/_/g"` echo "Name: kernel" echo "Summary: The Linux Kernel" @@ -47,6 +47,18 @@ echo "" echo "%description" echo "The Linux Kernel, the operating system core itself" echo "" +echo "%package headers" +echo "Summary: Header files for the Linux kernel for use by glibc" +echo "Group: Development/System" +echo "Obsoletes: kernel-headers" +echo "Provides: kernel-headers = %{version}" +echo "%description headers" +echo "Kernel-headers includes the C header files that specify the interface" +echo "between the Linux kernel and userspace libraries and programs. The" +echo "header files define structures and constants that are needed for" +echo "building most standard programs and are also needed for rebuilding the" +echo "glibc package." +echo "" if ! $PREBUILT; then echo "%prep" @@ -83,6 +95,7 @@ echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" echo "%endif" echo "%endif" +echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_install' echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE" @@ -105,3 +118,7 @@ echo "/lib/modules/$KERNELRELEASE" echo "/lib/firmware" echo "/boot/*" echo "" +echo "%files headers" +echo '%defattr (-, root, root)' +echo "/usr/include" +echo "" diff --git a/scripts/patch-kernel b/scripts/patch-kernel index 46a59cae3a0..20fb25c2338 100755 --- a/scripts/patch-kernel +++ b/scripts/patch-kernel @@ -250,7 +250,7 @@ while : # incrementing SUBLEVEL (s in v.p.s) do CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" EXTRAVER= - if [ $STOPFULLVERSION = $CURRENTFULLVERSION ]; then + if [ x$STOPFULLVERSION = x$CURRENTFULLVERSION ]; then echo "Stopping at $CURRENTFULLVERSION base as requested." break fi |