diff --git a/[refs] b/[refs] index 505dcf7ab400..45650265acea 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 10be289d07a5327e2e7764bb3ccbffa215075103 +refs/heads/master: d7dde8c191d136415819e4456e21f2b0cc00c326 diff --git a/trunk/Documentation/DMA-attributes.txt b/trunk/Documentation/DMA-attributes.txt index e59480db9ee0..f50309081ac7 100644 --- a/trunk/Documentation/DMA-attributes.txt +++ b/trunk/Documentation/DMA-attributes.txt @@ -91,12 +91,3 @@ transferred to 'device' domain. This attribute can be also used for dma_unmap_{single,page,sg} functions family to force buffer to stay in device domain after releasing a mapping for it. Use this attribute with care! - -DMA_ATTR_FORCE_CONTIGUOUS -------------------------- - -By default DMA-mapping subsystem is allowed to assemble the buffer -allocated by dma_alloc_attrs() function from individual pages if it can -be mapped as contiguous chunk into device dma address space. By -specifing this attribute the allocated buffer is forced to be contiguous -also in physical memory. diff --git a/trunk/Documentation/DocBook/drm.tmpl b/trunk/Documentation/DocBook/drm.tmpl index 4ee2304f82f9..b0300529ab13 100644 --- a/trunk/Documentation/DocBook/drm.tmpl +++ b/trunk/Documentation/DocBook/drm.tmpl @@ -1141,13 +1141,23 @@ int max_width, max_height; the page_flip operation will be called with a non-NULL event argument pointing to a drm_pending_vblank_event instance. Upon page - flip completion the driver must call drm_send_vblank_event - to fill in the event and send to wake up any waiting processes. - This can be performed with + flip completion the driver must fill the + event::event + sequence, tv_sec + and tv_usec fields with the associated + vertical blanking count and timestamp, add the event to the + drm_file list of events to be signaled, and wake + up any waiting process. This can be performed with event.sequence = drm_vblank_count_and_time(..., &now); + event->event.tv_sec = now.tv_sec; + event->event.tv_usec = now.tv_usec; + spin_lock_irqsave(&dev->event_lock, flags); - ... - drm_send_vblank_event(dev, pipe, event); + list_add_tail(&event->base.link, &event->base.file_priv->event_list); + wake_up_interruptible(&event->base.file_priv->event_wait); spin_unlock_irqrestore(&dev->event_lock, flags); ]]> @@ -1611,10 +1621,10 @@ void intel_crt_init(struct drm_device *dev) - + - Mode Setting Helper Functions + Mid-layer Helper Functions The CRTC, encoder and connector functions provided by the drivers implement the DRM API. They're called by the DRM core and ioctl handlers @@ -2096,21 +2106,6 @@ void intel_crt_init(struct drm_device *dev) - - Modeset Helper Functions Reference -!Edrivers/gpu/drm/drm_crtc_helper.c - - - fbdev Helper Functions Reference -!Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers -!Edrivers/gpu/drm/drm_fb_helper.c - - - Display Port Helper Functions Reference -!Pdrivers/gpu/drm/drm_dp_helper.c dp helpers -!Iinclude/drm/drm_dp_helper.h -!Edrivers/gpu/drm/drm_dp_helper.c - diff --git a/trunk/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/trunk/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt deleted file mode 100644 index b4fa934ae3a2..000000000000 --- a/trunk/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt +++ /dev/null @@ -1,191 +0,0 @@ -NVIDIA Tegra host1x - -Required properties: -- compatible: "nvidia,tegra-host1x" -- reg: Physical base address and length of the controller's registers. -- interrupts: The interrupt outputs from the controller. -- #address-cells: The number of cells used to represent physical base addresses - in the host1x address space. Should be 1. -- #size-cells: The number of cells used to represent the size of an address - range in the host1x address space. Should be 1. -- ranges: The mapping of the host1x address space to the CPU address space. - -The host1x top-level node defines a number of children, each representing one -of the following host1x client modules: - -- mpe: video encoder - - Required properties: - - compatible: "nvidia,tegra-mpe" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- vi: video input - - Required properties: - - compatible: "nvidia,tegra-vi" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- epp: encoder pre-processor - - Required properties: - - compatible: "nvidia,tegra-epp" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- isp: image signal processor - - Required properties: - - compatible: "nvidia,tegra-isp" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- gr2d: 2D graphics engine - - Required properties: - - compatible: "nvidia,tegra-gr2d" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- gr3d: 3D graphics engine - - Required properties: - - compatible: "nvidia,tegra-gr3d" - - reg: Physical base address and length of the controller's registers. - -- dc: display controller - - Required properties: - - compatible: "nvidia,tegra-dc" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - - Each display controller node has a child node, named "rgb", that represents - the RGB output associated with the controller. It can take the following - optional properties: - - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing - - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection - - nvidia,edid: supplies a binary EDID blob - -- hdmi: High Definition Multimedia Interface - - Required properties: - - compatible: "nvidia,tegra-hdmi" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - - vdd-supply: regulator for supply voltage - - pll-supply: regulator for PLL - - Optional properties: - - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing - - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection - - nvidia,edid: supplies a binary EDID blob - -- tvo: TV encoder output - - Required properties: - - compatible: "nvidia,tegra-tvo" - - reg: Physical base address and length of the controller's registers. - - interrupts: The interrupt outputs from the controller. - -- dsi: display serial interface - - Required properties: - - compatible: "nvidia,tegra-dsi" - - reg: Physical base address and length of the controller's registers. - -Example: - -/ { - ... - - host1x { - compatible = "nvidia,tegra20-host1x", "simple-bus"; - reg = <0x50000000 0x00024000>; - interrupts = <0 65 0x04 /* mpcore syncpt */ - 0 67 0x04>; /* mpcore general */ - - #address-cells = <1>; - #size-cells = <1>; - - ranges = <0x54000000 0x54000000 0x04000000>; - - mpe { - compatible = "nvidia,tegra20-mpe"; - reg = <0x54040000 0x00040000>; - interrupts = <0 68 0x04>; - }; - - vi { - compatible = "nvidia,tegra20-vi"; - reg = <0x54080000 0x00040000>; - interrupts = <0 69 0x04>; - }; - - epp { - compatible = "nvidia,tegra20-epp"; - reg = <0x540c0000 0x00040000>; - interrupts = <0 70 0x04>; - }; - - isp { - compatible = "nvidia,tegra20-isp"; - reg = <0x54100000 0x00040000>; - interrupts = <0 71 0x04>; - }; - - gr2d { - compatible = "nvidia,tegra20-gr2d"; - reg = <0x54140000 0x00040000>; - interrupts = <0 72 0x04>; - }; - - gr3d { - compatible = "nvidia,tegra20-gr3d"; - reg = <0x54180000 0x00040000>; - }; - - dc@54200000 { - compatible = "nvidia,tegra20-dc"; - reg = <0x54200000 0x00040000>; - interrupts = <0 73 0x04>; - - rgb { - status = "disabled"; - }; - }; - - dc@54240000 { - compatible = "nvidia,tegra20-dc"; - reg = <0x54240000 0x00040000>; - interrupts = <0 74 0x04>; - - rgb { - status = "disabled"; - }; - }; - - hdmi { - compatible = "nvidia,tegra20-hdmi"; - reg = <0x54280000 0x00040000>; - interrupts = <0 75 0x04>; - status = "disabled"; - }; - - tvo { - compatible = "nvidia,tegra20-tvo"; - reg = <0x542c0000 0x00040000>; - interrupts = <0 76 0x04>; - status = "disabled"; - }; - - dsi { - compatible = "nvidia,tegra20-dsi"; - reg = <0x54300000 0x00040000>; - status = "disabled"; - }; - }; - - ... -}; diff --git a/trunk/Documentation/devicetree/bindings/mfd/stmpe.txt b/trunk/Documentation/devicetree/bindings/mfd/stmpe.txt deleted file mode 100644 index 56edb5520685..000000000000 --- a/trunk/Documentation/devicetree/bindings/mfd/stmpe.txt +++ /dev/null @@ -1,28 +0,0 @@ -* ST Microelectronics STMPE Multi-Functional Device - -STMPE is an MFD device which may expose the following inbuilt devices: gpio, -keypad, touchscreen, adc, pwm, rotator. - -Required properties: - - compatible : "st,stmpe[610|801|811|1601|2401|2403]" - - reg : I2C/SPI address of the device - -Optional properties: - - interrupts : The interrupt outputs from the controller - - interrupt-controller : Marks the device node as an interrupt controller - - interrupt-parent : Specifies which IRQ controller we're connected to - - wakeup-source : Marks the input device as wakable - - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024 - -Example: - - stmpe1601: stmpe1601@40 { - compatible = "st,stmpe1601"; - reg = <0x40>; - interrupts = <26 0x4>; - interrupt-parent = <&gpio6>; - interrupt-controller; - - wakeup-source; - st,autosleep-timeout = <1024>; - }; diff --git a/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt b/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt index 4f05d208c95c..d316fb895daf 100644 --- a/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt +++ b/trunk/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -11,9 +11,6 @@ Required properties: using the standard binding for regulators found at Documentation/devicetree/bindings/regulator/regulator.txt. -Optional properties: -- ti,pmic-shutdown-controller: Telling the PMIC to shutdown on PWR_EN toggle. - The valid names for regulators are: tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4 @@ -23,7 +20,6 @@ Example: tps: tps@24 { compatible = "ti,tps65217"; - ti,pmic-shutdown-controller; regulators { dcdc1_reg: dcdc1 { diff --git a/trunk/Documentation/filesystems/ext4.txt b/trunk/Documentation/filesystems/ext4.txt index 34ea4f1fa6ea..104322bf378c 100644 --- a/trunk/Documentation/filesystems/ext4.txt +++ b/trunk/Documentation/filesystems/ext4.txt @@ -200,9 +200,12 @@ inode_readahead_blks=n This tuning parameter controls the maximum table readahead algorithm will pre-read into the buffer cache. The default value is 32 blocks. -nouser_xattr Disables Extended User Attributes. See the - attr(5) manual page and http://acl.bestbits.at/ - for more information about extended attributes. +nouser_xattr Disables Extended User Attributes. If you have extended + attribute support enabled in the kernel configuration + (CONFIG_EXT4_FS_XATTR), extended attribute support + is enabled by default on mount. See the attr(5) manual + page and http://acl.bestbits.at/ for more information + about extended attributes. noacl This option disables POSIX Access Control List support. If ACL support is enabled in the kernel diff --git a/trunk/Documentation/i2c/smbus-protocol b/trunk/Documentation/i2c/smbus-protocol index d1f22618e14b..49f5b680809d 100644 --- a/trunk/Documentation/i2c/smbus-protocol +++ b/trunk/Documentation/i2c/smbus-protocol @@ -23,12 +23,6 @@ don't match these function names. For some of the operations which pass a single data byte, the functions using SMBus protocol operation names execute a different protocol operation entirely. -Each transaction type corresponds to a functionality flag. Before calling a -transaction function, a device driver should always check (just once) for -the corresponding functionality flag to ensure that the underlying I2C -adapter supports the transaction in question. See - for the details. - Key to symbols ============== @@ -55,8 +49,6 @@ This sends a single bit to the device, at the place of the Rd/Wr bit. A Addr Rd/Wr [A] P -Functionality flag: I2C_FUNC_SMBUS_QUICK - SMBus Receive Byte: i2c_smbus_read_byte() ========================================== @@ -68,8 +60,6 @@ the previous SMBus command. S Addr Rd [A] [Data] NA P -Functionality flag: I2C_FUNC_SMBUS_READ_BYTE - SMBus Send Byte: i2c_smbus_write_byte() ======================================== @@ -79,8 +69,6 @@ to a device. See Receive Byte for more information. S Addr Wr [A] Data [A] P -Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE - SMBus Read Byte: i2c_smbus_read_byte_data() ============================================ @@ -90,8 +78,6 @@ The register is specified through the Comm byte. S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P -Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA - SMBus Read Word: i2c_smbus_read_word_data() ============================================ @@ -102,8 +88,6 @@ byte. But this time, the data is a complete word (16 bits). S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P -Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA - Note the convenience function i2c_smbus_read_word_swapped is available for reads where the two data bytes are the other way around (not SMBus compliant, but very popular.) @@ -118,8 +102,6 @@ the Read Byte operation. S Addr Wr [A] Comm [A] Data [A] P -Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA - SMBus Write Word: i2c_smbus_write_word_data() ============================================== @@ -130,8 +112,6 @@ specified through the Comm byte. S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P -Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA - Note the convenience function i2c_smbus_write_word_swapped is available for writes where the two data bytes are the other way around (not SMBus compliant, but very popular.) @@ -146,8 +126,6 @@ This command selects a device register (through the Comm byte), sends S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P -Functionality flag: I2C_FUNC_SMBUS_PROC_CALL - SMBus Block Read: i2c_smbus_read_block_data() ============================================== @@ -159,8 +137,6 @@ of data is specified by the device in the Count byte. S Addr Wr [A] Comm [A] S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P -Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA - SMBus Block Write: i2c_smbus_write_block_data() ================================================ @@ -171,8 +147,6 @@ Comm byte. The amount of data is specified in the Count byte. S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P -Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA - SMBus Block Write - Block Read Process Call =========================================== @@ -186,8 +160,6 @@ This command selects a device register (through the Comm byte), sends S Addr Wr [A] Comm [A] Count [A] Data [A] ... S Addr Rd [A] [Count] A [Data] ... A P -Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL - SMBus Host Notify ================= @@ -257,7 +229,15 @@ designated register that is specified through the Comm byte. S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P -Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK + +I2C Block Read (2 Comm bytes) +============================= + +This command reads a block of bytes from a device, from a +designated register that is specified through the two Comm bytes. + +S Addr Wr [A] Comm1 [A] Comm2 [A] + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P I2C Block Write: i2c_smbus_write_i2c_block_data() @@ -269,5 +249,3 @@ Comm byte. Note that command lengths of 0, 2, or more bytes are supported as they are indistinguishable from data. S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P - -Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index ea8e5b485576..20e248cc03a9 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -2032,9 +2032,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. nr_uarts= [SERIAL] maximum number of UARTs to be registered. - numa_balancing= [KNL,X86] Enable or disable automatic NUMA balancing. - Allowed values are enable and disable - numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA. one of ['zone', 'node', 'default'] can be specified This can be set from sysctl after boot. diff --git a/trunk/Documentation/kref.txt b/trunk/Documentation/kref.txt index ddf85a5dde0c..48ba715d5a63 100644 --- a/trunk/Documentation/kref.txt +++ b/trunk/Documentation/kref.txt @@ -213,91 +213,3 @@ presentation on krefs, which can be found at: and: http://www.kroah.com/linux/talks/ols_2004_kref_talk/ - -The above example could also be optimized using kref_get_unless_zero() in -the following way: - -static struct my_data *get_entry() -{ - struct my_data *entry = NULL; - mutex_lock(&mutex); - if (!list_empty(&q)) { - entry = container_of(q.next, struct my_data, link); - if (!kref_get_unless_zero(&entry->refcount)) - entry = NULL; - } - mutex_unlock(&mutex); - return entry; -} - -static void release_entry(struct kref *ref) -{ - struct my_data *entry = container_of(ref, struct my_data, refcount); - - mutex_lock(&mutex); - list_del(&entry->link); - mutex_unlock(&mutex); - kfree(entry); -} - -static void put_entry(struct my_data *entry) -{ - kref_put(&entry->refcount, release_entry); -} - -Which is useful to remove the mutex lock around kref_put() in put_entry(), but -it's important that kref_get_unless_zero is enclosed in the same critical -section that finds the entry in the lookup table, -otherwise kref_get_unless_zero may reference already freed memory. -Note that it is illegal to use kref_get_unless_zero without checking its -return value. If you are sure (by already having a valid pointer) that -kref_get_unless_zero() will return true, then use kref_get() instead. - -The function kref_get_unless_zero also makes it possible to use rcu -locking for lookups in the above example: - -struct my_data -{ - struct rcu_head rhead; - . - struct kref refcount; - . - . -}; - -static struct my_data *get_entry_rcu() -{ - struct my_data *entry = NULL; - rcu_read_lock(); - if (!list_empty(&q)) { - entry = container_of(q.next, struct my_data, link); - if (!kref_get_unless_zero(&entry->refcount)) - entry = NULL; - } - rcu_read_unlock(); - return entry; -} - -static void release_entry_rcu(struct kref *ref) -{ - struct my_data *entry = container_of(ref, struct my_data, refcount); - - mutex_lock(&mutex); - list_del_rcu(&entry->link); - mutex_unlock(&mutex); - kfree_rcu(entry, rhead); -} - -static void put_entry(struct my_data *entry) -{ - kref_put(&entry->refcount, release_entry_rcu); -} - -But note that the struct kref member needs to remain in valid memory for a -rcu grace period after release_entry_rcu was called. That can be accomplished -by using kfree_rcu(entry, rhead) as done above, or by calling synchronize_rcu() -before using kfree, but note that synchronize_rcu() may sleep for a -substantial amount of time. - - -Thomas Hellstrom diff --git a/trunk/Documentation/prctl/seccomp_filter.txt b/trunk/Documentation/prctl/seccomp_filter.txt index 1e469ef75778..597c3c581375 100644 --- a/trunk/Documentation/prctl/seccomp_filter.txt +++ b/trunk/Documentation/prctl/seccomp_filter.txt @@ -95,15 +95,12 @@ SECCOMP_RET_KILL: SECCOMP_RET_TRAP: Results in the kernel sending a SIGSYS signal to the triggering - task without executing the system call. siginfo->si_call_addr - will show the address of the system call instruction, and - siginfo->si_syscall and siginfo->si_arch will indicate which - syscall was attempted. The program counter will be as though - the syscall happened (i.e. it will not point to the syscall - instruction). The return value register will contain an arch- - dependent value -- if resuming execution, set it to something - sensible. (The architecture dependency is because replacing - it with -ENOSYS could overwrite some useful information.) + task without executing the system call. The kernel will + rollback the register state to just before the system call + entry such that a signal handler in the task will be able to + inspect the ucontext_t->uc_mcontext registers and emulate + system call success or failure upon return from the signal + handler. The SECCOMP_RET_DATA portion of the return value will be passed as si_errno. @@ -126,18 +123,6 @@ SECCOMP_RET_TRACE: the BPF program return value will be available to the tracer via PTRACE_GETEVENTMSG. - The tracer can skip the system call by changing the syscall number - to -1. Alternatively, the tracer can change the system call - requested by changing the system call to a valid syscall number. If - the tracer asks to skip the system call, then the system call will - appear to return the value that the tracer puts in the return value - register. - - The seccomp check will not be run again after the tracer is - notified. (This means that seccomp-based sandboxes MUST NOT - allow use of ptrace, even of other sandboxed processes, without - extreme care; ptracers can use this mechanism to escape.) - SECCOMP_RET_ALLOW: Results in the system call being executed. @@ -176,50 +161,3 @@ architecture supports both ptrace_event and seccomp, it will be able to support seccomp filter with minor fixup: SIGSYS support and seccomp return value checking. Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER to its arch-specific Kconfig. - - - -Caveats -------- - -The vDSO can cause some system calls to run entirely in userspace, -leading to surprises when you run programs on different machines that -fall back to real syscalls. To minimize these surprises on x86, make -sure you test with -/sys/devices/system/clocksource/clocksource0/current_clocksource set to -something like acpi_pm. - -On x86-64, vsyscall emulation is enabled by default. (vsyscalls are -legacy variants on vDSO calls.) Currently, emulated vsyscalls will honor seccomp, with a few oddities: - -- A return value of SECCOMP_RET_TRAP will set a si_call_addr pointing to - the vsyscall entry for the given call and not the address after the - 'syscall' instruction. Any code which wants to restart the call - should be aware that (a) a ret instruction has been emulated and (b) - trying to resume the syscall will again trigger the standard vsyscall - emulation security checks, making resuming the syscall mostly - pointless. - -- A return value of SECCOMP_RET_TRACE will signal the tracer as usual, - but the syscall may not be changed to another system call using the - orig_rax register. It may only be changed to -1 order to skip the - currently emulated call. Any other change MAY terminate the process. - The rip value seen by the tracer will be the syscall entry address; - this is different from normal behavior. The tracer MUST NOT modify - rip or rsp. (Do not rely on other changes terminating the process. - They might work. For example, on some kernels, choosing a syscall - that only exists in future kernels will be correctly emulated (by - returning -ENOSYS). - -To detect this quirky behavior, check for addr & ~0x0C00 == -0xFFFFFFFFFF600000. (For SECCOMP_RET_TRACE, use rip. For -SECCOMP_RET_TRAP, use siginfo->si_call_addr.) Do not check any other -condition: future kernels may improve vsyscall emulation and current -kernels in vsyscall=native mode will behave differently, but the -instructions at 0xF...F600{0,4,8,C}00 will not be system calls in these -cases. - -Note that modern systems are unlikely to use vsyscalls at all -- they -are a legacy feature and they are considerably slower than standard -syscalls. New code will use the vDSO, and vDSO-issued system calls -are indistinguishable from normal system calls. diff --git a/trunk/Documentation/security/keys.txt b/trunk/Documentation/security/keys.txt index 7b4145d00452..7d9ca92022d8 100644 --- a/trunk/Documentation/security/keys.txt +++ b/trunk/Documentation/security/keys.txt @@ -994,23 +994,6 @@ payload contents" for more information. reference pointer if successful. -(*) A keyring can be created by: - - struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, - const struct cred *cred, - key_perm_t perm, - unsigned long flags, - struct key *dest); - - This creates a keyring with the given attributes and returns it. If dest - is not NULL, the new keyring will be linked into the keyring to which it - points. No permission checks are made upon the destination keyring. - - Error EDQUOT can be returned if the keyring would overload the quota (pass - KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted - towards the user's quota). Error ENOMEM can also be returned. - - (*) To check the validity of a key, this function can be called: int validate_key(struct key *key); diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 6892b26025ba..f71d2f901a69 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2549,15 +2549,6 @@ S: Supported F: drivers/gpu/drm/exynos F: include/drm/exynos* -DRM DRIVERS FOR NVIDIA TEGRA -M: Thierry Reding -L: dri-devel@lists.freedesktop.org -L: linux-tegra@vger.kernel.org -T: git git://gitorious.org/thierryreding/linux.git -S: Maintained -F: drivers/gpu/drm/tegra/ -F: Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt - DSCC4 DRIVER M: Francois Romieu L: netdev@vger.kernel.org @@ -3721,7 +3712,7 @@ I2C/SMBUS STUB DRIVER M: "Mark M. Hoffman" L: linux-i2c@vger.kernel.org S: Maintained -F: drivers/i2c/i2c-stub.c +F: drivers/i2c/busses/i2c-stub.c I2C SUBSYSTEM M: Wolfram Sang diff --git a/trunk/arch/arm/boot/dts/Makefile b/trunk/arch/arm/boot/dts/Makefile index ca6fb8e7f17d..0f441740c22a 100644 --- a/trunk/arch/arm/boot/dts/Makefile +++ b/trunk/arch/arm/boot/dts/Makefile @@ -131,8 +131,8 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \ spear320-evb.dtb \ spear320-hmi.dtb dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb -dtb-$(CONFIG_ARCH_SUNXI) += sun4i-a10-cubieboard.dtb \ - sun5i-a13-olinuxino.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun4i-cubieboard.dtb \ + sun5i-olinuxino.dtb dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-medcom-wide.dtb \ tegra20-paz00.dtb \ diff --git a/trunk/arch/arm/boot/dts/sun4i-cubieboard.dts b/trunk/arch/arm/boot/dts/sun4i-cubieboard.dts index 5cab82540437..f4ca126ad994 100644 --- a/trunk/arch/arm/boot/dts/sun4i-cubieboard.dts +++ b/trunk/arch/arm/boot/dts/sun4i-cubieboard.dts @@ -11,11 +11,11 @@ */ /dts-v1/; -/include/ "sun4i-a10.dtsi" +/include/ "sun4i.dtsi" / { model = "Cubietech Cubieboard"; - compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10"; + compatible = "cubietech,cubieboard", "allwinner,sun4i"; aliases { serial0 = &uart0; diff --git a/trunk/arch/arm/boot/dts/sun5i-olinuxino.dts b/trunk/arch/arm/boot/dts/sun5i-olinuxino.dts index 498a091a4ea2..d6ff889a5d87 100644 --- a/trunk/arch/arm/boot/dts/sun5i-olinuxino.dts +++ b/trunk/arch/arm/boot/dts/sun5i-olinuxino.dts @@ -12,11 +12,11 @@ */ /dts-v1/; -/include/ "sun5i-a13.dtsi" +/include/ "sun5i.dtsi" / { model = "Olimex A13-Olinuxino"; - compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13"; + compatible = "olimex,a13-olinuxino", "allwinner,sun5i"; chosen { bootargs = "earlyprintk console=ttyS0,115200"; diff --git a/trunk/arch/arm/mach-davinci/board-da850-evm.c b/trunk/arch/arm/mach-davinci/board-da850-evm.c index 0299915575a8..7211772edd9d 100644 --- a/trunk/arch/arm/mach-davinci/board-da850-evm.c +++ b/trunk/arch/arm/mach-davinci/board-da850-evm.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/mach-exynos/common.h b/trunk/arch/arm/mach-exynos/common.h index 04744f9c120f..dac146df79ac 100644 --- a/trunk/arch/arm/mach-exynos/common.h +++ b/trunk/arch/arm/mach-exynos/common.h @@ -25,7 +25,7 @@ void exynos_init_late(void); #ifdef CONFIG_PM_GENERIC_DOMAINS int exynos_pm_late_initcall(void); #else -static inline int exynos_pm_late_initcall(void) { return 0; } +static int exynos_pm_late_initcall(void) { return 0; } #endif #ifdef CONFIG_ARCH_EXYNOS4 diff --git a/trunk/arch/arm/mach-omap2/cclock44xx_data.c b/trunk/arch/arm/mach-omap2/cclock44xx_data.c index 5789a5e25563..aa56c3e5bb34 100644 --- a/trunk/arch/arm/mach-omap2/cclock44xx_data.c +++ b/trunk/arch/arm/mach-omap2/cclock44xx_data.c @@ -40,14 +40,6 @@ #define OMAP4430_MODULEMODE_HWCTRL_SHIFT 0 #define OMAP4430_MODULEMODE_SWCTRL_SHIFT 1 -/* - * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section - * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK - * must be set to 196.608 MHz" and hence, the DPLL locked frequency is - * half of this value. - */ -#define OMAP4_DPLL_ABE_DEFFREQ 98304000 - /* Root clocks */ DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0); @@ -132,8 +124,6 @@ static struct dpll_data dpll_abe_dd = { .enable_mask = OMAP4430_DPLL_EN_MASK, .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, - .m4xen_mask = OMAP4430_DPLL_REGM4XEN_MASK, - .lpmode_mask = OMAP4430_DPLL_LPMODE_EN_MASK, .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, @@ -243,7 +233,7 @@ static struct dpll_data dpll_core_dd = { static const char *dpll_core_ck_parents[] = { - "sys_clkin_ck", "core_hsd_byp_clk_mux_ck" + "sys_clkin_ck", }; static struct clk dpll_core_ck; @@ -296,9 +286,9 @@ DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT, OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, - 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, OMAP4430_CLKSEL_0_1_SHIFT, - OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL); +DEFINE_CLK_OMAP_HSDIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", + &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, + OMAP4430_CLKSEL_0_1_MASK); DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT, @@ -373,21 +363,8 @@ static struct dpll_data dpll_iva_dd = { .min_divider = 1, }; -static const char *dpll_iva_ck_parents[] = { - "sys_clkin_ck", "iva_hsd_byp_clk_mux_ck" -}; - static struct clk dpll_iva_ck; -static const struct clk_ops dpll_ck_ops = { - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, - .recalc_rate = &omap3_dpll_recalc, - .round_rate = &omap2_dpll_round_rate, - .set_rate = &omap3_noncore_dpll_set_rate, - .get_parent = &omap2_init_dpll_parent, -}; - static struct clk_hw_omap dpll_iva_ck_hw = { .hw = { .clk = &dpll_iva_ck, @@ -396,7 +373,7 @@ static struct clk_hw_omap dpll_iva_ck_hw = { .ops = &clkhwops_omap3_dpll, }; -DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_iva_ck_parents, dpll_ck_ops); +DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_core_ck_parents, dpll_abe_ck_ops); static const char *dpll_iva_x2_ck_parents[] = { "dpll_iva_ck", @@ -439,10 +416,6 @@ static struct dpll_data dpll_mpu_dd = { .min_divider = 1, }; -static const char *dpll_mpu_ck_parents[] = { - "sys_clkin_ck", "div_mpu_hs_clk" -}; - static struct clk dpll_mpu_ck; static struct clk_hw_omap dpll_mpu_ck_hw = { @@ -453,7 +426,7 @@ static struct clk_hw_omap dpll_mpu_ck_hw = { .ops = &clkhwops_omap3_dpll, }; -DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_mpu_ck_parents, dpll_ck_ops); +DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_abe_ck_ops); DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2); @@ -491,9 +464,6 @@ static struct dpll_data dpll_per_dd = { .min_divider = 1, }; -static const char *dpll_per_ck_parents[] = { - "sys_clkin_ck", "per_hsd_byp_clk_mux_ck" -}; static struct clk dpll_per_ck; @@ -505,7 +475,7 @@ static struct clk_hw_omap dpll_per_ck_hw = { .ops = &clkhwops_omap3_dpll, }; -DEFINE_STRUCT_CLK(dpll_per_ck, dpll_per_ck_parents, dpll_ck_ops); +DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_abe_ck_ops); DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0, OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT, @@ -589,10 +559,6 @@ static struct dpll_data dpll_usb_dd = { .min_divider = 1, }; -static const char *dpll_usb_ck_parents[] = { - "sys_clkin_ck", "usb_hs_clk_div_ck" -}; - static struct clk dpll_usb_ck; static struct clk_hw_omap dpll_usb_ck_hw = { @@ -603,7 +569,7 @@ static struct clk_hw_omap dpll_usb_ck_hw = { .ops = &clkhwops_omap3_dpll, }; -DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_usb_ck_parents, dpll_ck_ops); +DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_core_ck_parents, dpll_abe_ck_ops); static const char *dpll_usb_clkdcoldo_ck_parents[] = { "dpll_usb_ck", @@ -730,13 +696,9 @@ DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0, OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT, OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL); -static const char *dbgclk_mux_ck_parents[] = { - "sys_clkin_ck" -}; - static struct clk dbgclk_mux_ck; DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL); -DEFINE_STRUCT_CLK(dbgclk_mux_ck, dbgclk_mux_ck_parents, +DEFINE_STRUCT_CLK(dbgclk_mux_ck, dpll_core_ck_parents, dpll_usb_clkdcoldo_ck_ops); /* Leaf clocks controlled by modules */ @@ -1973,10 +1935,10 @@ static struct omap_clk omap44xx_clks[] = { CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), - CLK("40138000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), - CLK("4013a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), - CLK("4013c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), - CLK("4013e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("49038000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("4903a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("4903c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), + CLK("4903e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X), }; @@ -1993,7 +1955,6 @@ int __init omap4xxx_clk_init(void) { u32 cpu_clkflg; struct omap_clk *c; - int rc; if (cpu_is_omap443x()) { cpu_mask = RATE_IN_4430; @@ -2022,18 +1983,5 @@ int __init omap4xxx_clk_init(void) omap2_clk_enable_init_clocks(enable_init_clks, ARRAY_SIZE(enable_init_clks)); - /* - * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power - * state when turning the ABE clock domain. Workaround this by - * locking the ABE DPLL on boot. - */ - if (cpu_is_omap446x()) { - rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck); - if (!rc) - rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ); - if (rc) - pr_err("%s: failed to configure ABE DPLL!\n", __func__); - } - return 0; } diff --git a/trunk/arch/arm/mach-omap2/clock.h b/trunk/arch/arm/mach-omap2/clock.h index b40204837bd7..9917f793c3b6 100644 --- a/trunk/arch/arm/mach-omap2/clock.h +++ b/trunk/arch/arm/mach-omap2/clock.h @@ -195,10 +195,6 @@ struct clksel { * @enable_mask: mask of the DPLL mode bitfield in @control_reg * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() - * @last_rounded_m4xen: cache of the last M4X result of - * omap4_dpll_regm4xen_round_rate() - * @last_rounded_lpmode: cache of the last lpmode result of - * omap4_dpll_lpmode_recalc() * @max_multiplier: maximum valid non-bypass multiplier value (actual) * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() * @min_divider: minimum valid non-bypass divider value (actual) @@ -209,8 +205,6 @@ struct clksel { * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg - * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg - * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs @@ -239,8 +233,6 @@ struct dpll_data { u32 enable_mask; unsigned long last_rounded_rate; u16 last_rounded_m; - u8 last_rounded_m4xen; - u8 last_rounded_lpmode; u16 max_multiplier; u8 last_rounded_n; u8 min_divider; @@ -253,8 +245,6 @@ struct dpll_data { u32 idlest_mask; u32 dco_mask; u32 sddiv_mask; - u32 lpmode_mask; - u32 m4xen_mask; u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; diff --git a/trunk/arch/arm/mach-omap2/clockdomain.c b/trunk/arch/arm/mach-omap2/clockdomain.c index 7faf82d4e85c..384873580b23 100644 --- a/trunk/arch/arm/mach-omap2/clockdomain.c +++ b/trunk/arch/arm/mach-omap2/clockdomain.c @@ -998,8 +998,7 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) spin_lock_irqsave(&clkdm->lock, flags); /* corner case: disabling unused clocks */ - if ((__clk_get_enable_count(clk) == 0) && - (atomic_read(&clkdm->usecount) == 0)) + if (__clk_get_enable_count(clk) == 0) goto ccd_exit; if (atomic_read(&clkdm->usecount) == 0) { diff --git a/trunk/arch/arm/mach-omap2/common.c b/trunk/arch/arm/mach-omap2/common.c index 5c2fd4863b2b..2dabb9ecb986 100644 --- a/trunk/arch/arm/mach-omap2/common.c +++ b/trunk/arch/arm/mach-omap2/common.c @@ -16,8 +16,6 @@ #include #include -#include - #include "common.h" #include "omap-secure.h" @@ -32,7 +30,6 @@ int __weak omap_secure_ram_reserve_memblock(void) void __init omap_reserve(void) { - omap_vram_reserve_sdram_memblock(); omap_dsp_reserve_sdram_memblock(); omap_secure_ram_reserve_memblock(); omap_barrier_reserve_memblock(); diff --git a/trunk/arch/arm/mach-omap2/cpuidle34xx.c b/trunk/arch/arm/mach-omap2/cpuidle34xx.c index 22590dbe8f14..bca7a8885703 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle34xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle34xx.c @@ -40,8 +40,6 @@ struct omap3_idle_statedata { u32 core_state; }; -static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; - static struct omap3_idle_statedata omap3_idle_data[] = { { .mpu_state = PWRDM_POWER_ON, @@ -73,7 +71,7 @@ static struct omap3_idle_statedata omap3_idle_data[] = { }, }; -/* Private functions */ +static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; static int __omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, @@ -262,11 +260,11 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, return ret; } -static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); +DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); -static struct cpuidle_driver omap3_idle_driver = { - .name = "omap3_idle", - .owner = THIS_MODULE, +struct cpuidle_driver omap3_idle_driver = { + .name = "omap3_idle", + .owner = THIS_MODULE, .states = { { .enter = omap3_enter_idle_bm, @@ -329,8 +327,6 @@ static struct cpuidle_driver omap3_idle_driver = { .safe_state_index = 0, }; -/* Public functions */ - /** * omap3_idle_init - Init routine for OMAP3 idle * diff --git a/trunk/arch/arm/mach-omap2/cpuidle44xx.c b/trunk/arch/arm/mach-omap2/cpuidle44xx.c index d639aef0deda..288bee6cbb76 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle44xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle44xx.c @@ -54,8 +54,6 @@ static struct clockdomain *cpu_clkdm[NR_CPUS]; static atomic_t abort_barrier; static bool cpu_done[NR_CPUS]; -/* Private functions */ - /** * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions * @dev: cpuidle device @@ -163,19 +161,9 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, return index; } -/* - * For each cpu, setup the broadcast timer because local timers - * stops for the states above C1. - */ -static void omap_setup_broadcast_timer(void *arg) -{ - int cpu = smp_processor_id(); - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); -} - -static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); -static struct cpuidle_driver omap4_idle_driver = { +struct cpuidle_driver omap4_idle_driver = { .name = "omap4_idle", .owner = THIS_MODULE, .en_core_tk_irqen = 1, @@ -190,7 +178,7 @@ static struct cpuidle_driver omap4_idle_driver = { .desc = "MPUSS ON" }, { - /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */ + /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */ .exit_latency = 328 + 440, .target_residency = 960, .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, @@ -212,7 +200,15 @@ static struct cpuidle_driver omap4_idle_driver = { .safe_state_index = 0, }; -/* Public functions */ +/* + * For each cpu, setup the broadcast timer because local timers + * stops for the states above C1. + */ +static void omap_setup_broadcast_timer(void *arg) +{ + int cpu = smp_processor_id(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); +} /** * omap4_idle_init - Init routine for OMAP4 idle diff --git a/trunk/arch/arm/mach-omap2/dpll3xxx.c b/trunk/arch/arm/mach-omap2/dpll3xxx.c index 2bb18838cba9..fafb28c0dcbc 100644 --- a/trunk/arch/arm/mach-omap2/dpll3xxx.c +++ b/trunk/arch/arm/mach-omap2/dpll3xxx.c @@ -291,13 +291,16 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) /* * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly - * @clk: struct clk * of DPLL to set - * @freqsel: FREQSEL value to set + * @clk: struct clk * of DPLL to set + * @m: DPLL multiplier to set + * @n: DPLL divider to set + * @freqsel: FREQSEL value to set * - * Program the DPLL with the last M, N values calculated, and wait for - * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success. + * Program the DPLL with the supplied M, N values, and wait for the DPLL to + * lock.. Returns -EINVAL upon error, or 0 upon success. */ -static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) +static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n, + u16 freqsel) { struct dpll_data *dd = clk->dpll_data; u8 dco, sd_div; @@ -320,45 +323,23 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) /* Set DPLL multiplier, divider */ v = __raw_readl(dd->mult_div1_reg); v &= ~(dd->mult_mask | dd->div1_mask); - v |= dd->last_rounded_m << __ffs(dd->mult_mask); - v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask); + v |= m << __ffs(dd->mult_mask); + v |= (n - 1) << __ffs(dd->div1_mask); /* Configure dco and sd_div for dplls that have these fields */ if (dd->dco_mask) { - _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n); + _lookup_dco(clk, &dco, m, n); v &= ~(dd->dco_mask); v |= dco << __ffs(dd->dco_mask); } if (dd->sddiv_mask) { - _lookup_sddiv(clk, &sd_div, dd->last_rounded_m, - dd->last_rounded_n); + _lookup_sddiv(clk, &sd_div, m, n); v &= ~(dd->sddiv_mask); v |= sd_div << __ffs(dd->sddiv_mask); } __raw_writel(v, dd->mult_div1_reg); - /* Set 4X multiplier and low-power mode */ - if (dd->m4xen_mask || dd->lpmode_mask) { - v = __raw_readl(dd->control_reg); - - if (dd->m4xen_mask) { - if (dd->last_rounded_m4xen) - v |= dd->m4xen_mask; - else - v &= ~dd->m4xen_mask; - } - - if (dd->lpmode_mask) { - if (dd->last_rounded_lpmode) - v |= dd->lpmode_mask; - else - v &= ~dd->lpmode_mask; - } - - __raw_writel(v, dd->control_reg); - } - /* We let the clock framework set the other output dividers later */ /* REVISIT: Set ramp-up delay? */ @@ -511,7 +492,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__, __clk_get_name(hw->clk), rate); - ret = omap3_noncore_dpll_program(clk, freqsel); + ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m, + dd->last_rounded_n, freqsel); if (!ret) new_parent = dd->clk_ref; } diff --git a/trunk/arch/arm/mach-omap2/dpll44xx.c b/trunk/arch/arm/mach-omap2/dpll44xx.c index d28b0f726715..d3326c474fdc 100644 --- a/trunk/arch/arm/mach-omap2/dpll44xx.c +++ b/trunk/arch/arm/mach-omap2/dpll44xx.c @@ -20,15 +20,6 @@ #include "clock44xx.h" #include "cm-regbits-44xx.h" -/* - * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that - * can supported when using the DPLL low-power mode. Frequencies are - * defined in OMAP4430/60 Public TRM section 3.6.3.3.2 "Enable Control, - * Status, and Low-Power Operation Mode". - */ -#define OMAP4_DPLL_LP_FINT_MAX 1000000 -#define OMAP4_DPLL_LP_FOUT_MAX 100000000 - /* Supported only on OMAP4 */ int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk) { @@ -90,31 +81,6 @@ const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = { .deny_idle = omap4_dpllmx_deny_gatectrl, }; -/** - * omap4_dpll_lpmode_recalc - compute DPLL low-power setting - * @dd: pointer to the dpll data structure - * - * Calculates if low-power mode can be enabled based upon the last - * multiplier and divider values calculated. If low-power mode can be - * enabled, then the bit to enable low-power mode is stored in the - * last_rounded_lpmode variable. This implementation is based upon the - * criteria for enabling low-power mode as described in the OMAP4430/60 - * Public TRM section 3.6.3.3.2 "Enable Control, Status, and Low-Power - * Operation Mode". - */ -static void omap4_dpll_lpmode_recalc(struct dpll_data *dd) -{ - long fint, fout; - - fint = __clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1); - fout = fint * dd->last_rounded_m; - - if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX)) - dd->last_rounded_lpmode = 1; - else - dd->last_rounded_lpmode = 0; -} - /** * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit * @clk: struct clk * of the DPLL to compute the rate for @@ -164,6 +130,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, unsigned long *parent_rate) { struct clk_hw_omap *clk = to_clk_hw_omap(hw); + u32 v; struct dpll_data *dd; long r; @@ -172,31 +139,18 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, dd = clk->dpll_data; - dd->last_rounded_m4xen = 0; + /* regm4xen adds a multiplier of 4 to DPLL calculations */ + v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK; + + if (v) + target_rate = target_rate / OMAP4430_REGM4XEN_MULT; - /* - * First try to compute the DPLL configuration for - * target rate without using the 4X multiplier. - */ r = omap2_dpll_round_rate(hw, target_rate, NULL); - if (r != ~0) - goto out; - - /* - * If we did not find a valid DPLL configuration, try again, but - * this time see if using the 4X multiplier can help. Enabling the - * 4X multiplier is equivalent to dividing the target rate by 4. - */ - r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT, - NULL); if (r == ~0) return r; - dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; - dd->last_rounded_m4xen = 1; - -out: - omap4_dpll_lpmode_recalc(dd); + if (v) + clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; - return dd->last_rounded_rate; + return clk->dpll_data->last_rounded_rate; } diff --git a/trunk/arch/arm/mach-tegra/common.c b/trunk/arch/arm/mach-tegra/common.c index d54cfc54b9fe..0816562725f6 100644 --- a/trunk/arch/arm/mach-tegra/common.c +++ b/trunk/arch/arm/mach-tegra/common.c @@ -104,7 +104,7 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = { /* name parent rate enabled */ { "clk_m", NULL, 0, true }, - { "pll_p", "pll_ref", 408000000, true }, + { "pll_p", "clk_m", 408000000, true }, { "pll_p_out1", "pll_p", 9600000, true }, { "pll_p_out4", "pll_p", 102000000, true }, { "sclk", "pll_p_out4", 102000000, true }, diff --git a/trunk/arch/arm/mach-tegra/tegra30_clocks.c b/trunk/arch/arm/mach-tegra/tegra30_clocks.c index d7147779f8ea..efc000e32e1c 100644 --- a/trunk/arch/arm/mach-tegra/tegra30_clocks.c +++ b/trunk/arch/arm/mach-tegra/tegra30_clocks.c @@ -2045,7 +2045,9 @@ struct clk_ops tegra30_periph_clk_ops = { static int tegra30_dsib_clk_set_parent(struct clk_hw *hw, u8 index) { struct clk *d = clk_get_sys(NULL, "pll_d"); - /* The DSIB parent selection bit is in PLLD base register */ + /* The DSIB parent selection bit is in PLLD base + register - can not do direct r-m-w, must be + protected by PLLD lock */ tegra_clk_cfg_ex( d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, index); diff --git a/trunk/arch/arm/mach-u300/core.c b/trunk/arch/arm/mach-u300/core.c index 0374b9863e9b..12f3994c43db 100644 --- a/trunk/arch/arm/mach-u300/core.c +++ b/trunk/arch/arm/mach-u300/core.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1542,6 +1543,39 @@ static struct pinctrl_map __initdata u300_pinmux_map[] = { pin_highz_conf), }; +struct u300_mux_hog { + struct device *dev; + struct pinctrl *p; +}; + +static struct u300_mux_hog u300_mux_hogs[] = { + { + .dev = &uart0_device.dev, + }, + { + .dev = &mmcsd_device.dev, + }, +}; + +static int __init u300_pinctrl_fetch(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) { + struct pinctrl *p; + + p = pinctrl_get_select_default(u300_mux_hogs[i].dev); + if (IS_ERR(p)) { + pr_err("u300: could not get pinmux hog for dev %s\n", + dev_name(u300_mux_hogs[i].dev)); + continue; + } + u300_mux_hogs[i].p = p; + } + return 0; +} +subsys_initcall(u300_pinctrl_fetch); + /* * Notice that AMBA devices are initialized before platform devices. * diff --git a/trunk/arch/arm/mach-ux500/devices-db8500.h b/trunk/arch/arm/mach-ux500/devices-db8500.h index a5e05f6e256f..4b24c9992654 100644 --- a/trunk/arch/arm/mach-ux500/devices-db8500.h +++ b/trunk/arch/arm/mach-ux500/devices-db8500.h @@ -8,7 +8,6 @@ #ifndef __DEVICES_DB8500_H #define __DEVICES_DB8500_H -#include #include #include "devices-common.h" diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index 6b2fb87c8698..5383bc018571 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -1034,8 +1034,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, spin_unlock_irqrestore(&mapping->lock, flags); } -static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, - gfp_t gfp, struct dma_attrs *attrs) +static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp) { struct page **pages; int count = size >> PAGE_SHIFT; @@ -1049,23 +1048,6 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, if (!pages) return NULL; - if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) - { - unsigned long order = get_order(size); - struct page *page; - - page = dma_alloc_from_contiguous(dev, count, order); - if (!page) - goto error; - - __dma_clear_buffer(page, size); - - for (i = 0; i < count; i++) - pages[i] = page + i; - - return pages; - } - while (count) { int j, order = __fls(count); @@ -1099,21 +1081,14 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, return NULL; } -static int __iommu_free_buffer(struct device *dev, struct page **pages, - size_t size, struct dma_attrs *attrs) +static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size) { int count = size >> PAGE_SHIFT; int array_size = count * sizeof(struct page *); int i; - - if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) { - dma_release_from_contiguous(dev, pages[0], count); - } else { - for (i = 0; i < count; i++) - if (pages[i]) - __free_pages(pages[i], 0); - } - + for (i = 0; i < count; i++) + if (pages[i]) + __free_pages(pages[i], 0); if (array_size <= PAGE_SIZE) kfree(pages); else @@ -1275,7 +1250,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, if (gfp & GFP_ATOMIC) return __iommu_alloc_atomic(dev, size, handle); - pages = __iommu_alloc_buffer(dev, size, gfp, attrs); + pages = __iommu_alloc_buffer(dev, size, gfp); if (!pages) return NULL; @@ -1296,7 +1271,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, err_mapping: __iommu_remove_mapping(dev, *handle, size); err_buffer: - __iommu_free_buffer(dev, pages, size, attrs); + __iommu_free_buffer(dev, pages, size); return NULL; } @@ -1352,7 +1327,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, } __iommu_remove_mapping(dev, handle, size); - __iommu_free_buffer(dev, pages, size, attrs); + __iommu_free_buffer(dev, pages, size); } static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt, diff --git a/trunk/arch/m68k/Kconfig.cpu b/trunk/arch/m68k/Kconfig.cpu index b1cfff832fb5..2f2d87b40341 100644 --- a/trunk/arch/m68k/Kconfig.cpu +++ b/trunk/arch/m68k/Kconfig.cpu @@ -35,8 +35,7 @@ endchoice if M68KCLASSIC config M68000 - bool "MC68000" - depends on !MMU + bool select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 select CPU_HAS_NO_UNALIGNED diff --git a/trunk/arch/m68k/Makefile b/trunk/arch/m68k/Makefile index 2f02acfb8edf..7636751f2f87 100644 --- a/trunk/arch/m68k/Makefile +++ b/trunk/arch/m68k/Makefile @@ -92,7 +92,7 @@ endif head-y := arch/m68k/kernel/head.o head-$(CONFIG_SUN3) := arch/m68k/kernel/sun3-head.o head-$(CONFIG_M68360) := arch/m68k/platform/68360/head.o -head-$(CONFIG_M68000) := arch/m68k/platform/68000/head.o +head-$(CONFIG_M68000) := arch/m68k/platform/68328/head.o head-$(CONFIG_COLDFIRE) := arch/m68k/platform/coldfire/head.o core-y += arch/m68k/kernel/ arch/m68k/mm/ @@ -114,7 +114,9 @@ core-$(CONFIG_M68040) += arch/m68k/fpsp040/ core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ core-$(CONFIG_M68360) += arch/m68k/platform/68360/ -core-$(CONFIG_M68000) += arch/m68k/platform/68000/ +core-$(CONFIG_M68000) += arch/m68k/platform/68328/ +core-$(CONFIG_M68EZ328) += arch/m68k/platform/68EZ328/ +core-$(CONFIG_M68VZ328) += arch/m68k/platform/68VZ328/ core-$(CONFIG_COLDFIRE) += arch/m68k/platform/coldfire/ diff --git a/trunk/arch/m68k/include/asm/m5249sim.h b/trunk/arch/m68k/include/asm/m5249sim.h new file mode 100644 index 000000000000..fdf45e6807c9 --- /dev/null +++ b/trunk/arch/m68k/include/asm/m5249sim.h @@ -0,0 +1,269 @@ +/****************************************************************************/ + +/* + * m5249sim.h -- ColdFire 5249 System Integration Module support. + * + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) + */ + +/****************************************************************************/ +#ifndef m5249sim_h +#define m5249sim_h +/****************************************************************************/ + +#define CPU_NAME "COLDFIRE(m5249)" +#define CPU_INSTR_PER_JIFFY 3 +#define MCF_BUSCLK (MCF_CLK / 2) + +#include + +/* + * The 5249 has a second MBAR region, define its address. + */ +#define MCF_MBAR2 0x80000000 + +/* + * Define the 5249 SIM register set addresses. + */ +#define MCFSIM_RSR (MCF_MBAR + 0x00) /* Reset Status */ +#define MCFSIM_SYPCR (MCF_MBAR + 0x01) /* System Protection */ +#define MCFSIM_SWIVR (MCF_MBAR + 0x02) /* SW Watchdog intr */ +#define MCFSIM_SWSR (MCF_MBAR + 0x03) /* SW Watchdog srv */ +#define MCFSIM_PAR (MCF_MBAR + 0x04) /* Pin Assignment */ +#define MCFSIM_IRQPAR (MCF_MBAR + 0x06) /* Intr Assignment */ +#define MCFSIM_MPARK (MCF_MBAR + 0x0C) /* BUS Master Ctrl */ +#define MCFSIM_IPR (MCF_MBAR + 0x40) /* Interrupt Pending */ +#define MCFSIM_IMR (MCF_MBAR + 0x44) /* Interrupt Mask */ +#define MCFSIM_AVR (MCF_MBAR + 0x4b) /* Autovector Ctrl */ +#define MCFSIM_ICR0 (MCF_MBAR + 0x4c) /* Intr Ctrl reg 0 */ +#define MCFSIM_ICR1 (MCF_MBAR + 0x4d) /* Intr Ctrl reg 1 */ +#define MCFSIM_ICR2 (MCF_MBAR + 0x4e) /* Intr Ctrl reg 2 */ +#define MCFSIM_ICR3 (MCF_MBAR + 0x4f) /* Intr Ctrl reg 3 */ +#define MCFSIM_ICR4 (MCF_MBAR + 0x50) /* Intr Ctrl reg 4 */ +#define MCFSIM_ICR5 (MCF_MBAR + 0x51) /* Intr Ctrl reg 5 */ +#define MCFSIM_ICR6 (MCF_MBAR + 0x52) /* Intr Ctrl reg 6 */ +#define MCFSIM_ICR7 (MCF_MBAR + 0x53) /* Intr Ctrl reg 7 */ +#define MCFSIM_ICR8 (MCF_MBAR + 0x54) /* Intr Ctrl reg 8 */ +#define MCFSIM_ICR9 (MCF_MBAR + 0x55) /* Intr Ctrl reg 9 */ +#define MCFSIM_ICR10 (MCF_MBAR + 0x56) /* Intr Ctrl reg 10 */ +#define MCFSIM_ICR11 (MCF_MBAR + 0x57) /* Intr Ctrl reg 11 */ + +#define MCFSIM_CSAR0 (MCF_MBAR + 0x80) /* CS 0 Address reg */ +#define MCFSIM_CSMR0 (MCF_MBAR + 0x84) /* CS 0 Mask reg */ +#define MCFSIM_CSCR0 (MCF_MBAR + 0x8a) /* CS 0 Control reg */ +#define MCFSIM_CSAR1 (MCF_MBAR + 0x8c) /* CS 1 Address reg */ +#define MCFSIM_CSMR1 (MCF_MBAR + 0x90) /* CS 1 Mask reg */ +#define MCFSIM_CSCR1 (MCF_MBAR + 0x96) /* CS 1 Control reg */ +#define MCFSIM_CSAR2 (MCF_MBAR + 0x98) /* CS 2 Address reg */ +#define MCFSIM_CSMR2 (MCF_MBAR + 0x9c) /* CS 2 Mask reg */ +#define MCFSIM_CSCR2 (MCF_MBAR + 0xa2) /* CS 2 Control reg */ +#define MCFSIM_CSAR3 (MCF_MBAR + 0xa4) /* CS 3 Address reg */ +#define MCFSIM_CSMR3 (MCF_MBAR + 0xa8) /* CS 3 Mask reg */ +#define MCFSIM_CSCR3 (MCF_MBAR + 0xae) /* CS 3 Control reg */ + +#define MCFSIM_DCR (MCF_MBAR + 0x100) /* DRAM Control */ +#define MCFSIM_DACR0 (MCF_MBAR + 0x108) /* DRAM 0 Addr/Ctrl */ +#define MCFSIM_DMR0 (MCF_MBAR + 0x10c) /* DRAM 0 Mask */ +#define MCFSIM_DACR1 (MCF_MBAR + 0x110) /* DRAM 1 Addr/Ctrl */ +#define MCFSIM_DMR1 (MCF_MBAR + 0x114) /* DRAM 1 Mask */ + +/* + * Timer module. + */ +#define MCFTIMER_BASE1 (MCF_MBAR + 0x140) /* Base of TIMER1 */ +#define MCFTIMER_BASE2 (MCF_MBAR + 0x180) /* Base of TIMER2 */ + +/* + * UART module. + */ +#define MCFUART_BASE0 (MCF_MBAR + 0x1c0) /* Base address UART0 */ +#define MCFUART_BASE1 (MCF_MBAR + 0x200) /* Base address UART1 */ + +/* + * QSPI module. + */ +#define MCFQSPI_BASE (MCF_MBAR + 0x300) /* Base address QSPI */ +#define MCFQSPI_SIZE 0x40 /* Register set size */ + +#define MCFQSPI_CS0 29 +#define MCFQSPI_CS1 24 +#define MCFQSPI_CS2 21 +#define MCFQSPI_CS3 22 + +/* + * DMA unit base addresses. + */ +#define MCFDMA_BASE0 (MCF_MBAR + 0x300) /* Base address DMA 0 */ +#define MCFDMA_BASE1 (MCF_MBAR + 0x340) /* Base address DMA 1 */ +#define MCFDMA_BASE2 (MCF_MBAR + 0x380) /* Base address DMA 2 */ +#define MCFDMA_BASE3 (MCF_MBAR + 0x3C0) /* Base address DMA 3 */ + +/* + * Some symbol defines for the above... + */ +#define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */ +#define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */ +#define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */ +#define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */ +#define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */ +#define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */ +#define MCFSIM_DMA1ICR MCFSIM_ICR7 /* DMA 1 ICR */ +#define MCFSIM_DMA2ICR MCFSIM_ICR8 /* DMA 2 ICR */ +#define MCFSIM_DMA3ICR MCFSIM_ICR9 /* DMA 3 ICR */ +#define MCFSIM_QSPIICR MCFSIM_ICR10 /* QSPI ICR */ + +/* + * Define system peripheral IRQ usage. + */ +#define MCF_IRQ_QSPI 28 /* QSPI, Level 4 */ +#define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */ +#define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */ + +#define MCF_IRQ_UART0 73 /* UART0 */ +#define MCF_IRQ_UART1 74 /* UART1 */ + +/* + * General purpose IO registers (in MBAR2). + */ +#define MCFSIM2_GPIOREAD (MCF_MBAR2 + 0x000) /* GPIO read values */ +#define MCFSIM2_GPIOWRITE (MCF_MBAR2 + 0x004) /* GPIO write values */ +#define MCFSIM2_GPIOENABLE (MCF_MBAR2 + 0x008) /* GPIO enabled */ +#define MCFSIM2_GPIOFUNC (MCF_MBAR2 + 0x00C) /* GPIO function */ +#define MCFSIM2_GPIO1READ (MCF_MBAR2 + 0x0B0) /* GPIO1 read values */ +#define MCFSIM2_GPIO1WRITE (MCF_MBAR2 + 0x0B4) /* GPIO1 write values */ +#define MCFSIM2_GPIO1ENABLE (MCF_MBAR2 + 0x0B8) /* GPIO1 enabled */ +#define MCFSIM2_GPIO1FUNC (MCF_MBAR2 + 0x0BC) /* GPIO1 function */ + +#define MCFSIM2_GPIOINTSTAT (MCF_MBAR2 + 0xc0) /* GPIO intr status */ +#define MCFSIM2_GPIOINTCLEAR (MCF_MBAR2 + 0xc0) /* GPIO intr clear */ +#define MCFSIM2_GPIOINTENABLE (MCF_MBAR2 + 0xc4) /* GPIO intr enable */ + +#define MCFSIM2_INTLEVEL1 (MCF_MBAR2 + 0x140) /* Intr level reg 1 */ +#define MCFSIM2_INTLEVEL2 (MCF_MBAR2 + 0x144) /* Intr level reg 2 */ +#define MCFSIM2_INTLEVEL3 (MCF_MBAR2 + 0x148) /* Intr level reg 3 */ +#define MCFSIM2_INTLEVEL4 (MCF_MBAR2 + 0x14c) /* Intr level reg 4 */ +#define MCFSIM2_INTLEVEL5 (MCF_MBAR2 + 0x150) /* Intr level reg 5 */ +#define MCFSIM2_INTLEVEL6 (MCF_MBAR2 + 0x154) /* Intr level reg 6 */ +#define MCFSIM2_INTLEVEL7 (MCF_MBAR2 + 0x158) /* Intr level reg 7 */ +#define MCFSIM2_INTLEVEL8 (MCF_MBAR2 + 0x15c) /* Intr level reg 8 */ + +#define MCFSIM2_DMAROUTE (MCF_MBAR2 + 0x188) /* DMA routing */ + +#define MCFSIM2_IDECONFIG1 (MCF_MBAR2 + 0x18c) /* IDEconfig1 */ +#define MCFSIM2_IDECONFIG2 (MCF_MBAR2 + 0x190) /* IDEconfig2 */ + +/* + * Define the base interrupt for the second interrupt controller. + * We set it to 128, out of the way of the base interrupts, and plenty + * of room for its 64 interrupts. + */ +#define MCFINTC2_VECBASE 128 + +#define MCFINTC2_GPIOIRQ0 (MCFINTC2_VECBASE + 32) +#define MCFINTC2_GPIOIRQ1 (MCFINTC2_VECBASE + 33) +#define MCFINTC2_GPIOIRQ2 (MCFINTC2_VECBASE + 34) +#define MCFINTC2_GPIOIRQ3 (MCFINTC2_VECBASE + 35) +#define MCFINTC2_GPIOIRQ4 (MCFINTC2_VECBASE + 36) +#define MCFINTC2_GPIOIRQ5 (MCFINTC2_VECBASE + 37) +#define MCFINTC2_GPIOIRQ6 (MCFINTC2_VECBASE + 38) +#define MCFINTC2_GPIOIRQ7 (MCFINTC2_VECBASE + 39) + +/* + * Generic GPIO support + */ +#define MCFGPIO_PIN_MAX 64 +#define MCFGPIO_IRQ_MAX -1 +#define MCFGPIO_IRQ_VECBASE -1 + +/****************************************************************************/ + +#ifdef __ASSEMBLER__ + +/* + * The M5249C3 board needs a little help getting all its SIM devices + * initialized at kernel start time. dBUG doesn't set much up, so + * we need to do it manually. + */ +.macro m5249c3_setup + /* + * Set MBAR1 and MBAR2, just incase they are not set. + */ + movel #0x10000001,%a0 + movec %a0,%MBAR /* map MBAR region */ + subql #1,%a0 /* get MBAR address in a0 */ + + movel #0x80000001,%a1 + movec %a1,#3086 /* map MBAR2 region */ + subql #1,%a1 /* get MBAR2 address in a1 */ + + /* + * Move secondary interrupts to their base (128). + */ + moveb #MCFINTC2_VECBASE,%d0 + moveb %d0,0x16b(%a1) /* interrupt base register */ + + /* + * Work around broken CSMR0/DRAM vector problem. + */ + movel #0x001F0021,%d0 /* disable C/I bit */ + movel %d0,0x84(%a0) /* set CSMR0 */ + + /* + * Disable the PLL firstly. (Who knows what state it is + * in here!). + */ + movel 0x180(%a1),%d0 /* get current PLL value */ + andl #0xfffffffe,%d0 /* PLL bypass first */ + movel %d0,0x180(%a1) /* set PLL register */ + nop + +#if CONFIG_CLOCK_FREQ == 140000000 + /* + * Set initial clock frequency. This assumes M5249C3 board + * is fitted with 11.2896MHz crystal. It will program the + * PLL for 140MHz. Lets go fast :-) + */ + movel #0x125a40f0,%d0 /* set for 140MHz */ + movel %d0,0x180(%a1) /* set PLL register */ + orl #0x1,%d0 + movel %d0,0x180(%a1) /* set PLL register */ +#endif + + /* + * Setup CS1 for ethernet controller. + * (Setup as per M5249C3 doco). + */ + movel #0xe0000000,%d0 /* CS1 mapped at 0xe0000000 */ + movel %d0,0x8c(%a0) + movel #0x001f0021,%d0 /* CS1 size of 1Mb */ + movel %d0,0x90(%a0) + movew #0x0080,%d0 /* CS1 = 16bit port, AA */ + movew %d0,0x96(%a0) + + /* + * Setup CS2 for IDE interface. + */ + movel #0x50000000,%d0 /* CS2 mapped at 0x50000000 */ + movel %d0,0x98(%a0) + movel #0x001f0001,%d0 /* CS2 size of 1MB */ + movel %d0,0x9c(%a0) + movew #0x0080,%d0 /* CS2 = 16bit, TA */ + movew %d0,0xa2(%a0) + + movel #0x00107000,%d0 /* IDEconfig1 */ + movel %d0,0x18c(%a1) + movel #0x000c0400,%d0 /* IDEconfig2 */ + movel %d0,0x190(%a1) + + movel #0x00080000,%d0 /* GPIO19, IDE reset bit */ + orl %d0,0xc(%a1) /* function GPIO19 */ + orl %d0,0x8(%a1) /* enable GPIO19 as output */ + orl %d0,0x4(%a1) /* de-assert IDE reset */ +.endm + +#define PLATFORM_SETUP m5249c3_setup + +#endif /* __ASSEMBLER__ */ + +/****************************************************************************/ +#endif /* m5249sim_h */ diff --git a/trunk/arch/m68k/include/asm/m525xsim.h b/trunk/arch/m68k/include/asm/m525xsim.h index e33f5bb6aca8..acab61cb91ed 100644 --- a/trunk/arch/m68k/include/asm/m525xsim.h +++ b/trunk/arch/m68k/include/asm/m525xsim.h @@ -12,11 +12,6 @@ #define m525xsim_h /****************************************************************************/ -/* - * This header supports ColdFire 5249, 5251 and 5253. There are a few - * little differences between them, but most of the peripheral support - * can be used by all of them. - */ #define CPU_NAME "COLDFIRE(m525x)" #define CPU_INSTR_PER_JIFFY 3 #define MCF_BUSCLK (MCF_CLK / 2) @@ -70,8 +65,6 @@ #define MCFSIM_DCR (MCF_MBAR + 0x100) /* DRAM Control */ #define MCFSIM_DACR0 (MCF_MBAR + 0x108) /* DRAM 0 Addr/Ctrl */ #define MCFSIM_DMR0 (MCF_MBAR + 0x10c) /* DRAM 0 Mask */ -#define MCFSIM_DACR1 (MCF_MBAR + 0x110) /* DRAM 1 Addr/Ctrl */ -#define MCFSIM_DMR1 (MCF_MBAR + 0x114) /* DRAM 1 Mask */ /* * Secondary Interrupt Controller (in MBAR2) @@ -108,17 +101,11 @@ #define MCFQSPI_BASE (MCF_MBAR + 0x300) /* Base address QSPI */ #define MCFQSPI_SIZE 0x40 /* Register set size */ -#ifdef CONFIG_M5249 -#define MCFQSPI_CS0 29 -#define MCFQSPI_CS1 24 -#define MCFQSPI_CS2 21 -#define MCFQSPI_CS3 22 -#else + #define MCFQSPI_CS0 15 #define MCFQSPI_CS1 16 #define MCFQSPI_CS2 24 #define MCFQSPI_CS3 28 -#endif /* * I2C module. @@ -128,7 +115,6 @@ #define MCFI2C_BASE1 (MCF_MBAR2 + 0x440) /* Base addreess I2C1 */ #define MCFI2C_SIZE1 0x20 /* Register set size */ - /* * DMA unit base addresses. */ @@ -177,7 +163,6 @@ #define MCF_IRQ_GPIO4 (MCFINTC2_VECBASE + 36) #define MCF_IRQ_GPIO5 (MCFINTC2_VECBASE + 37) #define MCF_IRQ_GPIO6 (MCFINTC2_VECBASE + 38) -#define MCF_IRQ_GPIO7 (MCFINTC2_VECBASE + 39) #define MCF_IRQ_USBWUP (MCFINTC2_VECBASE + 40) #define MCF_IRQ_I2C1 (MCFINTC2_VECBASE + 62) @@ -198,111 +183,12 @@ #define MCFSIM2_GPIOINTCLEAR (MCF_MBAR2 + 0xc0) /* GPIO intr clear */ #define MCFSIM2_GPIOINTENABLE (MCF_MBAR2 + 0xc4) /* GPIO intr enable */ -#define MCFSIM2_DMAROUTE (MCF_MBAR2 + 0x188) /* DMA routing */ -#define MCFSIM2_IDECONFIG1 (MCF_MBAR2 + 0x18c) /* IDEconfig1 */ -#define MCFSIM2_IDECONFIG2 (MCF_MBAR2 + 0x190) /* IDEconfig2 */ - /* * Generic GPIO support */ #define MCFGPIO_PIN_MAX 64 -#ifdef CONFIG_M5249 -#define MCFGPIO_IRQ_MAX -1 -#define MCFGPIO_IRQ_VECBASE -1 -#else #define MCFGPIO_IRQ_MAX 7 #define MCFGPIO_IRQ_VECBASE MCF_IRQ_GPIO0 -#endif - -/****************************************************************************/ - -#ifdef __ASSEMBLER__ -#ifdef CONFIG_M5249C3 -/* - * The M5249C3 board needs a little help getting all its SIM devices - * initialized at kernel start time. dBUG doesn't set much up, so - * we need to do it manually. - */ -.macro m5249c3_setup - /* - * Set MBAR1 and MBAR2, just incase they are not set. - */ - movel #0x10000001,%a0 - movec %a0,%MBAR /* map MBAR region */ - subql #1,%a0 /* get MBAR address in a0 */ - - movel #0x80000001,%a1 - movec %a1,#3086 /* map MBAR2 region */ - subql #1,%a1 /* get MBAR2 address in a1 */ - - /* - * Move secondary interrupts to their base (128). - */ - moveb #MCFINTC2_VECBASE,%d0 - moveb %d0,0x16b(%a1) /* interrupt base register */ - - /* - * Work around broken CSMR0/DRAM vector problem. - */ - movel #0x001F0021,%d0 /* disable C/I bit */ - movel %d0,0x84(%a0) /* set CSMR0 */ - - /* - * Disable the PLL firstly. (Who knows what state it is - * in here!). - */ - movel 0x180(%a1),%d0 /* get current PLL value */ - andl #0xfffffffe,%d0 /* PLL bypass first */ - movel %d0,0x180(%a1) /* set PLL register */ - nop - -#if CONFIG_CLOCK_FREQ == 140000000 - /* - * Set initial clock frequency. This assumes M5249C3 board - * is fitted with 11.2896MHz crystal. It will program the - * PLL for 140MHz. Lets go fast :-) - */ - movel #0x125a40f0,%d0 /* set for 140MHz */ - movel %d0,0x180(%a1) /* set PLL register */ - orl #0x1,%d0 - movel %d0,0x180(%a1) /* set PLL register */ -#endif - - /* - * Setup CS1 for ethernet controller. - * (Setup as per M5249C3 doco). - */ - movel #0xe0000000,%d0 /* CS1 mapped at 0xe0000000 */ - movel %d0,0x8c(%a0) - movel #0x001f0021,%d0 /* CS1 size of 1Mb */ - movel %d0,0x90(%a0) - movew #0x0080,%d0 /* CS1 = 16bit port, AA */ - movew %d0,0x96(%a0) - - /* - * Setup CS2 for IDE interface. - */ - movel #0x50000000,%d0 /* CS2 mapped at 0x50000000 */ - movel %d0,0x98(%a0) - movel #0x001f0001,%d0 /* CS2 size of 1MB */ - movel %d0,0x9c(%a0) - movew #0x0080,%d0 /* CS2 = 16bit, TA */ - movew %d0,0xa2(%a0) - - movel #0x00107000,%d0 /* IDEconfig1 */ - movel %d0,0x18c(%a1) - movel #0x000c0400,%d0 /* IDEconfig2 */ - movel %d0,0x190(%a1) - - movel #0x00080000,%d0 /* GPIO19, IDE reset bit */ - orl %d0,0xc(%a1) /* function GPIO19 */ - orl %d0,0x8(%a1) /* enable GPIO19 as output */ - orl %d0,0x4(%a1) /* de-assert IDE reset */ -.endm - -#define PLATFORM_SETUP m5249c3_setup -#endif /* CONFIG_M5249C3 */ -#endif /* __ASSEMBLER__ */ /****************************************************************************/ #endif /* m525xsim_h */ diff --git a/trunk/arch/m68k/include/asm/mcfclk.h b/trunk/arch/m68k/include/asm/mcfclk.h index ea4791e3a557..b676a02bb392 100644 --- a/trunk/arch/m68k/include/asm/mcfclk.h +++ b/trunk/arch/m68k/include/asm/mcfclk.h @@ -8,6 +8,7 @@ struct clk; +#ifdef MCFPM_PPMCR0 struct clk_ops { void (*enable)(struct clk *); void (*disable)(struct clk *); @@ -22,8 +23,6 @@ struct clk { }; extern struct clk *mcf_clks[]; - -#ifdef MCFPM_PPMCR0 extern struct clk_ops clk_ops0; #ifdef MCFPM_PPMCR1 extern struct clk_ops clk_ops1; @@ -39,12 +38,6 @@ static struct clk __clk_##clk_bank##_##clk_slot = { \ void __clk_init_enabled(struct clk *); void __clk_init_disabled(struct clk *); -#else -#define DEFINE_CLK(clk_ref, clk_name, clk_rate) \ - static struct clk clk_##clk_ref = { \ - .name = clk_name, \ - .rate = clk_rate, \ - } #endif /* MCFPM_PPMCR0 */ #endif /* mcfclk_h */ diff --git a/trunk/arch/m68k/include/asm/mcfsim.h b/trunk/arch/m68k/include/asm/mcfsim.h index a04fd9b2714c..7a83e619e73b 100644 --- a/trunk/arch/m68k/include/asm/mcfsim.h +++ b/trunk/arch/m68k/include/asm/mcfsim.h @@ -24,7 +24,10 @@ #elif defined(CONFIG_M523x) #include #include -#elif defined(CONFIG_M5249) || defined(CONFIG_M525x) +#elif defined(CONFIG_M5249) +#include +#include +#elif defined(CONFIG_M525x) #include #include #elif defined(CONFIG_M527x) diff --git a/trunk/arch/m68k/include/asm/page_no.h b/trunk/arch/m68k/include/asm/page_no.h index ef209169579a..90595721185f 100644 --- a/trunk/arch/m68k/include/asm/page_no.h +++ b/trunk/arch/m68k/include/asm/page_no.h @@ -26,7 +26,7 @@ extern unsigned long memory_end; #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) #define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) -#define page_to_virt(page) __va(((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)) +#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) #define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn)) #define page_to_pfn(page) virt_to_pfn(page_to_virt(page)) diff --git a/trunk/arch/m68k/lib/memcpy.c b/trunk/arch/m68k/lib/memcpy.c index c1e2dfb206f3..10ca051d56b8 100644 --- a/trunk/arch/m68k/lib/memcpy.c +++ b/trunk/arch/m68k/lib/memcpy.c @@ -10,7 +10,7 @@ void *memcpy(void *to, const void *from, size_t n) { void *xto = to; - size_t temp; + size_t temp, temp1; if (!n) return xto; @@ -47,7 +47,6 @@ void *memcpy(void *to, const void *from, size_t n) for (; temp; temp--) *lto++ = *lfrom++; #else - size_t temp1; asm volatile ( " movel %2,%3\n" " andw #7,%3\n" diff --git a/trunk/arch/m68k/platform/68000/Makefile b/trunk/arch/m68k/platform/68000/Makefile deleted file mode 100644 index 1eab70c7194b..000000000000 --- a/trunk/arch/m68k/platform/68000/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -################################################## -# -# Makefile for 68000 core based cpus -# -# 2012.10.21, Luis Alves -# Merged all 68000 based cpu's config -# files into a single directory. -# - -# 68328, 68EZ328, 68VZ328 - -obj-y += entry.o ints.o timers.o -obj-$(CONFIG_M68328) += m68328.o -obj-$(CONFIG_M68EZ328) += m68EZ328.o -obj-$(CONFIG_M68VZ328) += m68VZ328.o -obj-$(CONFIG_ROM) += romvec.o - -extra-y := head.o diff --git a/trunk/arch/m68k/platform/68000/head.S b/trunk/arch/m68k/platform/68000/head.S deleted file mode 100644 index 536ef9616dad..000000000000 --- a/trunk/arch/m68k/platform/68000/head.S +++ /dev/null @@ -1,240 +0,0 @@ -/* - * head.S - Common startup code for 68000 core based CPU's - * - * 2012.10.21, Luis Alves , Single head.S file for all - * 68000 core based CPU's. Based on the sources from: - * Coldfire by Greg Ungerer - * 68328 by D. Jeff Dionne , - * Kenneth Albanowski , - * The Silver Hammer Group, Ltd. - * - */ - -#include -#include -#include -#include - - -/***************************************************************************** - * UCSIMM and UCDIMM use CONFIG_MEMORY_RESERVE to reserve some RAM - *****************************************************************************/ -#ifdef CONFIG_MEMORY_RESERVE -#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE)-(CONFIG_MEMORY_RESERVE*0x100000) -#else -#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE) -#endif -/*****************************************************************************/ - -.global _start -.global _rambase -.global _ramvec -.global _ramstart -.global _ramend - -#if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD) -.global bootlogo_bits -#endif - -/* Defining DEBUG_HEAD_CODE, serial port in 68x328 is inited */ -/* #define DEBUG_HEAD_CODE */ -#undef DEBUG_HEAD_CODE - -.data - -/***************************************************************************** - * RAM setup pointers. Used by the kernel to determine RAM location and size. - *****************************************************************************/ - -_rambase: - .long 0 -_ramvec: - .long 0 -_ramstart: - .long 0 -_ramend: - .long 0 - -__HEAD - -/***************************************************************************** - * Entry point, where all begins! - *****************************************************************************/ - -_start: - -/* Pilot need this specific signature at the start of ROM */ -#ifdef CONFIG_PILOT - .byte 0x4e, 0xfa, 0x00, 0x0a /* bra opcode (jmp 10 bytes) */ - .byte 'b', 'o', 'o', 't' - .word 10000 - nop - moveq #0, %d0 - movew %d0, 0xfffff618 /* Watchdog off */ - movel #0x00011f07, 0xfffff114 /* CS A1 Mask */ -#endif /* CONFIG_PILOT */ - - movew #0x2700, %sr /* disable all interrupts */ - -/***************************************************************************** - * Setup PLL and wait for it to settle (in 68x328 cpu's). - * Also, if enabled, init serial port. - *****************************************************************************/ -#if defined(CONFIG_M68328) || \ - defined(CONFIG_M68EZ328) || \ - defined(CONFIG_M68VZ328) - -/* Serial port setup. Should only be needed if debugging this startup code. */ -#ifdef DEBUG_HEAD_CODE - movew #0x0800, 0xfffff906 /* Ignore CTS */ - movew #0x010b, 0xfffff902 /* BAUD to 9600 */ - movew #0xe100, 0xfffff900 /* enable */ -#endif /* DEBUG_HEAD */ - -#ifdef CONFIG_PILOT - movew #0x2410, 0xfffff200 /* PLLCR */ -#else - movew #0x2400, 0xfffff200 /* PLLCR */ -#endif - movew #0x0123, 0xfffff202 /* PLLFSR */ - moveq #0, %d0 - movew #16384, %d0 /* PLL settle wait loop */ -_pll_settle: - subw #1, %d0 - bne _pll_settle -#endif /* CONFIG_M68x328 */ - - -/***************************************************************************** - * If running kernel from ROM some specific initialization has to be done. - * (Assuming that everything is already init'ed when running from RAM) - *****************************************************************************/ -#ifdef CONFIG_ROMKERNEL - -/***************************************************************************** - * Init chip registers (uCsimm specific) - *****************************************************************************/ -#ifdef CONFIG_UCSIMM - moveb #0x00, 0xfffffb0b /* Watchdog off */ - moveb #0x10, 0xfffff000 /* SCR */ - moveb #0x00, 0xfffff40b /* enable chip select */ - moveb #0x00, 0xfffff423 /* enable /DWE */ - moveb #0x08, 0xfffffd0d /* disable hardmap */ - moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */ - movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */ - movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */ - movew #0x8f00, 0xfffffc00 /* DRAM configuration */ - movew #0x9667, 0xfffffc02 /* DRAM control */ - movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */ - movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */ - moveb #0x40, 0xfffff300 /* IVR */ - movel #0x007FFFFF, %d0 /* IMR */ - movel %d0, 0xfffff304 - moveb 0xfffff42b, %d0 - andb #0xe0, %d0 - moveb %d0, 0xfffff42b -#endif - -/***************************************************************************** - * Init LCD controller. - * (Assuming that LCD controller is already init'ed when running from RAM) - *****************************************************************************/ -#ifdef CONFIG_INIT_LCD -#ifdef CONFIG_PILOT - moveb #0, 0xfffffA27 /* LCKCON */ - movel #_start, 0xfffffA00 /* LSSA */ - moveb #0xa, 0xfffffA05 /* LVPW */ - movew #0x9f, 0xFFFFFa08 /* LXMAX */ - movew #0x9f, 0xFFFFFa0a /* LYMAX */ - moveb #9, 0xfffffa29 /* LBAR */ - moveb #0, 0xfffffa25 /* LPXCD */ - moveb #0x04, 0xFFFFFa20 /* LPICF */ - moveb #0x58, 0xfffffA27 /* LCKCON */ - moveb #0x85, 0xfffff429 /* PFDATA */ - moveb #0xd8, 0xfffffA27 /* LCKCON */ - moveb #0xc5, 0xfffff429 /* PFDATA */ - moveb #0xd5, 0xfffff429 /* PFDATA */ - movel #bootlogo_bits, 0xFFFFFA00 /* LSSA */ - moveb #10, 0xFFFFFA05 /* LVPW */ - movew #160, 0xFFFFFA08 /* LXMAX */ - movew #160, 0xFFFFFA0A /* LYMAX */ -#else /* CONFIG_PILOT */ - movel #bootlogo_bits, 0xfffffA00 /* LSSA */ - moveb #0x28, 0xfffffA05 /* LVPW */ - movew #0x280, 0xFFFFFa08 /* LXMAX */ - movew #0x1df, 0xFFFFFa0a /* LYMAX */ - moveb #0, 0xfffffa29 /* LBAR */ - moveb #0, 0xfffffa25 /* LPXCD */ - moveb #0x08, 0xFFFFFa20 /* LPICF */ - moveb #0x01, 0xFFFFFA21 /* -ve pol */ - moveb #0x81, 0xfffffA27 /* LCKCON */ - movew #0xff00, 0xfffff412 /* LCD pins */ -#endif /* CONFIG_PILOT */ -#endif /* CONFIG_INIT_LCD */ - -/***************************************************************************** - * Kernel is running from FLASH/ROM (XIP) - * Copy init text & data to RAM - *****************************************************************************/ - moveal #_etext, %a0 - moveal #_sdata, %a1 - moveal #__bss_start, %a2 -_copy_initmem: - movel %a0@+, %a1@+ - cmpal %a1, %a2 - bhi _copy_initmem -#endif /* CONFIG_ROMKERNEL */ - -/***************************************************************************** - * Setup basic memory information for kernel - *****************************************************************************/ - movel #CONFIG_VECTORBASE,_ramvec /* set vector base location */ - movel #CONFIG_RAMBASE,_rambase /* set the base of RAM */ - movel #RAMEND, _ramend /* set end ram addr */ - lea __bss_stop,%a1 - movel %a1,_ramstart - -/***************************************************************************** - * If the kernel is in RAM, move romfs to right above bss and - * adjust _ramstart to where romfs ends. - * - * (Do this only if CONFIG_MTD_UCLINUX is true) - *****************************************************************************/ - -#if defined(CONFIG_ROMFS_FS) && defined(CONFIG_RAMKERNEL) && \ - defined(CONFIG_MTD_UCLINUX) - lea __bss_start, %a0 /* get start of bss */ - lea __bss_stop, %a1 /* set up destination */ - movel %a0, %a2 /* copy of bss start */ - - movel 8(%a0), %d0 /* get size of ROMFS */ - addql #8, %d0 /* allow for rounding */ - andl #0xfffffffc, %d0 /* whole words */ - - addl %d0, %a0 /* copy from end */ - addl %d0, %a1 /* copy from end */ - movel %a1, _ramstart /* set start of ram */ -_copy_romfs: - movel -(%a0), -(%a1) /* copy dword */ - cmpl %a0, %a2 /* check if at end */ - bne _copy_romfs -#endif /* CONFIG_ROMFS_FS && CONFIG_RAMKERNEL && CONFIG_MTD_UCLINUX */ - -/***************************************************************************** - * Clear bss region - *****************************************************************************/ - lea __bss_start, %a0 /* get start of bss */ - lea __bss_stop, %a1 /* get end of bss */ -_clear_bss: - movel #0, (%a0)+ /* clear each word */ - cmpl %a0, %a1 /* check if at end */ - bne _clear_bss - -/***************************************************************************** - * Load the current task pointer and stack. - *****************************************************************************/ - lea init_thread_union,%a0 - lea THREAD_SIZE(%a0),%sp - jsr start_kernel /* start Linux kernel */ -_exit: - jmp _exit /* should never get here */ diff --git a/trunk/arch/m68k/platform/68328/Makefile b/trunk/arch/m68k/platform/68328/Makefile new file mode 100644 index 000000000000..ee61bf84d4a0 --- /dev/null +++ b/trunk/arch/m68k/platform/68328/Makefile @@ -0,0 +1,21 @@ +# +# Makefile for arch/m68knommu/platform/68328. +# + +model-y := ram +model-$(CONFIG_ROMKERNEL) := rom + +head-y = head-$(model-y).o +head-$(CONFIG_PILOT) = head-pilot.o +head-$(CONFIG_DRAGEN2) = head-de2.o + +obj-y += entry.o ints.o timers.o +obj-$(CONFIG_M68328) += config.o +obj-$(CONFIG_ROM) += romvec.o + +extra-y := head.o + +$(obj)/head.o: $(obj)/$(head-y) + ln -sf $(head-y) $(obj)/head.o + +clean-files := $(obj)/head.o $(head-y) diff --git a/trunk/arch/m68k/platform/68000/bootlogo.h b/trunk/arch/m68k/platform/68328/bootlogo.h similarity index 100% rename from trunk/arch/m68k/platform/68000/bootlogo.h rename to trunk/arch/m68k/platform/68328/bootlogo.h diff --git a/trunk/arch/m68k/platform/68000/m68328.c b/trunk/arch/m68k/platform/68328/config.c similarity index 97% rename from trunk/arch/m68k/platform/68000/m68328.c rename to trunk/arch/m68k/platform/68328/config.c index a86eb66835aa..8c20e891e981 100644 --- a/trunk/arch/m68k/platform/68000/m68328.c +++ b/trunk/arch/m68k/platform/68328/config.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * m68328.c - 68328 specific config + * linux/arch/m68knommu/platform/68328/config.c * * Copyright (C) 1993 Hamish Macdonald * Copyright (C) 1999 D. Jeff Dionne diff --git a/trunk/arch/m68k/platform/68000/entry.S b/trunk/arch/m68k/platform/68328/entry.S similarity index 100% rename from trunk/arch/m68k/platform/68000/entry.S rename to trunk/arch/m68k/platform/68328/entry.S diff --git a/trunk/arch/m68k/platform/68328/head-de2.S b/trunk/arch/m68k/platform/68328/head-de2.S new file mode 100644 index 000000000000..537d3245b539 --- /dev/null +++ b/trunk/arch/m68k/platform/68328/head-de2.S @@ -0,0 +1,128 @@ + +#define MEM_END 0x00800000 /* Memory size 8Mb */ + +#undef CRT_DEBUG + +.macro PUTC CHAR +#ifdef CRT_DEBUG + moveq #\CHAR, %d7 + jsr putc +#endif +.endm + + .global _start + .global _rambase + .global _ramvec + .global _ramstart + .global _ramend + + .data + +/* + * Set up the usable of RAM stuff + */ +_rambase: + .long 0 +_ramvec: + .long 0 +_ramstart: + .long 0 +_ramend: + .long 0 + + .text + +_start: + +/* + * Setup initial stack + */ + /* disable all interrupts */ + movew #0x2700, %sr + movel #-1, 0xfffff304 + movel #MEM_END-4, %sp + + PUTC '\r' + PUTC '\n' + PUTC 'A' + PUTC 'B' + +/* + * Determine end of RAM + */ + + movel #MEM_END, %a0 + movel %a0, _ramend + + PUTC 'C' + +/* + * Move ROM filesystem above bss :-) + */ + + moveal #__bss_start, %a0 /* romfs at the start of bss */ + moveal #__bss_stop, %a1 /* Set up destination */ + movel %a0, %a2 /* Copy of bss start */ + + movel 8(%a0), %d1 /* Get size of ROMFS */ + addql #8, %d1 /* Allow for rounding */ + andl #0xfffffffc, %d1 /* Whole words */ + + addl %d1, %a0 /* Copy from end */ + addl %d1, %a1 /* Copy from end */ + movel %a1, _ramstart /* Set start of ram */ + +1: + movel -(%a0), %d0 /* Copy dword */ + movel %d0, -(%a1) + cmpl %a0, %a2 /* Check if at end */ + bne 1b + + PUTC 'D' + +/* + * Initialize BSS segment to 0 + */ + + lea __bss_start, %a0 + lea __bss_stop, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +2: cmpal %a0, %a1 + beq 1f + clrl (%a0)+ + bra 2b +1: + + PUTC 'E' + +/* + * Load the current task pointer and stack + */ + + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + PUTC 'F' + PUTC '\r' + PUTC '\n' + +/* + * Go + */ + + jmp start_kernel + +/* + * Local functions + */ + +#ifdef CRT_DEBUG +putc: + moveb %d7, 0xfffff907 +1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq 1b + rts +#endif diff --git a/trunk/arch/m68k/platform/68328/head-pilot.S b/trunk/arch/m68k/platform/68328/head-pilot.S new file mode 100644 index 000000000000..45a9dad29e3d --- /dev/null +++ b/trunk/arch/m68k/platform/68328/head-pilot.S @@ -0,0 +1,207 @@ +/* + * linux/arch/m68knommu/platform/68328/head-pilot.S + * - A startup file for the MC68328 + * + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * (c) 1995, Dionne & Associates + * (c) 1995, DKG Display Tech. + */ + +#define ASSEMBLY + +#define IMMED # +#define DBG_PUTC(x) moveb IMMED x, 0xfffff907 + + +.global _stext +.global _start + +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +.global bootlogo_bits + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +.text + +_start: +_stext: + + +#ifdef CONFIG_M68328 + +#ifdef CONFIG_PILOT + .byte 0x4e, 0xfa, 0x00, 0x0a /* Jmp +X bytes */ + .byte 'b', 'o', 'o', 't' + .word 10000 + + nop +#endif + + moveq #0, %d0 + movew %d0, 0xfffff618 /* Watchdog off */ + movel #0x00011f07, 0xfffff114 /* CS A1 Mask */ + + movew #0x0800, 0xfffff906 /* Ignore CTS */ + movew #0x010b, 0xfffff902 /* BAUD to 9600 */ + + movew #0x2410, 0xfffff200 /* PLLCR */ + movew #0x123, 0xfffff202 /* PLLFSR */ + +#ifdef CONFIG_PILOT + moveb #0, 0xfffffA27 /* LCKCON */ + movel #_start, 0xfffffA00 /* LSSA */ + moveb #0xa, 0xfffffA05 /* LVPW */ + movew #0x9f, 0xFFFFFa08 /* LXMAX */ + movew #0x9f, 0xFFFFFa0a /* LYMAX */ + moveb #9, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x04, 0xFFFFFa20 /* LPICF */ + moveb #0x58, 0xfffffA27 /* LCKCON */ + moveb #0x85, 0xfffff429 /* PFDATA */ + moveb #0xd8, 0xfffffA27 /* LCKCON */ + moveb #0xc5, 0xfffff429 /* PFDATA */ + moveb #0xd5, 0xfffff429 /* PFDATA */ + + moveal #0x00100000, %a3 + moveal #0x100ffc00, %a4 +#endif /* CONFIG_PILOT */ + +#endif /* CONFIG_M68328 */ + + movew #0x2700, %sr + lea %a4@(-4), %sp + + DBG_PUTC('\r') + DBG_PUTC('\n') + DBG_PUTC('A') + + moveq #0,%d0 + movew #16384, %d0 /* PLL settle wait loop */ +L0: + subw #1, %d0 + bne L0 + + DBG_PUTC('B') + + /* Copy command line from beginning of RAM (+16) to end of bss */ + movel #CONFIG_VECTORBASE, %d7 + addl #16, %d7 + moveal %d7, %a0 + moveal #__bss_stop, %a1 + lea %a1@(512), %a2 + + DBG_PUTC('C') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +L2: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi L2 + + /* Copy data+init segment from ROM to RAM */ + moveal #_etext, %a0 + moveal #_sdata, %a1 + moveal #__init_end, %a2 + + DBG_PUTC('D') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi LD1 + + DBG_PUTC('E') + + moveal #__bss_start, %a0 + moveal #__bss_stop, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + + DBG_PUTC('F') + + /* Copy command line from end of bss to command line */ + moveal #__bss_stop, %a0 + moveal #command_line, %a1 + lea %a1@(512), %a2 + + DBG_PUTC('G') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +L3: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi L3 + + movel #_sdata, %d0 + movel %d0, _rambase + movel #__bss_stop, %d0 + movel %d0, _ramstart + + movel %a4, %d0 + subl #4096, %d0 /* Reserve 4K of stack */ + moveq #79, %d7 + movel %d0, _ramend + + pea 0 + pea env + pea %sp@(4) + pea 0 + + DBG_PUTC('H') + +#ifdef CONFIG_PILOT + movel #bootlogo_bits, 0xFFFFFA00 + moveb #10, 0xFFFFFA05 + movew #160, 0xFFFFFA08 + movew #160, 0xFFFFFA0A +#endif /* CONFIG_PILOT */ + + DBG_PUTC('I') + + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + DBG_PUTC('J') + DBG_PUTC('\r') + DBG_PUTC('\n') + + jsr start_kernel +_exit: + + jmp _exit + + + .data +env: + .long 0 diff --git a/trunk/arch/m68k/platform/68328/head-ram.S b/trunk/arch/m68k/platform/68328/head-ram.S new file mode 100644 index 000000000000..5189ef926098 --- /dev/null +++ b/trunk/arch/m68k/platform/68328/head-ram.S @@ -0,0 +1,141 @@ + + .global __main + .global __rom_start + + .global _rambase + .global _ramstart + + .global splash_bits + .global _start + .global _stext + .global _edata + +#define DEBUG +#define ROM_OFFSET 0x10C00000 +#define STACK_GAURD 0x10 + + .text + +_start: +_stext: + movew #0x2700, %sr /* Exceptions off! */ + +#if 0 + /* Init chip registers. uCsimm specific */ + moveb #0x00, 0xfffffb0b /* Watchdog off */ + moveb #0x10, 0xfffff000 /* SCR */ + + movew #0x2400, 0xfffff200 /* PLLCR */ + movew #0x0123, 0xfffff202 /* PLLFSR */ + + moveb #0x00, 0xfffff40b /* enable chip select */ + moveb #0x00, 0xfffff423 /* enable /DWE */ + moveb #0x08, 0xfffffd0d /* disable hardmap */ + moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */ + + movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */ + movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */ + + movew #0x8f00, 0xfffffc00 /* DRAM configuration */ + movew #0x9667, 0xfffffc02 /* DRAM control */ + movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */ + movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */ + + moveb #0x40, 0xfffff300 /* IVR */ + movel #0x007FFFFF, %d0 /* IMR */ + movel %d0, 0xfffff304 + + moveb 0xfffff42b, %d0 + andb #0xe0, %d0 + moveb %d0, 0xfffff42b + + moveb #0x08, 0xfffff907 /* Ignore CTS */ + movew #0x010b, 0xfffff902 /* BAUD to 9600 */ + movew #0xe100, 0xfffff900 /* enable */ +#endif + + movew #16384, %d0 /* PLL settle wait loop */ +L0: + subw #1, %d0 + bne L0 +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp1 +#endif /* DEBUG */ + +#ifdef DEBUG + moveq #82, %d7 /* 'R' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp3: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp3 +#endif /* DEBUG */ + moveal #0x007ffff0, %ssp + moveal #__bss_start, %a0 + moveal #__bss_stop, %a1 + + /* Copy 0 to %a0 until %a0 >= %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + +#ifdef DEBUG + moveq #67, %d7 /* 'C' */ + jsr putc +#endif /* DEBUG */ + + pea 0 + pea env + pea %sp@(4) + pea 0 + +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + jsr putc +#endif /* DEBUG */ + +lp: + jsr start_kernel + jmp lp +_exit: + + jmp _exit + +__main: + /* nothing */ + rts + +#ifdef DEBUG +putc: + moveb %d7,0xfffff907 +pclp: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp + rts +#endif /* DEBUG */ + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +env: + .long 0 diff --git a/trunk/arch/m68k/platform/68328/head-rom.S b/trunk/arch/m68k/platform/68328/head-rom.S new file mode 100644 index 000000000000..3dff98ba2e97 --- /dev/null +++ b/trunk/arch/m68k/platform/68328/head-rom.S @@ -0,0 +1,105 @@ + + .global _start + .global _stext + + .global _rambase + .global _ramvec + .global _ramstart + .global _ramend + +#ifdef CONFIG_INIT_LCD + .global bootlogo_bits +#endif + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +#define RAMEND (CONFIG_RAMBASE + CONFIG_RAMSIZE) + + .text +_start: +_stext: movew #0x2700,%sr +#ifdef CONFIG_INIT_LCD + movel #bootlogo_bits, 0xfffffA00 /* LSSA */ + moveb #0x28, 0xfffffA05 /* LVPW */ + movew #0x280, 0xFFFFFa08 /* LXMAX */ + movew #0x1df, 0xFFFFFa0a /* LYMAX */ + moveb #0, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x08, 0xFFFFFa20 /* LPICF */ + moveb #0x01, 0xFFFFFA21 /* -ve pol */ + moveb #0x81, 0xfffffA27 /* LCKCON */ + movew #0xff00, 0xfffff412 /* LCD pins */ +#endif + moveal #RAMEND-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp + movew #32767, %d0 /* PLL settle wait loop */ +1: subq #1, %d0 + bne 1b + + /* Copy data segment from ROM to RAM */ + moveal #_etext, %a0 + moveal #_sdata, %a1 + moveal #_edata, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +1: movel %a0@+, %a1@+ + cmpal %a1, %a2 + bhi 1b + + moveal #__bss_start, %a0 + moveal #__bss_stop, %a1 + /* Copy 0 to %a0 until %a0 == %a1 */ + +1: + clrl %a0@+ + cmpal %a0, %a1 + bhi 1b + + movel #_sdata, %d0 + movel %d0, _rambase + movel #__bss_stop, %d0 + movel %d0, _ramstart + movel #RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0 + movel %d0, _ramend + movel #CONFIG_VECTORBASE, %d0 + movel %d0, _ramvec + +/* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + +1: jsr start_kernel + bra 1b +_exit: + + jmp _exit + + +putc: + moveb %d7,0xfffff907 +1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq 1b + rts + + .data +env: + .long 0 + .text + diff --git a/trunk/arch/m68k/platform/68000/ints.c b/trunk/arch/m68k/platform/68328/ints.c similarity index 98% rename from trunk/arch/m68k/platform/68000/ints.c rename to trunk/arch/m68k/platform/68328/ints.c index cda49b12d7be..b3810febb3e3 100644 --- a/trunk/arch/m68k/platform/68000/ints.c +++ b/trunk/arch/m68k/platform/68328/ints.c @@ -1,5 +1,5 @@ /* - * ints.c - Generic interrupt controller support + * linux/arch/m68knommu/platform/68328/ints.c * * 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 diff --git a/trunk/arch/m68k/platform/68000/romvec.S b/trunk/arch/m68k/platform/68328/romvec.S similarity index 94% rename from trunk/arch/m68k/platform/68000/romvec.S rename to trunk/arch/m68k/platform/68328/romvec.S index 15c70cd6453f..31084466eae8 100644 --- a/trunk/arch/m68k/platform/68000/romvec.S +++ b/trunk/arch/m68k/platform/68328/romvec.S @@ -1,5 +1,5 @@ /* - * romvec.S - Vector table for 68000 cpus + * linux/arch/m68knommu/platform/68328/romvec.S * * 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 diff --git a/trunk/arch/m68k/platform/68000/timers.c b/trunk/arch/m68k/platform/68328/timers.c similarity index 98% rename from trunk/arch/m68k/platform/68000/timers.c rename to trunk/arch/m68k/platform/68328/timers.c index ec30acbfe6db..f4dc9b295609 100644 --- a/trunk/arch/m68k/platform/68000/timers.c +++ b/trunk/arch/m68k/platform/68328/timers.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * timers.c - Generic hardware timer support. + * linux/arch/m68knommu/platform/68328/timers.c * * Copyright (C) 1993 Hamish Macdonald * Copyright (C) 1999 D. Jeff Dionne diff --git a/trunk/arch/m68k/platform/68EZ328/Makefile b/trunk/arch/m68k/platform/68EZ328/Makefile new file mode 100644 index 000000000000..b44d799b1115 --- /dev/null +++ b/trunk/arch/m68k/platform/68EZ328/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for arch/m68knommu/platform/68EZ328. +# + +obj-y := config.o diff --git a/trunk/arch/m68k/platform/68000/m68EZ328.c b/trunk/arch/m68k/platform/68EZ328/config.c similarity index 97% rename from trunk/arch/m68k/platform/68000/m68EZ328.c rename to trunk/arch/m68k/platform/68EZ328/config.c index a6eb72d75008..4f158d551f02 100644 --- a/trunk/arch/m68k/platform/68000/m68EZ328.c +++ b/trunk/arch/m68k/platform/68EZ328/config.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * m68EZ328.c - 68EZ328 specific config + * linux/arch/m68knommu/platform/68EZ328/config.c * * Copyright (C) 1993 Hamish Macdonald * Copyright (C) 1999 D. Jeff Dionne diff --git a/trunk/arch/m68k/platform/68VZ328/Makefile b/trunk/arch/m68k/platform/68VZ328/Makefile new file mode 100644 index 000000000000..816674164682 --- /dev/null +++ b/trunk/arch/m68k/platform/68VZ328/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for arch/m68k/platform/68VZ328. +# + +obj-y := config.o diff --git a/trunk/arch/m68k/platform/68000/bootlogo-vz.h b/trunk/arch/m68k/platform/68VZ328/bootlogo.h similarity index 100% rename from trunk/arch/m68k/platform/68000/bootlogo-vz.h rename to trunk/arch/m68k/platform/68VZ328/bootlogo.h diff --git a/trunk/arch/m68k/platform/68000/m68VZ328.c b/trunk/arch/m68k/platform/68VZ328/config.c similarity index 98% rename from trunk/arch/m68k/platform/68000/m68VZ328.c rename to trunk/arch/m68k/platform/68VZ328/config.c index eb6964fbec09..2ed8dc305e42 100644 --- a/trunk/arch/m68k/platform/68000/m68VZ328.c +++ b/trunk/arch/m68k/platform/68VZ328/config.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * m68VZ328.c - 68VZ328 specific config + * linux/arch/m68knommu/platform/68VZ328/config.c * * Copyright (C) 1993 Hamish Macdonald * Copyright (C) 1999 D. Jeff Dionne @@ -28,7 +28,7 @@ #include #ifdef CONFIG_INIT_LCD -#include "bootlogo-vz.h" +#include "bootlogo.h" #endif /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/clk.c b/trunk/arch/m68k/platform/coldfire/clk.c index fddfdccae63b..9cd13b4ce42b 100644 --- a/trunk/arch/m68k/platform/coldfire/clk.c +++ b/trunk/arch/m68k/platform/coldfire/clk.c @@ -19,58 +19,37 @@ #include #include -static DEFINE_SPINLOCK(clk_lock); - -#ifdef MCFPM_PPMCR0 -/* - * For more advanced ColdFire parts that have clocks that can be enabled - * we supply enable/disable functions. These must properly define their - * clocks in their platform specific code. - */ -void __clk_init_enabled(struct clk *clk) -{ - clk->enabled = 1; - clk->clk_ops->enable(clk); -} - -void __clk_init_disabled(struct clk *clk) +/***************************************************************************/ +#ifndef MCFPM_PPMCR0 +struct clk *clk_get(struct device *dev, const char *id) { - clk->enabled = 0; - clk->clk_ops->disable(clk); + return NULL; } +EXPORT_SYMBOL(clk_get); -static void __clk_enable0(struct clk *clk) +int clk_enable(struct clk *clk) { - __raw_writeb(clk->slot, MCFPM_PPMCR0); + return 0; } +EXPORT_SYMBOL(clk_enable); -static void __clk_disable0(struct clk *clk) +void clk_disable(struct clk *clk) { - __raw_writeb(clk->slot, MCFPM_PPMSR0); } +EXPORT_SYMBOL(clk_disable); -struct clk_ops clk_ops0 = { - .enable = __clk_enable0, - .disable = __clk_disable0, -}; - -#ifdef MCFPM_PPMCR1 -static void __clk_enable1(struct clk *clk) +void clk_put(struct clk *clk) { - __raw_writeb(clk->slot, MCFPM_PPMCR1); } +EXPORT_SYMBOL(clk_put); -static void __clk_disable1(struct clk *clk) +unsigned long clk_get_rate(struct clk *clk) { - __raw_writeb(clk->slot, MCFPM_PPMSR1); + return MCF_CLK; } - -struct clk_ops clk_ops1 = { - .enable = __clk_enable1, - .disable = __clk_disable1, -}; -#endif /* MCFPM_PPMCR1 */ -#endif /* MCFPM_PPMCR0 */ +EXPORT_SYMBOL(clk_get_rate); +#else +static DEFINE_SPINLOCK(clk_lock); struct clk *clk_get(struct device *dev, const char *id) { @@ -122,3 +101,48 @@ unsigned long clk_get_rate(struct clk *clk) EXPORT_SYMBOL(clk_get_rate); /***************************************************************************/ + +void __clk_init_enabled(struct clk *clk) +{ + clk->enabled = 1; + clk->clk_ops->enable(clk); +} + +void __clk_init_disabled(struct clk *clk) +{ + clk->enabled = 0; + clk->clk_ops->disable(clk); +} + +static void __clk_enable0(struct clk *clk) +{ + __raw_writeb(clk->slot, MCFPM_PPMCR0); +} + +static void __clk_disable0(struct clk *clk) +{ + __raw_writeb(clk->slot, MCFPM_PPMSR0); +} + +struct clk_ops clk_ops0 = { + .enable = __clk_enable0, + .disable = __clk_disable0, +}; + +#ifdef MCFPM_PPMCR1 +static void __clk_enable1(struct clk *clk) +{ + __raw_writeb(clk->slot, MCFPM_PPMCR1); +} + +static void __clk_disable1(struct clk *clk) +{ + __raw_writeb(clk->slot, MCFPM_PPMSR1); +} + +struct clk_ops clk_ops1 = { + .enable = __clk_enable1, + .disable = __clk_disable1, +}; +#endif /* MCFPM_PPMCR1 */ +#endif /* MCFPM_PPMCR0 */ diff --git a/trunk/arch/m68k/platform/coldfire/intc-5249.c b/trunk/arch/m68k/platform/coldfire/intc-5249.c index b0d1641053e4..0864b836699a 100644 --- a/trunk/arch/m68k/platform/coldfire/intc-5249.c +++ b/trunk/arch/m68k/platform/coldfire/intc-5249.c @@ -21,7 +21,7 @@ static void intc2_irq_gpio_mask(struct irq_data *d) { u32 imr; imr = readl(MCFSIM2_GPIOINTENABLE); - imr &= ~(0x1 << (d->irq - MCF_IRQ_GPIO0)); + imr &= ~(0x1 << (d->irq - MCFINTC2_GPIOIRQ0)); writel(imr, MCFSIM2_GPIOINTENABLE); } @@ -29,13 +29,13 @@ static void intc2_irq_gpio_unmask(struct irq_data *d) { u32 imr; imr = readl(MCFSIM2_GPIOINTENABLE); - imr |= (0x1 << (d->irq - MCF_IRQ_GPIO0)); + imr |= (0x1 << (d->irq - MCFINTC2_GPIOIRQ0)); writel(imr, MCFSIM2_GPIOINTENABLE); } static void intc2_irq_gpio_ack(struct irq_data *d) { - writel(0x1 << (d->irq - MCF_IRQ_GPIO0), MCFSIM2_GPIOINTCLEAR); + writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCFSIM2_GPIOINTCLEAR); } static struct irq_chip intc2_irq_gpio_chip = { @@ -50,7 +50,7 @@ static int __init mcf_intc2_init(void) int irq; /* GPIO interrupt sources */ - for (irq = MCF_IRQ_GPIO0; (irq <= MCF_IRQ_GPIO7); irq++) { + for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) { irq_set_chip(irq, &intc2_irq_gpio_chip); irq_set_handler(irq, handle_edge_irq); } diff --git a/trunk/arch/m68k/platform/coldfire/m5206.c b/trunk/arch/m68k/platform/coldfire/m5206.c index 0e55f449a88c..6bfbeebd231b 100644 --- a/trunk/arch/m68k/platform/coldfire/m5206.c +++ b/trunk/arch/m68k/platform/coldfire/m5206.c @@ -16,26 +16,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m523x.c b/trunk/arch/m68k/platform/coldfire/m523x.c index 2b10e9f198cd..ff37fe9553ea 100644 --- a/trunk/arch/m68k/platform/coldfire/m523x.c +++ b/trunk/arch/m68k/platform/coldfire/m523x.c @@ -19,34 +19,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_fec0, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m5249.c b/trunk/arch/m68k/platform/coldfire/m5249.c index c80b5e51d29a..23b19cb7ab50 100644 --- a/trunk/arch/m68k/platform/coldfire/m5249.c +++ b/trunk/arch/m68k/platform/coldfire/m5249.c @@ -16,26 +16,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - NULL -}; /***************************************************************************/ @@ -48,8 +28,8 @@ static struct resource m5249_smc91x_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = MCF_IRQ_GPIO6, - .end = MCF_IRQ_GPIO6, + .start = MCFINTC2_GPIOIRQ6, + .end = MCFINTC2_GPIOIRQ6, .flags = IORESOURCE_IRQ, }, }; @@ -95,8 +75,8 @@ static void __init m5249_smc91x_init(void) gpio = readl(MCFSIM2_GPIOINTENABLE); writel(gpio | 0x40, MCFSIM2_GPIOINTENABLE); - gpio = readl(MCFINTC2_INTPRI5); - writel(gpio | 0x04000000, MCFINTC2_INTPRI5); + gpio = readl(MCFSIM2_INTLEVEL5); + writel(gpio | 0x04000000, MCFSIM2_INTLEVEL5); } #endif /* CONFIG_M5249C3 */ diff --git a/trunk/arch/m68k/platform/coldfire/m525x.c b/trunk/arch/m68k/platform/coldfire/m525x.c index 5b9f657b2df0..fce8f8a45bf0 100644 --- a/trunk/arch/m68k/platform/coldfire/m525x.c +++ b/trunk/arch/m68k/platform/coldfire/m525x.c @@ -16,26 +16,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m5272.c b/trunk/arch/m68k/platform/coldfire/m5272.c index a8c5856fe5ec..45b246d052ef 100644 --- a/trunk/arch/m68k/platform/coldfire/m5272.c +++ b/trunk/arch/m68k/platform/coldfire/m5272.c @@ -19,7 +19,6 @@ #include #include #include -#include /***************************************************************************/ @@ -31,31 +30,6 @@ unsigned char ledbank = 0xff; /***************************************************************************/ -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcftmr2, "mcftmr.2", MCF_BUSCLK); -DEFINE_CLK(mcftmr3, "mcftmr.3", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcftmr2, - &clk_mcftmr3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_fec0, - NULL -}; - -/***************************************************************************/ - static void __init m5272_uarts_init(void) { u32 v; diff --git a/trunk/arch/m68k/platform/coldfire/m527x.c b/trunk/arch/m68k/platform/coldfire/m527x.c index 6fbfe9096c3e..1431ba03c602 100644 --- a/trunk/arch/m68k/platform/coldfire/m527x.c +++ b/trunk/arch/m68k/platform/coldfire/m527x.c @@ -20,36 +20,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); -DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_fec0, - &clk_fec1, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m528x.c b/trunk/arch/m68k/platform/coldfire/m528x.c index 83b7dad7a84e..f9f7e6a13d04 100644 --- a/trunk/arch/m68k/platform/coldfire/m528x.c +++ b/trunk/arch/m68k/platform/coldfire/m528x.c @@ -21,34 +21,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_fec0, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m5307.c b/trunk/arch/m68k/platform/coldfire/m5307.c index 887435361386..a568d2870d15 100644 --- a/trunk/arch/m68k/platform/coldfire/m5307.c +++ b/trunk/arch/m68k/platform/coldfire/m5307.c @@ -17,7 +17,6 @@ #include #include #include -#include /***************************************************************************/ @@ -29,25 +28,6 @@ unsigned char ledbank = 0xff; /***************************************************************************/ -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - NULL -}; - -/***************************************************************************/ - void __init config_BSP(char *commandp, int size) { #if defined(CONFIG_NETtel) || \ diff --git a/trunk/arch/m68k/platform/coldfire/m5407.c b/trunk/arch/m68k/platform/coldfire/m5407.c index 2fb3cdbfde30..bb6c746ae819 100644 --- a/trunk/arch/m68k/platform/coldfire/m5407.c +++ b/trunk/arch/m68k/platform/coldfire/m5407.c @@ -16,26 +16,6 @@ #include #include #include -#include - -/***************************************************************************/ - -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - NULL -}; /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/coldfire/m54xx.c b/trunk/arch/m68k/platform/coldfire/m54xx.c index 952da53aa0bc..b587bf35175b 100644 --- a/trunk/arch/m68k/platform/coldfire/m54xx.c +++ b/trunk/arch/m68k/platform/coldfire/m54xx.c @@ -14,45 +14,19 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include -#include #ifdef CONFIG_MMU #include #endif /***************************************************************************/ -DEFINE_CLK(pll, "pll.0", MCF_CLK); -DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfslt0, "mcfslt.0", MCF_BUSCLK); -DEFINE_CLK(mcfslt1, "mcfslt.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK); - -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfslt0, - &clk_mcfslt1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_mcfuart3, - NULL -}; - -/***************************************************************************/ - static void __init m54xx_uarts_init(void) { /* enable io pins */ diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 0f7c852f355c..cb8f9920f4dd 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -111,7 +111,6 @@ config VSYSCALL config NUMA bool "Non Uniform Memory Access (NUMA) Support" depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL - select ARCH_WANT_NUMA_VARIABLE_LOCALITY default n help Some SH systems have many various memories scattered around diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 97f8c5ad8c2d..65a872bf72f9 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -22,8 +22,6 @@ config X86 def_bool y select HAVE_AOUT if X86_32 select HAVE_UNSTABLE_SCHED_CLOCK - select ARCH_SUPPORTS_NUMA_BALANCING - select ARCH_WANTS_PROT_NUMA_PROT_NONE select HAVE_IDE select HAVE_OPROFILE select HAVE_PCSPKR_PLATFORM diff --git a/trunk/arch/x86/include/asm/efi.h b/trunk/arch/x86/include/asm/efi.h index 6e8fdf5ad113..fd13815fe85c 100644 --- a/trunk/arch/x86/include/asm/efi.h +++ b/trunk/arch/x86/include/asm/efi.h @@ -69,23 +69,37 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \ (u64)(a4), (u64)(a5), (u64)(a6)) +extern unsigned long efi_call_virt_prelog(void); +extern void efi_call_virt_epilog(unsigned long); + +#define efi_callx(x, func, ...) \ + ({ \ + efi_status_t __status; \ + unsigned long __pgd; \ + \ + __pgd = efi_call_virt_prelog(); \ + __status = efi_call##x(func, __VA_ARGS__); \ + efi_call_virt_epilog(__pgd); \ + __status; \ + }) + #define efi_call_virt0(f) \ - efi_call0((void *)(efi.systab->runtime->f)) + efi_callx(0, (void *)(efi.systab->runtime->f)) #define efi_call_virt1(f, a1) \ - efi_call1((void *)(efi.systab->runtime->f), (u64)(a1)) + efi_callx(1, (void *)(efi.systab->runtime->f), (u64)(a1)) #define efi_call_virt2(f, a1, a2) \ - efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2)) + efi_callx(2, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2)) #define efi_call_virt3(f, a1, a2, a3) \ - efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + efi_callx(3, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3)) #define efi_call_virt4(f, a1, a2, a3, a4) \ - efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + efi_callx(4, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4)) #define efi_call_virt5(f, a1, a2, a3, a4, a5) \ - efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + efi_callx(5, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5)) #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ - efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + efi_callx(6, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, diff --git a/trunk/arch/x86/include/asm/pgtable.h b/trunk/arch/x86/include/asm/pgtable.h index 5199db2923d3..a1f780d45f76 100644 --- a/trunk/arch/x86/include/asm/pgtable.h +++ b/trunk/arch/x86/include/asm/pgtable.h @@ -404,14 +404,7 @@ static inline int pte_same(pte_t a, pte_t b) static inline int pte_present(pte_t a) { - return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE | - _PAGE_NUMA); -} - -#define pte_accessible pte_accessible -static inline int pte_accessible(pte_t a) -{ - return pte_flags(a) & _PAGE_PRESENT; + return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE); } static inline int pte_hidden(pte_t pte) @@ -427,8 +420,7 @@ static inline int pmd_present(pmd_t pmd) * the _PAGE_PSE flag will remain set at all times while the * _PAGE_PRESENT bit is clear). */ - return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE | - _PAGE_NUMA); + return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE); } static inline int pmd_none(pmd_t pmd) @@ -487,11 +479,6 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) static inline int pmd_bad(pmd_t pmd) { -#ifdef CONFIG_NUMA_BALANCING - /* pmd_numa check */ - if ((pmd_flags(pmd) & (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA) - return 0; -#endif return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE; } diff --git a/trunk/arch/x86/include/asm/pgtable_types.h b/trunk/arch/x86/include/asm/pgtable_types.h index 3c32db8c539d..ec8a1fc9505d 100644 --- a/trunk/arch/x86/include/asm/pgtable_types.h +++ b/trunk/arch/x86/include/asm/pgtable_types.h @@ -64,26 +64,6 @@ #define _PAGE_FILE (_AT(pteval_t, 1) << _PAGE_BIT_FILE) #define _PAGE_PROTNONE (_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE) -/* - * _PAGE_NUMA indicates that this page will trigger a numa hinting - * minor page fault to gather numa placement statistics (see - * pte_numa()). The bit picked (8) is within the range between - * _PAGE_FILE (6) and _PAGE_PROTNONE (8) bits. Therefore, it doesn't - * require changes to the swp entry format because that bit is always - * zero when the pte is not present. - * - * The bit picked must be always zero when the pmd is present and not - * present, so that we don't lose information when we set it while - * atomically clearing the present bit. - * - * Because we shared the same bit (8) with _PAGE_PROTNONE this can be - * interpreted as _PAGE_NUMA only in places that _PAGE_PROTNONE - * couldn't reach, like handle_mm_fault() (see access_error in - * arch/x86/mm/fault.c, the vma protection must not be PROT_NONE for - * handle_mm_fault() to be invoked). - */ -#define _PAGE_NUMA _PAGE_PROTNONE - #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ diff --git a/trunk/arch/x86/kernel/tboot.c b/trunk/arch/x86/kernel/tboot.c index f84fe00fad48..d4f460f962ee 100644 --- a/trunk/arch/x86/kernel/tboot.c +++ b/trunk/arch/x86/kernel/tboot.c @@ -103,71 +103,13 @@ void __init tboot_probe(void) pr_debug("tboot_size: 0x%x\n", tboot->tboot_size); } -static pgd_t *tboot_pg_dir; -static struct mm_struct tboot_mm = { - .mm_rb = RB_ROOT, - .pgd = swapper_pg_dir, - .mm_users = ATOMIC_INIT(2), - .mm_count = ATOMIC_INIT(1), - .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), - .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), - .mmlist = LIST_HEAD_INIT(init_mm.mmlist), -}; - static inline void switch_to_tboot_pt(void) { - write_cr3(virt_to_phys(tboot_pg_dir)); -} - -static int map_tboot_page(unsigned long vaddr, unsigned long pfn, - pgprot_t prot) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - pgd = pgd_offset(&tboot_mm, vaddr); - pud = pud_alloc(&tboot_mm, pgd, vaddr); - if (!pud) - return -1; - pmd = pmd_alloc(&tboot_mm, pud, vaddr); - if (!pmd) - return -1; - pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr); - if (!pte) - return -1; - set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot)); - pte_unmap(pte); - return 0; -} - -static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn, - unsigned long nr) -{ - /* Reuse the original kernel mapping */ - tboot_pg_dir = pgd_alloc(&tboot_mm); - if (!tboot_pg_dir) - return -1; - - for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) { - if (map_tboot_page(vaddr, start_pfn, PAGE_KERNEL_EXEC)) - return -1; - } - - return 0; -} - -static void tboot_create_trampoline(void) -{ - u32 map_base, map_size; - - /* Create identity map for tboot shutdown code. */ - map_base = PFN_DOWN(tboot->tboot_base); - map_size = PFN_UP(tboot->tboot_size); - if (map_tboot_pages(map_base << PAGE_SHIFT, map_base, map_size)) - panic("tboot: Error mapping tboot pages (mfns) @ 0x%x, 0x%x\n", - map_base, map_size); +#ifdef CONFIG_X86_32 + load_cr3(initial_page_table); +#else + write_cr3(real_mode_header->trampoline_pgd); +#endif } #ifdef CONFIG_ACPI_SLEEP @@ -225,14 +167,6 @@ void tboot_shutdown(u32 shutdown_type) if (!tboot_enabled()) return; - /* - * if we're being called before the 1:1 mapping is set up then just - * return and let the normal shutdown happen; this should only be - * due to very early panic() - */ - if (!tboot_pg_dir) - return; - /* if this is S3 then set regions to MAC */ if (shutdown_type == TB_SHUTDOWN_S3) if (tboot_setup_sleep()) @@ -343,8 +277,6 @@ static __init int tboot_late_init(void) if (!tboot_enabled()) return 0; - tboot_create_trampoline(); - atomic_set(&ap_wfs_count, 0); register_hotcpu_notifier(&tboot_cpu_notifier); diff --git a/trunk/arch/x86/kernel/vsyscall_64.c b/trunk/arch/x86/kernel/vsyscall_64.c index 9a907a67be8f..3a3e8c9e280d 100644 --- a/trunk/arch/x86/kernel/vsyscall_64.c +++ b/trunk/arch/x86/kernel/vsyscall_64.c @@ -145,6 +145,19 @@ static int addr_to_vsyscall_nr(unsigned long addr) return nr; } +#ifdef CONFIG_SECCOMP +static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr) +{ + if (!seccomp_mode(&tsk->seccomp)) + return 0; + task_pt_regs(tsk)->orig_ax = syscall_nr; + task_pt_regs(tsk)->ax = syscall_nr; + return __secure_computing(syscall_nr); +} +#else +#define vsyscall_seccomp(_tsk, _nr) 0 +#endif + static bool write_ok_or_segv(unsigned long ptr, size_t size) { /* @@ -177,9 +190,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) { struct task_struct *tsk; unsigned long caller; - int vsyscall_nr, syscall_nr, tmp; + int vsyscall_nr; int prev_sig_on_uaccess_error; long ret; + int skip; /* * No point in checking CS -- the only way to get here is a user mode @@ -211,84 +225,56 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) } tsk = current; + /* + * With a real vsyscall, page faults cause SIGSEGV. We want to + * preserve that behavior to make writing exploits harder. + */ + prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error; + current_thread_info()->sig_on_uaccess_error = 1; /* - * Check for access_ok violations and find the syscall nr. - * * NULL is a valid user pointer (in the access_ok sense) on 32-bit and * 64-bit, so we don't need to special-case it here. For all the * vsyscalls, NULL means "don't write anything" not "write it at * address 0". */ + ret = -EFAULT; + skip = 0; switch (vsyscall_nr) { case 0: - if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || - !write_ok_or_segv(regs->si, sizeof(struct timezone))) { - ret = -EFAULT; - goto check_fault; - } - - syscall_nr = __NR_gettimeofday; - break; - - case 1: - if (!write_ok_or_segv(regs->di, sizeof(time_t))) { - ret = -EFAULT; - goto check_fault; - } - - syscall_nr = __NR_time; - break; - - case 2: - if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || - !write_ok_or_segv(regs->si, sizeof(unsigned))) { - ret = -EFAULT; - goto check_fault; - } - - syscall_nr = __NR_getcpu; - break; - } - - /* - * Handle seccomp. regs->ip must be the original value. - * See seccomp_send_sigsys and Documentation/prctl/seccomp_filter.txt. - * - * We could optimize the seccomp disabled case, but performance - * here doesn't matter. - */ - regs->orig_ax = syscall_nr; - regs->ax = -ENOSYS; - tmp = secure_computing(syscall_nr); - if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { - warn_bad_vsyscall(KERN_DEBUG, regs, - "seccomp tried to change syscall nr or ip"); - do_exit(SIGSYS); - } - if (tmp) - goto do_ret; /* skip requested */ + skip = vsyscall_seccomp(tsk, __NR_gettimeofday); + if (skip) + break; - /* - * With a real vsyscall, page faults cause SIGSEGV. We want to - * preserve that behavior to make writing exploits harder. - */ - prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error; - current_thread_info()->sig_on_uaccess_error = 1; + if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || + !write_ok_or_segv(regs->si, sizeof(struct timezone))) + break; - ret = -EFAULT; - switch (vsyscall_nr) { - case 0: ret = sys_gettimeofday( (struct timeval __user *)regs->di, (struct timezone __user *)regs->si); break; case 1: + skip = vsyscall_seccomp(tsk, __NR_time); + if (skip) + break; + + if (!write_ok_or_segv(regs->di, sizeof(time_t))) + break; + ret = sys_time((time_t __user *)regs->di); break; case 2: + skip = vsyscall_seccomp(tsk, __NR_getcpu); + if (skip) + break; + + if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || + !write_ok_or_segv(regs->si, sizeof(unsigned))) + break; + ret = sys_getcpu((unsigned __user *)regs->di, (unsigned __user *)regs->si, NULL); @@ -297,7 +283,12 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; -check_fault: + if (skip) { + if ((long)regs->ax <= 0L) /* seccomp errno emulation */ + goto do_ret; + goto done; /* seccomp trace/trap */ + } + if (ret == -EFAULT) { /* Bad news -- userspace fed a bad pointer to a vsyscall. */ warn_bad_vsyscall(KERN_INFO, regs, @@ -320,6 +311,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) /* Emulate a ret instruction. */ regs->ip = caller; regs->sp += 8; +done: return true; sigsegv: diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index a718e0d23503..931930a96160 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -919,11 +919,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, /* * On success we use clflush, when the CPU supports it to - * avoid the wbindv. If the CPU does not support it and in the - * error case we fall back to cpa_flush_all (which uses - * wbindv): + * avoid the wbindv. If the CPU does not support it, in the + * error case, and during early boot (for EFI) we fall back + * to cpa_flush_all (which uses wbinvd): */ - if (!ret && cpu_has_clflush) { + if (early_boot_irqs_disabled) + __cpa_flush_all((void *)(long)cache); + else if (!ret && cpu_has_clflush) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/trunk/arch/x86/mm/pgtable.c b/trunk/arch/x86/mm/pgtable.c index e27fbf887f3b..217eb705fac0 100644 --- a/trunk/arch/x86/mm/pgtable.c +++ b/trunk/arch/x86/mm/pgtable.c @@ -301,13 +301,6 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd) free_page((unsigned long)pgd); } -/* - * Used to set accessed or dirty bits in the page table entries - * on other architectures. On x86, the accessed and dirty bits - * are tracked by hardware. However, do_wp_page calls this function - * to also make the pte writeable at the same time the dirty bit is - * set. In that case we do actually need to write the PTE. - */ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, pte_t entry, int dirty) @@ -317,6 +310,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, if (changed && dirty) { *ptep = entry; pte_update_defer(vma->vm_mm, address, ptep); + flush_tlb_page(vma, address); } return changed; diff --git a/trunk/arch/x86/platform/efi/efi.c b/trunk/arch/x86/platform/efi/efi.c index ad4439145f85..0a34d9e9c263 100644 --- a/trunk/arch/x86/platform/efi/efi.c +++ b/trunk/arch/x86/platform/efi/efi.c @@ -239,22 +239,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( return status; } -static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) -{ - unsigned long flags; - efi_status_t status; - - spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), - virt_to_phys(tc)); - efi_call_phys_epilog(); - spin_unlock_irqrestore(&rtc_lock, flags); - return status; -} - -int efi_set_rtc_mmss(unsigned long nowtime) +static int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -283,7 +268,7 @@ int efi_set_rtc_mmss(unsigned long nowtime) return 0; } -unsigned long efi_get_time(void) +static unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; @@ -639,18 +624,13 @@ static int __init efi_runtime_init(void) } /* * We will only need *early* access to the following - * two EFI runtime services before set_virtual_address_map + * EFI runtime service before set_virtual_address_map * is invoked. */ - efi_phys.get_time = (efi_get_time_t *)runtime->get_time; efi_phys.set_virtual_address_map = (efi_set_virtual_address_map_t *) runtime->set_virtual_address_map; - /* - * Make efi_get_time can be called before entering - * virtual mode. - */ - efi.get_time = phys_efi_get_time; + early_iounmap(runtime, sizeof(efi_runtime_services_t)); return 0; @@ -736,12 +716,10 @@ void __init efi_init(void) efi_enabled = 0; return; } -#ifdef CONFIG_X86_32 if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } -#endif #if EFI_DEBUG print_efi_memmap(); diff --git a/trunk/arch/x86/platform/efi/efi_64.c b/trunk/arch/x86/platform/efi/efi_64.c index 95fd505dfeb6..06c8b2e662ab 100644 --- a/trunk/arch/x86/platform/efi/efi_64.c +++ b/trunk/arch/x86/platform/efi/efi_64.c @@ -58,6 +58,21 @@ static void __init early_code_mapping_set_exec(int executable) } } +unsigned long efi_call_virt_prelog(void) +{ + unsigned long saved; + + saved = read_cr3(); + write_cr3(real_mode_header->trampoline_pgd); + + return saved; +} + +void efi_call_virt_epilog(unsigned long saved) +{ + write_cr3(saved); +} + void __init efi_call_phys_prelog(void) { unsigned long vaddress; diff --git a/trunk/block/blk-cgroup.c b/trunk/block/blk-cgroup.c index b8858fb0cafa..3f6d39d23bb6 100644 --- a/trunk/block/blk-cgroup.c +++ b/trunk/block/blk-cgroup.c @@ -231,7 +231,7 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, * we shouldn't allow anything to go through for a bypassing queue. */ if (unlikely(blk_queue_bypass(q))) - return ERR_PTR(blk_queue_dying(q) ? -EINVAL : -EBUSY); + return ERR_PTR(blk_queue_dead(q) ? -EINVAL : -EBUSY); return __blkg_lookup_create(blkcg, q, NULL); } EXPORT_SYMBOL_GPL(blkg_lookup_create); diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index c973249d68cd..3c95c4d6e31a 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -40,7 +40,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap); EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap); EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete); -EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug); DEFINE_IDA(blk_queue_ida); @@ -220,13 +219,12 @@ static void blk_delay_work(struct work_struct *work) * Description: * Sometimes queueing needs to be postponed for a little while, to allow * resources to come back. This function will make sure that queueing is - * restarted around the specified time. Queue lock must be held. + * restarted around the specified time. */ void blk_delay_queue(struct request_queue *q, unsigned long msecs) { - if (likely(!blk_queue_dead(q))) - queue_delayed_work(kblockd_workqueue, &q->delay_work, - msecs_to_jiffies(msecs)); + queue_delayed_work(kblockd_workqueue, &q->delay_work, + msecs_to_jiffies(msecs)); } EXPORT_SYMBOL(blk_delay_queue); @@ -294,34 +292,6 @@ void blk_sync_queue(struct request_queue *q) } EXPORT_SYMBOL(blk_sync_queue); -/** - * __blk_run_queue_uncond - run a queue whether or not it has been stopped - * @q: The queue to run - * - * Description: - * Invoke request handling on a queue if there are any pending requests. - * May be used to restart request handling after a request has completed. - * This variant runs the queue whether or not the queue has been - * stopped. Must be called with the queue lock held and interrupts - * disabled. See also @blk_run_queue. - */ -inline void __blk_run_queue_uncond(struct request_queue *q) -{ - if (unlikely(blk_queue_dead(q))) - return; - - /* - * Some request_fn implementations, e.g. scsi_request_fn(), unlock - * the queue lock internally. As a result multiple threads may be - * running such a request function concurrently. Keep track of the - * number of active request_fn invocations such that blk_drain_queue() - * can wait until all these request_fn calls have finished. - */ - q->request_fn_active++; - q->request_fn(q); - q->request_fn_active--; -} - /** * __blk_run_queue - run a single device queue * @q: The queue to run @@ -335,7 +305,7 @@ void __blk_run_queue(struct request_queue *q) if (unlikely(blk_queue_stopped(q))) return; - __blk_run_queue_uncond(q); + q->request_fn(q); } EXPORT_SYMBOL(__blk_run_queue); @@ -345,11 +315,11 @@ EXPORT_SYMBOL(__blk_run_queue); * * Description: * Tells kblockd to perform the equivalent of @blk_run_queue on behalf - * of us. The caller must hold the queue lock. + * of us. */ void blk_run_queue_async(struct request_queue *q) { - if (likely(!blk_queue_stopped(q) && !blk_queue_dead(q))) + if (likely(!blk_queue_stopped(q))) mod_delayed_work(kblockd_workqueue, &q->delay_work, 0); } EXPORT_SYMBOL(blk_run_queue_async); @@ -379,7 +349,7 @@ void blk_put_queue(struct request_queue *q) EXPORT_SYMBOL(blk_put_queue); /** - * __blk_drain_queue - drain requests from request_queue + * blk_drain_queue - drain requests from request_queue * @q: queue to drain * @drain_all: whether to drain all requests or only the ones w/ ELVPRIV * @@ -387,17 +357,15 @@ EXPORT_SYMBOL(blk_put_queue); * If not, only ELVPRIV requests are drained. The caller is responsible * for ensuring that no new requests which need to be drained are queued. */ -static void __blk_drain_queue(struct request_queue *q, bool drain_all) - __releases(q->queue_lock) - __acquires(q->queue_lock) +void blk_drain_queue(struct request_queue *q, bool drain_all) { int i; - lockdep_assert_held(q->queue_lock); - while (true) { bool drain = false; + spin_lock_irq(q->queue_lock); + /* * The caller might be trying to drain @q before its * elevator is initialized. @@ -418,7 +386,6 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all) __blk_run_queue(q); drain |= q->nr_rqs_elvpriv; - drain |= q->request_fn_active; /* * Unfortunately, requests are queued at and tracked from @@ -434,14 +401,11 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all) } } - if (!drain) - break; - spin_unlock_irq(q->queue_lock); + if (!drain) + break; msleep(10); - - spin_lock_irq(q->queue_lock); } /* @@ -452,9 +416,13 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all) if (q->request_fn) { struct request_list *rl; + spin_lock_irq(q->queue_lock); + blk_queue_for_each_rl(rl, q) for (i = 0; i < ARRAY_SIZE(rl->wait); i++) wake_up_all(&rl->wait[i]); + + spin_unlock_irq(q->queue_lock); } } @@ -478,10 +446,7 @@ void blk_queue_bypass_start(struct request_queue *q) spin_unlock_irq(q->queue_lock); if (drain) { - spin_lock_irq(q->queue_lock); - __blk_drain_queue(q, false); - spin_unlock_irq(q->queue_lock); - + blk_drain_queue(q, false); /* ensure blk_queue_bypass() is %true inside RCU read lock */ synchronize_rcu(); } @@ -508,20 +473,20 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end); * blk_cleanup_queue - shutdown a request queue * @q: request queue to shutdown * - * Mark @q DYING, drain all pending requests, mark @q DEAD, destroy and - * put it. All future requests will be failed immediately with -ENODEV. + * Mark @q DEAD, drain all pending requests, destroy and put it. All + * future requests will be failed immediately with -ENODEV. */ void blk_cleanup_queue(struct request_queue *q) { spinlock_t *lock = q->queue_lock; - /* mark @q DYING, no new request or merges will be allowed afterwards */ + /* mark @q DEAD, no new request or merges will be allowed afterwards */ mutex_lock(&q->sysfs_lock); - queue_flag_set_unlocked(QUEUE_FLAG_DYING, q); + queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); spin_lock_irq(lock); /* - * A dying queue is permanently in bypass mode till released. Note + * Dead queue is permanently in bypass mode till released. Note * that, unlike blk_queue_bypass_start(), we aren't performing * synchronize_rcu() after entering bypass mode to avoid the delay * as some drivers create and destroy a lot of queues while @@ -534,18 +499,12 @@ void blk_cleanup_queue(struct request_queue *q) queue_flag_set(QUEUE_FLAG_NOMERGES, q); queue_flag_set(QUEUE_FLAG_NOXMERGES, q); - queue_flag_set(QUEUE_FLAG_DYING, q); + queue_flag_set(QUEUE_FLAG_DEAD, q); spin_unlock_irq(lock); mutex_unlock(&q->sysfs_lock); - /* - * Drain all requests queued before DYING marking. Set DEAD flag to - * prevent that q->request_fn() gets invoked after draining finished. - */ - spin_lock_irq(lock); - __blk_drain_queue(q, true); - queue_flag_set(QUEUE_FLAG_DEAD, q); - spin_unlock_irq(lock); + /* drain all requests queued before DEAD marking */ + blk_drain_queue(q, true); /* @q won't process any more request, flush async actions */ del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); @@ -590,7 +549,7 @@ void blk_exit_rl(struct request_list *rl) struct request_queue *blk_alloc_queue(gfp_t gfp_mask) { - return blk_alloc_queue_node(gfp_mask, NUMA_NO_NODE); + return blk_alloc_queue_node(gfp_mask, -1); } EXPORT_SYMBOL(blk_alloc_queue); @@ -701,7 +660,7 @@ EXPORT_SYMBOL(blk_alloc_queue_node); struct request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) { - return blk_init_queue_node(rfn, lock, NUMA_NO_NODE); + return blk_init_queue_node(rfn, lock, -1); } EXPORT_SYMBOL(blk_init_queue); @@ -757,7 +716,7 @@ EXPORT_SYMBOL(blk_init_allocated_queue); bool blk_get_queue(struct request_queue *q) { - if (likely(!blk_queue_dying(q))) { + if (likely(!blk_queue_dead(q))) { __blk_get_queue(q); return true; } @@ -911,7 +870,7 @@ static struct request *__get_request(struct request_list *rl, int rw_flags, const bool is_sync = rw_is_sync(rw_flags) != 0; int may_queue; - if (unlikely(blk_queue_dying(q))) + if (unlikely(blk_queue_dead(q))) return NULL; may_queue = elv_may_queue(q, rw_flags); @@ -1091,7 +1050,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags, if (rq) return rq; - if (!(gfp_mask & __GFP_WAIT) || unlikely(blk_queue_dying(q))) { + if (!(gfp_mask & __GFP_WAIT) || unlikely(blk_queue_dead(q))) { blk_put_rl(rl); return NULL; } @@ -1951,7 +1910,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) return -EIO; spin_lock_irqsave(q->queue_lock, flags); - if (unlikely(blk_queue_dying(q))) { + if (unlikely(blk_queue_dead(q))) { spin_unlock_irqrestore(q->queue_lock, flags); return -ENODEV; } @@ -2925,11 +2884,27 @@ static void queue_unplugged(struct request_queue *q, unsigned int depth, { trace_block_unplug(q, depth, !from_schedule); - if (from_schedule) + /* + * Don't mess with dead queue. + */ + if (unlikely(blk_queue_dead(q))) { + spin_unlock(q->queue_lock); + return; + } + + /* + * If we are punting this to kblockd, then we can safely drop + * the queue_lock before waking kblockd (which needs to take + * this lock). + */ + if (from_schedule) { + spin_unlock(q->queue_lock); blk_run_queue_async(q); - else + } else { __blk_run_queue(q); - spin_unlock(q->queue_lock); + spin_unlock(q->queue_lock); + } + } static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule) @@ -3021,7 +2996,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) /* * Short-circuit if @q is dead */ - if (unlikely(blk_queue_dying(q))) { + if (unlikely(blk_queue_dead(q))) { __blk_end_request_all(rq, -ENODEV); continue; } diff --git a/trunk/block/blk-exec.c b/trunk/block/blk-exec.c index 74638ec234c8..f71eac35c1b9 100644 --- a/trunk/block/blk-exec.c +++ b/trunk/block/blk-exec.c @@ -66,7 +66,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, spin_lock_irq(q->queue_lock); - if (unlikely(blk_queue_dying(q))) { + if (unlikely(blk_queue_dead(q))) { rq->errors = -ENXIO; if (rq->end_io) rq->end_io(rq, rq->errors); @@ -78,7 +78,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, __blk_run_queue(q); /* the queue is stopped so it won't be run */ if (is_pm_resume) - __blk_run_queue_uncond(q); + q->request_fn(q); spin_unlock_irq(q->queue_lock); } EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); diff --git a/trunk/block/blk-lib.c b/trunk/block/blk-lib.c index b3a1f2b70b31..9373b58dfab1 100644 --- a/trunk/block/blk-lib.c +++ b/trunk/block/blk-lib.c @@ -43,12 +43,11 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q = bdev_get_queue(bdev); int type = REQ_WRITE | REQ_DISCARD; - sector_t max_discard_sectors; - sector_t granularity, alignment; + unsigned int max_discard_sectors; + unsigned int granularity, alignment, mask; struct bio_batch bb; struct bio *bio; int ret = 0; - struct blk_plug plug; if (!q) return -ENXIO; @@ -58,16 +57,15 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, /* Zero-sector (unknown) and one-sector granularities are the same. */ granularity = max(q->limits.discard_granularity >> 9, 1U); - alignment = bdev_discard_alignment(bdev) >> 9; - alignment = sector_div(alignment, granularity); + mask = granularity - 1; + alignment = (bdev_discard_alignment(bdev) >> 9) & mask; /* * Ensure that max_discard_sectors is of the proper * granularity, so that requests stay aligned after a split. */ max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9); - sector_div(max_discard_sectors, granularity); - max_discard_sectors *= granularity; + max_discard_sectors = round_down(max_discard_sectors, granularity); if (unlikely(!max_discard_sectors)) { /* Avoid infinite loop below. Being cautious never hurts. */ return -EOPNOTSUPP; @@ -83,10 +81,9 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, bb.flags = 1 << BIO_UPTODATE; bb.wait = &wait; - blk_start_plug(&plug); while (nr_sects) { unsigned int req_sects; - sector_t end_sect, tmp; + sector_t end_sect; bio = bio_alloc(gfp_mask, 1); if (!bio) { @@ -101,12 +98,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, * misaligned, stop the discard at the previous aligned sector. */ end_sect = sector + req_sects; - tmp = end_sect; - if (req_sects < nr_sects && - sector_div(tmp, granularity) != alignment) { - end_sect = end_sect - alignment; - sector_div(end_sect, granularity); - end_sect = end_sect * granularity + alignment; + if (req_sects < nr_sects && (end_sect & mask) != alignment) { + end_sect = + round_down(end_sect - alignment, granularity) + + alignment; req_sects = end_sect - sector; } @@ -122,7 +117,6 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, atomic_inc(&bb.done); submit_bio(type, bio); } - blk_finish_plug(&plug); /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) diff --git a/trunk/block/blk-settings.c b/trunk/block/blk-settings.c index c50ecf0ea3b1..779bb7646bcd 100644 --- a/trunk/block/blk-settings.c +++ b/trunk/block/blk-settings.c @@ -611,7 +611,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, bottom = b->discard_granularity + alignment; /* Verify that top and bottom intervals line up */ - if ((max(top, bottom) % min(top, bottom)) != 0) + if (max(top, bottom) & (min(top, bottom) - 1)) t->discard_misaligned = 1; } @@ -619,8 +619,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, b->max_discard_sectors); t->discard_granularity = max(t->discard_granularity, b->discard_granularity); - t->discard_alignment = lcm(t->discard_alignment, alignment) % - t->discard_granularity; + t->discard_alignment = lcm(t->discard_alignment, alignment) & + (t->discard_granularity - 1); } return ret; diff --git a/trunk/block/blk-sysfs.c b/trunk/block/blk-sysfs.c index 788147797a79..ce6204608822 100644 --- a/trunk/block/blk-sysfs.c +++ b/trunk/block/blk-sysfs.c @@ -466,7 +466,7 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) if (!entry->show) return -EIO; mutex_lock(&q->sysfs_lock); - if (blk_queue_dying(q)) { + if (blk_queue_dead(q)) { mutex_unlock(&q->sysfs_lock); return -ENOENT; } @@ -488,7 +488,7 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr, q = container_of(kobj, struct request_queue, kobj); mutex_lock(&q->sysfs_lock); - if (blk_queue_dying(q)) { + if (blk_queue_dead(q)) { mutex_unlock(&q->sysfs_lock); return -ENOENT; } diff --git a/trunk/block/blk-throttle.c b/trunk/block/blk-throttle.c index 31146225f3d0..a9664fa0b609 100644 --- a/trunk/block/blk-throttle.c +++ b/trunk/block/blk-throttle.c @@ -302,7 +302,7 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, /* if %NULL and @q is alive, fall back to root_tg */ if (!IS_ERR(blkg)) tg = blkg_to_tg(blkg); - else if (!blk_queue_dying(q)) + else if (!blk_queue_dead(q)) tg = td_root_tg(td); } diff --git a/trunk/block/blk.h b/trunk/block/blk.h index 47fdfdd41520..ca51543b248c 100644 --- a/trunk/block/blk.h +++ b/trunk/block/blk.h @@ -96,7 +96,7 @@ static inline struct request *__elv_next_request(struct request_queue *q) q->flush_queue_delayed = 1; return NULL; } - if (unlikely(blk_queue_dying(q)) || + if (unlikely(blk_queue_dead(q)) || !q->elevator->type->ops.elevator_dispatch_fn(q, 0)) return NULL; } @@ -145,8 +145,6 @@ int blk_try_merge(struct request *rq, struct bio *bio); void blk_queue_congestion_threshold(struct request_queue *q); -void __blk_run_queue_uncond(struct request_queue *q); - int blk_dev_init(void); diff --git a/trunk/block/bsg-lib.c b/trunk/block/bsg-lib.c index 650f427d915b..deee61fbb741 100644 --- a/trunk/block/bsg-lib.c +++ b/trunk/block/bsg-lib.c @@ -151,6 +151,19 @@ static int bsg_create_job(struct device *dev, struct request *req) return -ENOMEM; } +/* + * bsg_goose_queue - restart queue in case it was stopped + * @q: request q to be restarted + */ +void bsg_goose_queue(struct request_queue *q) +{ + if (!q) + return; + + blk_run_queue_async(q); +} +EXPORT_SYMBOL_GPL(bsg_goose_queue); + /** * bsg_request_fn - generic handler for bsg requests * @q: request queue to manage diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index e62e9205b80a..fb52df9744f5 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -1973,8 +1973,7 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, * reposition in fifo if next is older than rq */ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && - time_before(rq_fifo_time(next), rq_fifo_time(rq)) && - cfqq == RQ_CFQQ(next)) { + time_before(rq_fifo_time(next), rq_fifo_time(rq))) { list_move(&rq->queuelist, &next->queuelist); rq_set_fifo_time(rq, rq_fifo_time(next)); } diff --git a/trunk/block/deadline-iosched.c b/trunk/block/deadline-iosched.c index 90037b5eb17f..599b12e5380f 100644 --- a/trunk/block/deadline-iosched.c +++ b/trunk/block/deadline-iosched.c @@ -230,7 +230,7 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) /* * rq is expired! */ - if (time_after_eq(jiffies, rq_fifo_time(rq))) + if (time_after(jiffies, rq_fifo_time(rq))) return 1; return 0; diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 9edba1b8323e..9b1d42b62f20 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -458,7 +458,6 @@ static bool elv_attempt_insert_merge(struct request_queue *q, struct request *rq) { struct request *__rq; - bool ret; if (blk_queue_nomerges(q)) return false; @@ -472,21 +471,14 @@ static bool elv_attempt_insert_merge(struct request_queue *q, if (blk_queue_noxmerges(q)) return false; - ret = false; /* * See if our hash lookup can find a potential backmerge. */ - while (1) { - __rq = elv_rqhash_find(q, blk_rq_pos(rq)); - if (!__rq || !blk_attempt_req_merge(q, __rq, rq)) - break; - - /* The merged request could be merged with others, try again */ - ret = true; - rq = __rq; - } + __rq = elv_rqhash_find(q, blk_rq_pos(rq)); + if (__rq && blk_attempt_req_merge(q, __rq, rq)) + return true; - return ret; + return false; } void elv_merged_request(struct request_queue *q, struct request *rq, int type) diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index 2a6fdf539a69..6cace663a80e 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -1245,7 +1245,7 @@ EXPORT_SYMBOL(blk_lookup_devt); struct gendisk *alloc_disk(int minors) { - return alloc_disk_node(minors, NUMA_NO_NODE); + return alloc_disk_node(minors, -1); } EXPORT_SYMBOL(alloc_disk); diff --git a/trunk/block/partitions/Kconfig b/trunk/block/partitions/Kconfig index 75a54e1adbb5..cb5f0a3f1b03 100644 --- a/trunk/block/partitions/Kconfig +++ b/trunk/block/partitions/Kconfig @@ -234,8 +234,8 @@ config KARMA_PARTITION uses a proprietary partition table. config EFI_PARTITION - bool "EFI GUID Partition support" if PARTITION_ADVANCED - default y + bool "EFI GUID Partition support" + depends on PARTITION_ADVANCED select CRC32 help Say Y here if you would like to use hard disks under Linux which diff --git a/trunk/drivers/amba/tegra-ahb.c b/trunk/drivers/amba/tegra-ahb.c index 0576a7dd32a5..bd5de08ad6fd 100644 --- a/trunk/drivers/amba/tegra-ahb.c +++ b/trunk/drivers/amba/tegra-ahb.c @@ -157,7 +157,6 @@ int tegra_ahb_enable_smmu(struct device_node *dn) EXPORT_SYMBOL(tegra_ahb_enable_smmu); #endif -#ifdef CONFIG_PM_SLEEP static int tegra_ahb_suspend(struct device *dev) { int i; @@ -177,7 +176,6 @@ static int tegra_ahb_resume(struct device *dev) gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); return 0; } -#endif static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, tegra_ahb_suspend, diff --git a/trunk/drivers/bus/Kconfig b/trunk/drivers/bus/Kconfig index 0f51ed687dc8..bbec35d21fe5 100644 --- a/trunk/drivers/bus/Kconfig +++ b/trunk/drivers/bus/Kconfig @@ -6,7 +6,6 @@ menu "Bus devices" config OMAP_OCP2SCP tristate "OMAP OCP2SCP DRIVER" - depends on ARCH_OMAP2PLUS help Driver to enable ocp2scp module which transforms ocp interface protocol to scp protocol. In OMAP4, USB PHY is connected via diff --git a/trunk/drivers/char/agp/intel-agp.h b/trunk/drivers/char/agp/intel-agp.h index 1042c1b90376..6ec0fff79bc2 100644 --- a/trunk/drivers/char/agp/intel-agp.h +++ b/trunk/drivers/char/agp/intel-agp.h @@ -62,6 +62,12 @@ #define I810_PTE_LOCAL 0x00000002 #define I810_PTE_VALID 0x00000001 #define I830_PTE_SYSTEM_CACHED 0x00000006 +/* GT PTE cache control fields */ +#define GEN6_PTE_UNCACHED 0x00000002 +#define HSW_PTE_UNCACHED 0x00000000 +#define GEN6_PTE_LLC 0x00000004 +#define GEN6_PTE_LLC_MLC 0x00000006 +#define GEN6_PTE_GFDT 0x00000008 #define I810_SMRAM_MISCC 0x70 #define I810_GFX_MEM_WIN_SIZE 0x00010000 @@ -91,6 +97,7 @@ #define G4x_GMCH_SIZE_VT_2M (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN) #define GFX_FLSH_CNTL 0x2170 /* 915+ */ +#define GFX_FLSH_CNTL_VLV 0x101008 #define I810_DRAM_CTL 0x3000 #define I810_DRAM_ROW_0 0x00000001 @@ -141,6 +148,29 @@ #define INTEL_I7505_AGPCTRL 0x70 #define INTEL_I7505_MCHCFG 0x50 +#define SNB_GMCH_CTRL 0x50 +#define SNB_GMCH_GMS_STOLEN_MASK 0xF8 +#define SNB_GMCH_GMS_STOLEN_32M (1 << 3) +#define SNB_GMCH_GMS_STOLEN_64M (2 << 3) +#define SNB_GMCH_GMS_STOLEN_96M (3 << 3) +#define SNB_GMCH_GMS_STOLEN_128M (4 << 3) +#define SNB_GMCH_GMS_STOLEN_160M (5 << 3) +#define SNB_GMCH_GMS_STOLEN_192M (6 << 3) +#define SNB_GMCH_GMS_STOLEN_224M (7 << 3) +#define SNB_GMCH_GMS_STOLEN_256M (8 << 3) +#define SNB_GMCH_GMS_STOLEN_288M (9 << 3) +#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) +#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) +#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) +#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) +#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) +#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) +#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) +#define SNB_GTT_SIZE_0M (0 << 8) +#define SNB_GTT_SIZE_1M (1 << 8) +#define SNB_GTT_SIZE_2M (2 << 8) +#define SNB_GTT_SIZE_MASK (3 << 8) + /* pci devices ids */ #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a @@ -189,5 +219,66 @@ #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB 0x0150 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG 0x0152 +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG 0x0162 +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB 0x0154 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG 0x0156 +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG 0x0166 +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */ +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A +#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB 0x0F00 /* VLV1 */ +#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG 0x0F30 +#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG 0x0402 +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG 0x0412 +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG 0x0422 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG 0x0406 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG 0x0416 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG 0x0426 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG 0x040a +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG 0x041a +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG 0x042a +#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG 0x0C02 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG 0x0C12 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG 0x0C22 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG 0x0C06 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG 0x0C16 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG 0x0C26 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG 0x0C0A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG 0x0C1A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG 0x0C2A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG 0x0A02 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG 0x0A12 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG 0x0A22 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG 0x0A06 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG 0x0A16 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG 0x0A26 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG 0x0A0A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG 0x0A1A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG 0x0A2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG 0x0D12 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG 0x0D22 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG 0x0D32 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG 0x0D16 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG 0x0D26 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG 0x0D36 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG 0x0D1A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG 0x0D2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG 0x0D3A #endif diff --git a/trunk/drivers/char/agp/intel-gtt.c b/trunk/drivers/char/agp/intel-gtt.c index dbd901e94ea6..38390f7c6ab6 100644 --- a/trunk/drivers/char/agp/intel-gtt.c +++ b/trunk/drivers/char/agp/intel-gtt.c @@ -367,6 +367,62 @@ static unsigned int intel_gtt_stolen_size(void) stolen_size = 0; break; } + } else if (INTEL_GTT_GEN == 6) { + /* + * SandyBridge has new memory control reg at 0x50.w + */ + u16 snb_gmch_ctl; + pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); + switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { + case SNB_GMCH_GMS_STOLEN_32M: + stolen_size = MB(32); + break; + case SNB_GMCH_GMS_STOLEN_64M: + stolen_size = MB(64); + break; + case SNB_GMCH_GMS_STOLEN_96M: + stolen_size = MB(96); + break; + case SNB_GMCH_GMS_STOLEN_128M: + stolen_size = MB(128); + break; + case SNB_GMCH_GMS_STOLEN_160M: + stolen_size = MB(160); + break; + case SNB_GMCH_GMS_STOLEN_192M: + stolen_size = MB(192); + break; + case SNB_GMCH_GMS_STOLEN_224M: + stolen_size = MB(224); + break; + case SNB_GMCH_GMS_STOLEN_256M: + stolen_size = MB(256); + break; + case SNB_GMCH_GMS_STOLEN_288M: + stolen_size = MB(288); + break; + case SNB_GMCH_GMS_STOLEN_320M: + stolen_size = MB(320); + break; + case SNB_GMCH_GMS_STOLEN_352M: + stolen_size = MB(352); + break; + case SNB_GMCH_GMS_STOLEN_384M: + stolen_size = MB(384); + break; + case SNB_GMCH_GMS_STOLEN_416M: + stolen_size = MB(416); + break; + case SNB_GMCH_GMS_STOLEN_448M: + stolen_size = MB(448); + break; + case SNB_GMCH_GMS_STOLEN_480M: + stolen_size = MB(480); + break; + case SNB_GMCH_GMS_STOLEN_512M: + stolen_size = MB(512); + break; + } } else { switch (gmch_ctrl & I855_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: @@ -500,9 +556,29 @@ static unsigned int i965_gtt_total_entries(void) static unsigned int intel_gtt_total_entries(void) { + int size; + if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) return i965_gtt_total_entries(); - else { + else if (INTEL_GTT_GEN == 6) { + u16 snb_gmch_ctl; + + pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); + switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { + default: + case SNB_GTT_SIZE_0M: + printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); + size = MB(0); + break; + case SNB_GTT_SIZE_1M: + size = MB(1); + break; + case SNB_GTT_SIZE_2M: + size = MB(2); + break; + } + return size/4; + } else { /* On previous hardware, the GTT size was just what was * required to map the aperture. */ @@ -702,6 +778,9 @@ bool intel_enable_gtt(void) { u8 __iomem *reg; + if (INTEL_GTT_GEN >= 6) + return true; + if (INTEL_GTT_GEN == 2) { u16 gmch_ctrl; @@ -1070,6 +1149,85 @@ static void i965_write_entry(dma_addr_t addr, writel(addr | pte_flags, intel_private.gtt + entry); } +static bool gen6_check_flags(unsigned int flags) +{ + return true; +} + +static void haswell_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; + u32 pte_flags; + + if (type_mask == AGP_USER_MEMORY) + pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { + pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } else { /* set 'normal'/'cached' to LLC by default */ + pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } + + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; + writel(addr | pte_flags, intel_private.gtt + entry); +} + +static void gen6_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; + u32 pte_flags; + + if (type_mask == AGP_USER_MEMORY) + pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { + pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } else { /* set 'normal'/'cached' to LLC by default */ + pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } + + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; + writel(addr | pte_flags, intel_private.gtt + entry); +} + +static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; + u32 pte_flags; + + if (type_mask == AGP_USER_MEMORY) + pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; + else { + pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; + if (gfdt) + pte_flags |= GEN6_PTE_GFDT; + } + + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; + writel(addr | pte_flags, intel_private.gtt + entry); + + writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV); +} + +static void gen6_cleanup(void) +{ +} + /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. */ @@ -1091,29 +1249,41 @@ static inline int needs_idle_maps(void) static int i9xx_setup(void) { - u32 reg_addr, gtt_addr; + u32 reg_addr; int size = KB(512); pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); reg_addr &= 0xfff80000; + if (INTEL_GTT_GEN >= 7) + size = MB(2); + intel_private.registers = ioremap(reg_addr, size); if (!intel_private.registers) return -ENOMEM; - switch (INTEL_GTT_GEN) { - case 3: + if (INTEL_GTT_GEN == 3) { + u32 gtt_addr; + pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, >t_addr); intel_private.gtt_bus_addr = gtt_addr; - break; - case 5: - intel_private.gtt_bus_addr = reg_addr + MB(2); - break; - default: - intel_private.gtt_bus_addr = reg_addr + KB(512); - break; + } else { + u32 gtt_offset; + + switch (INTEL_GTT_GEN) { + case 5: + case 6: + case 7: + gtt_offset = MB(2); + break; + case 4: + default: + gtt_offset = KB(512); + break; + } + intel_private.gtt_bus_addr = reg_addr + gtt_offset; } if (needs_idle_maps()) @@ -1225,6 +1395,32 @@ static const struct intel_gtt_driver ironlake_gtt_driver = { .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, }; +static const struct intel_gtt_driver sandybridge_gtt_driver = { + .gen = 6, + .setup = i9xx_setup, + .cleanup = gen6_cleanup, + .write_entry = gen6_write_entry, + .dma_mask_size = 40, + .check_flags = gen6_check_flags, + .chipset_flush = i9xx_chipset_flush, +}; +static const struct intel_gtt_driver haswell_gtt_driver = { + .gen = 6, + .setup = i9xx_setup, + .cleanup = gen6_cleanup, + .write_entry = haswell_write_entry, + .dma_mask_size = 40, + .check_flags = gen6_check_flags, + .chipset_flush = i9xx_chipset_flush, +}; +static const struct intel_gtt_driver valleyview_gtt_driver = { + .gen = 7, + .setup = i9xx_setup, + .cleanup = gen6_cleanup, + .write_entry = valleyview_write_entry, + .dma_mask_size = 40, + .check_flags = gen6_check_flags, +}; /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of * driver and gmch_driver must be non-null, and find_gmch will determine @@ -1305,6 +1501,106 @@ static const struct intel_gtt_driver_description { "HD Graphics", &ironlake_gtt_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, "HD Graphics", &ironlake_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, + "Sandybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG, + "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, + "ValleyView", &valleyview_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, + "Haswell", &haswell_gtt_driver }, + { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, + "Haswell", &haswell_gtt_driver }, { 0, NULL, NULL } }; @@ -1390,7 +1686,7 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, } EXPORT_SYMBOL(intel_gmch_probe); -struct intel_gtt *intel_gtt_get(void) +const struct intel_gtt *intel_gtt_get(void) { return &intel_private.base; } diff --git a/trunk/drivers/char/tpm/tpm_ibmvtpm.c b/trunk/drivers/char/tpm/tpm_ibmvtpm.c index 9978609d93b2..7da840d487d2 100644 --- a/trunk/drivers/char/tpm/tpm_ibmvtpm.c +++ b/trunk/drivers/char/tpm/tpm_ibmvtpm.c @@ -38,6 +38,8 @@ static struct vio_device_id tpm_ibmvtpm_device_table[] = { }; MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); +DECLARE_WAIT_QUEUE_HEAD(wq); + /** * ibmvtpm_send_crq - Send a CRQ request * @vdev: vio device struct @@ -81,7 +83,6 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct ibmvtpm_dev *ibmvtpm; u16 len; - int sig; ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; @@ -90,23 +91,22 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) return 0; } - sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0); - if (sig) - return -EINTR; - - len = ibmvtpm->res_len; + wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0); - if (count < len) { + if (count < ibmvtpm->crq_res.len) { dev_err(ibmvtpm->dev, "Invalid size in recv: count=%ld, crq_size=%d\n", - count, len); + count, ibmvtpm->crq_res.len); return -EIO; } spin_lock(&ibmvtpm->rtce_lock); - memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len); - memset(ibmvtpm->rtce_buf, 0, len); - ibmvtpm->res_len = 0; + memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len); + memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len); + ibmvtpm->crq_res.valid = 0; + ibmvtpm->crq_res.msg = 0; + len = ibmvtpm->crq_res.len; + ibmvtpm->crq_res.len = 0; spin_unlock(&ibmvtpm->rtce_lock); return len; } @@ -273,6 +273,7 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) int rc = 0; free_irq(vdev->irq, ibmvtpm); + tasklet_kill(&ibmvtpm->tasklet); do { if (rc) @@ -371,6 +372,7 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm) static int tpm_ibmvtpm_resume(struct device *dev) { struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); + unsigned long flags; int rc = 0; do { @@ -385,11 +387,10 @@ static int tpm_ibmvtpm_resume(struct device *dev) return rc; } - rc = vio_enable_interrupts(ibmvtpm->vdev); - if (rc) { - dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc); - return rc; - } + spin_lock_irqsave(&ibmvtpm->lock, flags); + vio_disable_interrupts(ibmvtpm->vdev); + tasklet_schedule(&ibmvtpm->tasklet); + spin_unlock_irqrestore(&ibmvtpm->lock, flags); rc = ibmvtpm_crq_send_init(ibmvtpm); if (rc) @@ -466,7 +467,7 @@ static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm) if (crq->valid & VTPM_MSG_RES) { if (++crq_q->index == crq_q->num_entry) crq_q->index = 0; - smp_rmb(); + rmb(); } else crq = NULL; return crq; @@ -534,9 +535,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, ibmvtpm->vtpm_version = crq->data; return; case VTPM_TPM_COMMAND_RES: - /* len of the data in rtce buffer */ - ibmvtpm->res_len = crq->len; - wake_up_interruptible(&ibmvtpm->wq); + ibmvtpm->crq_res.valid = crq->valid; + ibmvtpm->crq_res.msg = crq->msg; + ibmvtpm->crq_res.len = crq->len; + ibmvtpm->crq_res.data = crq->data; + wake_up_interruptible(&wq); return; default: return; @@ -556,19 +559,38 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance) { struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance; + unsigned long flags; + + spin_lock_irqsave(&ibmvtpm->lock, flags); + vio_disable_interrupts(ibmvtpm->vdev); + tasklet_schedule(&ibmvtpm->tasklet); + spin_unlock_irqrestore(&ibmvtpm->lock, flags); + + return IRQ_HANDLED; +} + +/** + * ibmvtpm_tasklet - Interrupt handler tasklet + * @data: ibm vtpm device struct + * + * Returns: + * Nothing + **/ +static void ibmvtpm_tasklet(void *data) +{ + struct ibmvtpm_dev *ibmvtpm = data; struct ibmvtpm_crq *crq; + unsigned long flags; - /* while loop is needed for initial setup (get version and - * get rtce_size). There should be only one tpm request at any - * given time. - */ + spin_lock_irqsave(&ibmvtpm->lock, flags); while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) { ibmvtpm_crq_process(crq, ibmvtpm); crq->valid = 0; - smp_wmb(); + wmb(); } - return IRQ_HANDLED; + vio_enable_interrupts(ibmvtpm->vdev); + spin_unlock_irqrestore(&ibmvtpm->lock, flags); } /** @@ -628,6 +650,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto reg_crq_cleanup; } + tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet, + (unsigned long)ibmvtpm); + rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0, tpm_ibmvtpm_driver_name, ibmvtpm); if (rc) { @@ -641,14 +666,13 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto init_irq_cleanup; } - init_waitqueue_head(&ibmvtpm->wq); - crq_q->index = 0; ibmvtpm->dev = dev; ibmvtpm->vdev = vio_dev; chip->vendor.data = (void *)ibmvtpm; + spin_lock_init(&ibmvtpm->lock); spin_lock_init(&ibmvtpm->rtce_lock); rc = ibmvtpm_crq_send_init(ibmvtpm); @@ -665,6 +689,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, return rc; init_irq_cleanup: + tasklet_kill(&ibmvtpm->tasklet); do { rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); } while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1)); diff --git a/trunk/drivers/char/tpm/tpm_ibmvtpm.h b/trunk/drivers/char/tpm/tpm_ibmvtpm.h index bd82a791f995..4296eb4b4d82 100644 --- a/trunk/drivers/char/tpm/tpm_ibmvtpm.h +++ b/trunk/drivers/char/tpm/tpm_ibmvtpm.h @@ -38,12 +38,13 @@ struct ibmvtpm_dev { struct vio_dev *vdev; struct ibmvtpm_crq_queue crq_queue; dma_addr_t crq_dma_handle; + spinlock_t lock; + struct tasklet_struct tasklet; u32 rtce_size; void __iomem *rtce_buf; dma_addr_t rtce_dma_handle; spinlock_t rtce_lock; - wait_queue_head_t wq; - u16 res_len; + struct ibmvtpm_crq crq_res; u32 vtpm_version; }; diff --git a/trunk/drivers/extcon/extcon-arizona.c b/trunk/drivers/extcon/extcon-arizona.c index 414aed50b1bc..f10f05d4ee9c 100644 --- a/trunk/drivers/extcon/extcon-arizona.c +++ b/trunk/drivers/extcon/extcon-arizona.c @@ -166,7 +166,6 @@ static irqreturn_t arizona_micdet(int irq, void *data) ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); if (ret != 0) { dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret); - mutex_unlock(&info->lock); return IRQ_NONE; } diff --git a/trunk/drivers/extcon/extcon-class.c b/trunk/drivers/extcon/extcon-class.c index 60adc04b0561..d398821097f3 100644 --- a/trunk/drivers/extcon/extcon-class.c +++ b/trunk/drivers/extcon/extcon-class.c @@ -472,7 +472,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); if (obj->cable_index < 0) - return obj->cable_index; + return -ENODEV; obj->user_nb = nb; diff --git a/trunk/drivers/extcon/extcon-max77693.c b/trunk/drivers/extcon/extcon-max77693.c index 8c17b65eb74d..b656dfa401a6 100644 --- a/trunk/drivers/extcon/extcon-max77693.c +++ b/trunk/drivers/extcon/extcon-max77693.c @@ -657,17 +657,17 @@ static int max77693_muic_probe(struct platform_device *pdev) int ret, i; u8 id; - info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), - GFP_KERNEL); + info = kzalloc(sizeof(struct max77693_muic_info), GFP_KERNEL); if (!info) { dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_kfree; } info->dev = &pdev->dev; info->max77693 = max77693; - if (info->max77693->regmap_muic) { + if (info->max77693->regmap_muic) dev_dbg(&pdev->dev, "allocate register map\n"); - } else { + else { info->max77693->regmap_muic = devm_regmap_init_i2c( info->max77693->muic, &max77693_muic_regmap_config); @@ -675,7 +675,7 @@ static int max77693_muic_probe(struct platform_device *pdev) ret = PTR_ERR(info->max77693->regmap_muic); dev_err(max77693->dev, "failed to allocate register map: %d\n", ret); - return ret; + goto err_regmap; } } platform_set_drvdata(pdev, info); @@ -686,13 +686,11 @@ static int max77693_muic_probe(struct platform_device *pdev) /* Support irq domain for MAX77693 MUIC device */ for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max77693_muic_irq *muic_irq = &muic_irqs[i]; - unsigned int virq = 0; + int virq = 0; virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq); - if (!virq) { - ret = -EINVAL; + if (!virq) goto err_irq; - } muic_irq->virq = virq; ret = request_threaded_irq(virq, NULL, @@ -704,13 +702,14 @@ static int max77693_muic_probe(struct platform_device *pdev) " error :%d)\n", muic_irq->irq, ret); + for (i = i - 1; i >= 0; i--) + free_irq(muic_irq->virq, info); goto err_irq; } } /* Initialize extcon device */ - info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev), - GFP_KERNEL); + info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL); if (!info->edev) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); ret = -ENOMEM; @@ -721,7 +720,7 @@ static int max77693_muic_probe(struct platform_device *pdev) ret = extcon_dev_register(info->edev, NULL); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); - goto err_irq; + goto err_extcon; } /* Initialize MUIC register by using platform data */ @@ -754,7 +753,7 @@ static int max77693_muic_probe(struct platform_device *pdev) MAX77693_MUIC_REG_ID, &id); if (ret < 0) { dev_err(&pdev->dev, "failed to read revision number\n"); - goto err_irq; + goto err_extcon; } dev_info(info->dev, "device ID : 0x%x\n", id); @@ -766,9 +765,12 @@ static int max77693_muic_probe(struct platform_device *pdev) return ret; +err_extcon: + kfree(info->edev); err_irq: - while (--i >= 0) - free_irq(muic_irqs[i].virq, info); +err_regmap: + kfree(info); +err_kfree: return ret; } @@ -781,6 +783,8 @@ static int max77693_muic_remove(struct platform_device *pdev) free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); + kfree(info->edev); + kfree(info); return 0; } diff --git a/trunk/drivers/extcon/extcon-max8997.c b/trunk/drivers/extcon/extcon-max8997.c index 93009fe6ef05..bad76f51161b 100644 --- a/trunk/drivers/extcon/extcon-max8997.c +++ b/trunk/drivers/extcon/extcon-max8997.c @@ -1,7 +1,7 @@ /* * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC * - * Copyright (C) 2012 Samsung Electronics + * Copyright (C) 2012 Samsung Electrnoics * Donggeun Kim * * This program is free software; you can redistribute it and/or modify @@ -433,11 +433,11 @@ static int max8997_muic_probe(struct platform_device *pdev) struct max8997_muic_info *info; int ret, i; - info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info), - GFP_KERNEL); + info = kzalloc(sizeof(struct max8997_muic_info), GFP_KERNEL); if (!info) { dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_kfree; } info->dev = &pdev->dev; @@ -450,16 +450,14 @@ static int max8997_muic_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max8997_muic_irq *muic_irq = &muic_irqs[i]; - unsigned int virq = 0; + int virq = 0; virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq); - if (!virq) { - ret = -EINVAL; + if (!virq) goto err_irq; - } muic_irq->virq = virq; - ret = request_threaded_irq(virq, NULL, max8997_muic_irq_handler, + ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler, 0, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, @@ -471,8 +469,7 @@ static int max8997_muic_probe(struct platform_device *pdev) } /* External connector */ - info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev), - GFP_KERNEL); + info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL); if (!info->edev) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); ret = -ENOMEM; @@ -483,7 +480,7 @@ static int max8997_muic_probe(struct platform_device *pdev) ret = extcon_dev_register(info->edev, NULL); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); - goto err_irq; + goto err_extcon; } /* Initialize registers according to platform data */ @@ -501,9 +498,13 @@ static int max8997_muic_probe(struct platform_device *pdev) return ret; +err_extcon: + kfree(info->edev); err_irq: while (--i >= 0) free_irq(muic_irqs[i].virq, info); + kfree(info); +err_kfree: return ret; } @@ -518,6 +519,9 @@ static int max8997_muic_remove(struct platform_device *pdev) extcon_dev_unregister(info->edev); + kfree(info->edev); + kfree(info); + return 0; } diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index 8ae1f5b19669..bf892bd68c17 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -683,17 +683,4 @@ config GPIO_MSIC Enable support for GPIO on intel MSIC controllers found in intel MID devices -comment "USB GPIO expanders:" - -config GPIO_VIPERBOARD - tristate "Viperboard GPIO a & b support" - depends on MFD_VIPERBOARD && USB - help - Say yes here to access the GPIO signals of Nano River - Technologies Viperboard. There are two GPIO chips on the - board: gpioa and gpiob. - See viperboard API specification and Nano - River Tech's viperboard.h for detailed meaning - of the module parameters. - endif diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile index c5aebd008dde..76b344683251 100644 --- a/trunk/drivers/gpio/Makefile +++ b/trunk/drivers/gpio/Makefile @@ -76,7 +76,6 @@ obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o -obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VT8500) += gpio-vt8500.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o diff --git a/trunk/drivers/gpio/gpio-da9052.c b/trunk/drivers/gpio/gpio-da9052.c index 29b11e9b6a78..a05aacd2777a 100644 --- a/trunk/drivers/gpio/gpio-da9052.c +++ b/trunk/drivers/gpio/gpio-da9052.c @@ -185,11 +185,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset) struct da9052_gpio *gpio = to_da9052_gpio(gc); struct da9052 *da9052 = gpio->da9052; - int irq; - - irq = regmap_irq_get_virq(da9052->irq_data, DA9052_IRQ_GPI0 + offset); - - return irq; + return da9052->irq_base + DA9052_IRQ_GPI0 + offset; } static struct gpio_chip reference_gp = { diff --git a/trunk/drivers/gpio/gpio-tps6586x.c b/trunk/drivers/gpio/gpio-tps6586x.c index 29e8e750bd49..c1b82da56504 100644 --- a/trunk/drivers/gpio/gpio-tps6586x.c +++ b/trunk/drivers/gpio/gpio-tps6586x.c @@ -80,14 +80,6 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, val, mask); } -static int tps6586x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); - - return tps6586x_irq_get_virq(tps6586x_gpio->parent, - TPS6586X_INT_PLDO_0 + offset); -} - static int tps6586x_gpio_probe(struct platform_device *pdev) { struct tps6586x_platform_data *pdata; @@ -114,7 +106,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; tps6586x_gpio->gpio_chip.set = tps6586x_gpio_set; tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get; - tps6586x_gpio->gpio_chip.to_irq = tps6586x_gpio_to_irq; #ifdef CONFIG_OF_GPIO tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node; diff --git a/trunk/drivers/gpio/gpio-twl4030.c b/trunk/drivers/gpio/gpio-twl4030.c index 9572aa137e6f..00329f2fc05b 100644 --- a/trunk/drivers/gpio/gpio-twl4030.c +++ b/trunk/drivers/gpio/gpio-twl4030.c @@ -355,13 +355,13 @@ static struct gpio_chip twl_gpiochip = { static int gpio_twl4030_pulls(u32 ups, u32 downs) { - u8 message[5]; + u8 message[6]; unsigned i, gpio_bit; /* For most pins, a pulldown was enabled by default. * We should have data that's specific to this board. */ - for (gpio_bit = 1, i = 0; i < 5; i++) { + for (gpio_bit = 1, i = 1; i < 6; i++) { u8 bit_mask; unsigned j; @@ -380,16 +380,16 @@ static int gpio_twl4030_pulls(u32 ups, u32 downs) static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) { - u8 message[3]; + u8 message[4]; /* 30 msec of debouncing is always used for MMC card detect, * and is optional for everything else. */ - message[0] = (debounce & 0xff) | (mmc_cd & 0x03); + message[1] = (debounce & 0xff) | (mmc_cd & 0x03); debounce >>= 8; - message[1] = (debounce & 0xff); + message[2] = (debounce & 0xff); debounce >>= 8; - message[2] = (debounce & 0x03); + message[3] = (debounce & 0x03); return twl_i2c_write(TWL4030_MODULE_GPIO, message, REG_GPIO_DEBEN1, 3); diff --git a/trunk/drivers/gpio/gpio-viperboard.c b/trunk/drivers/gpio/gpio-viperboard.c deleted file mode 100644 index 13772996cf24..000000000000 --- a/trunk/drivers/gpio/gpio-viperboard.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Nano River Technologies viperboard GPIO lib driver - * - * (C) 2012 by Lemonage GmbH - * Author: Lars Poeschel - * 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; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define VPRBRD_GPIOA_CLK_1MHZ 0 -#define VPRBRD_GPIOA_CLK_100KHZ 1 -#define VPRBRD_GPIOA_CLK_10KHZ 2 -#define VPRBRD_GPIOA_CLK_1KHZ 3 -#define VPRBRD_GPIOA_CLK_100HZ 4 -#define VPRBRD_GPIOA_CLK_10HZ 5 - -#define VPRBRD_GPIOA_FREQ_DEFAULT 1000 - -#define VPRBRD_GPIOA_CMD_CONT 0x00 -#define VPRBRD_GPIOA_CMD_PULSE 0x01 -#define VPRBRD_GPIOA_CMD_PWM 0x02 -#define VPRBRD_GPIOA_CMD_SETOUT 0x03 -#define VPRBRD_GPIOA_CMD_SETIN 0x04 -#define VPRBRD_GPIOA_CMD_SETINT 0x05 -#define VPRBRD_GPIOA_CMD_GETIN 0x06 - -#define VPRBRD_GPIOB_CMD_SETDIR 0x00 -#define VPRBRD_GPIOB_CMD_SETVAL 0x01 - -struct vprbrd_gpioa_msg { - u8 cmd; - u8 clk; - u8 offset; - u8 t1; - u8 t2; - u8 invert; - u8 pwmlevel; - u8 outval; - u8 risefall; - u8 answer; - u8 __fill; -} __packed; - -struct vprbrd_gpiob_msg { - u8 cmd; - u16 val; - u16 mask; -} __packed; - -struct vprbrd_gpio { - struct gpio_chip gpioa; /* gpio a related things */ - u32 gpioa_out; - u32 gpioa_val; - struct gpio_chip gpiob; /* gpio b related things */ - u32 gpiob_out; - u32 gpiob_val; - struct vprbrd *vb; -}; - -/* gpioa sampling clock module parameter */ -static unsigned char gpioa_clk; -static unsigned int gpioa_freq = VPRBRD_GPIOA_FREQ_DEFAULT; -module_param(gpioa_freq, uint, 0); -MODULE_PARM_DESC(gpioa_freq, - "gpio-a sampling freq in Hz (default is 1000Hz) valid values: 10, 100, 1000, 10000, 100000, 1000000"); - -/* ----- begin of gipo a chip -------------------------------------------- */ - -static int vprbrd_gpioa_get(struct gpio_chip *chip, - unsigned offset) -{ - int ret, answer, error = 0; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; - - /* if io is set to output, just return the saved value */ - if (gpio->gpioa_out & (1 << offset)) - return gpio->gpioa_val & (1 << offset); - - mutex_lock(&vb->lock); - - gamsg->cmd = VPRBRD_GPIOA_CMD_GETIN; - gamsg->clk = 0x00; - gamsg->offset = offset; - gamsg->t1 = 0x00; - gamsg->t2 = 0x00; - gamsg->invert = 0x00; - gamsg->pwmlevel = 0x00; - gamsg->outval = 0x00; - gamsg->risefall = 0x00; - gamsg->answer = 0x00; - gamsg->__fill = 0x00; - - ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000, - 0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg), - VPRBRD_USB_TIMEOUT_MS); - if (ret != sizeof(struct vprbrd_gpioa_msg)) - error = -EREMOTEIO; - - ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_IN, 0x0000, - 0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg), - VPRBRD_USB_TIMEOUT_MS); - answer = gamsg->answer & 0x01; - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpioa_msg)) - error = -EREMOTEIO; - - if (error) - return error; - - return answer; -} - -static void vprbrd_gpioa_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; - - if (gpio->gpioa_out & (1 << offset)) { - if (value) - gpio->gpioa_val |= (1 << offset); - else - gpio->gpioa_val &= ~(1 << offset); - - mutex_lock(&vb->lock); - - gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT; - gamsg->clk = 0x00; - gamsg->offset = offset; - gamsg->t1 = 0x00; - gamsg->t2 = 0x00; - gamsg->invert = 0x00; - gamsg->pwmlevel = 0x00; - gamsg->outval = value; - gamsg->risefall = 0x00; - gamsg->answer = 0x00; - gamsg->__fill = 0x00; - - ret = usb_control_msg(vb->usb_dev, - usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, - 0x0000, 0x0000, gamsg, - sizeof(struct vprbrd_gpioa_msg), VPRBRD_USB_TIMEOUT_MS); - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpioa_msg)) - dev_err(chip->dev, "usb error setting pin value\n"); - } -} - -static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; - - gpio->gpioa_out &= ~(1 << offset); - - mutex_lock(&vb->lock); - - gamsg->cmd = VPRBRD_GPIOA_CMD_SETIN; - gamsg->clk = gpioa_clk; - gamsg->offset = offset; - gamsg->t1 = 0x00; - gamsg->t2 = 0x00; - gamsg->invert = 0x00; - gamsg->pwmlevel = 0x00; - gamsg->outval = 0x00; - gamsg->risefall = 0x00; - gamsg->answer = 0x00; - gamsg->__fill = 0x00; - - ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000, - 0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg), - VPRBRD_USB_TIMEOUT_MS); - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpioa_msg)) - return -EREMOTEIO; - - return 0; -} - -static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; - - gpio->gpioa_out |= (1 << offset); - if (value) - gpio->gpioa_val |= (1 << offset); - else - gpio->gpioa_val &= ~(1 << offset); - - mutex_lock(&vb->lock); - - gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT; - gamsg->clk = 0x00; - gamsg->offset = offset; - gamsg->t1 = 0x00; - gamsg->t2 = 0x00; - gamsg->invert = 0x00; - gamsg->pwmlevel = 0x00; - gamsg->outval = value; - gamsg->risefall = 0x00; - gamsg->answer = 0x00; - gamsg->__fill = 0x00; - - ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000, - 0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg), - VPRBRD_USB_TIMEOUT_MS); - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpioa_msg)) - return -EREMOTEIO; - - return 0; -} - -/* ----- end of gpio a chip ---------------------------------------------- */ - -/* ----- begin of gipo b chip -------------------------------------------- */ - -static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, - unsigned dir) -{ - struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; - int ret; - - gbmsg->cmd = VPRBRD_GPIOB_CMD_SETDIR; - gbmsg->val = cpu_to_be16(dir << offset); - gbmsg->mask = cpu_to_be16(0x0001 << offset); - - ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, 0x0000, - 0x0000, gbmsg, sizeof(struct vprbrd_gpiob_msg), - VPRBRD_USB_TIMEOUT_MS); - - if (ret != sizeof(struct vprbrd_gpiob_msg)) - return -EREMOTEIO; - - return 0; -} - -static int vprbrd_gpiob_get(struct gpio_chip *chip, - unsigned offset) -{ - int ret; - u16 val; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; - - /* if io is set to output, just return the saved value */ - if (gpio->gpiob_out & (1 << offset)) - return gpio->gpiob_val & (1 << offset); - - mutex_lock(&vb->lock); - - ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_IN, 0x0000, - 0x0000, gbmsg, sizeof(struct vprbrd_gpiob_msg), - VPRBRD_USB_TIMEOUT_MS); - val = gbmsg->val; - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpiob_msg)) - return ret; - - /* cache the read values */ - gpio->gpiob_val = be16_to_cpu(val); - - return (gpio->gpiob_val >> offset) & 0x1; -} - -static void vprbrd_gpiob_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); - struct vprbrd *vb = gpio->vb; - struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; - - if (gpio->gpiob_out & (1 << offset)) { - if (value) - gpio->gpiob_val |= (1 << offset); - else - gpio->gpiob_val &= ~(1 << offset); - - mutex_lock(&vb->lock); - - gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL; - gbmsg->val = cpu_to_be16(value << offset); - gbmsg->mask = cpu_to_be16(0x0001 << offset); - - ret = usb_control_msg(vb->usb_dev, - usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, - 0x0000, 0x0000, gbmsg, - sizeof(struct vprbrd_gpiob_msg), VPRBRD_USB_TIMEOUT_MS); - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpiob_msg)) - dev_err(chip->dev, "usb error setting pin value\n"); - } -} - -static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); - struct vprbrd *vb = gpio->vb; - - gpio->gpiob_out &= ~(1 << offset); - - mutex_lock(&vb->lock); - - ret = vprbrd_gpiob_setdir(vb, offset, 0); - - mutex_unlock(&vb->lock); - - if (ret) - dev_err(chip->dev, "usb error setting pin to input\n"); - - return ret; -} - -static int vprbrd_gpiob_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); - struct vprbrd *vb = gpio->vb; - - gpio->gpiob_out |= (1 << offset); - if (value) - gpio->gpiob_val |= (1 << offset); - else - gpio->gpiob_val &= ~(1 << offset); - - mutex_lock(&vb->lock); - - ret = vprbrd_gpiob_setdir(vb, offset, 1); - if (ret) - dev_err(chip->dev, "usb error setting pin to output\n"); - - mutex_unlock(&vb->lock); - - vprbrd_gpiob_set(chip, offset, value); - - return ret; -} - -/* ----- end of gpio b chip ---------------------------------------------- */ - -static int __devinit vprbrd_gpio_probe(struct platform_device *pdev) -{ - struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent); - struct vprbrd_gpio *vb_gpio; - int ret; - - vb_gpio = devm_kzalloc(&pdev->dev, sizeof(*vb_gpio), GFP_KERNEL); - if (vb_gpio == NULL) - return -ENOMEM; - - vb_gpio->vb = vb; - /* registering gpio a */ - vb_gpio->gpioa.label = "viperboard gpio a"; - vb_gpio->gpioa.dev = &pdev->dev; - vb_gpio->gpioa.owner = THIS_MODULE; - vb_gpio->gpioa.base = -1; - vb_gpio->gpioa.ngpio = 16; - vb_gpio->gpioa.can_sleep = 1; - vb_gpio->gpioa.set = vprbrd_gpioa_set; - vb_gpio->gpioa.get = vprbrd_gpioa_get; - vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; - vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output; - ret = gpiochip_add(&vb_gpio->gpioa); - if (ret < 0) { - dev_err(vb_gpio->gpioa.dev, "could not add gpio a"); - goto err_gpioa; - } - - /* registering gpio b */ - vb_gpio->gpiob.label = "viperboard gpio b"; - vb_gpio->gpiob.dev = &pdev->dev; - vb_gpio->gpiob.owner = THIS_MODULE; - vb_gpio->gpiob.base = -1; - vb_gpio->gpiob.ngpio = 16; - vb_gpio->gpiob.can_sleep = 1; - vb_gpio->gpiob.set = vprbrd_gpiob_set; - vb_gpio->gpiob.get = vprbrd_gpiob_get; - vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; - vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output; - ret = gpiochip_add(&vb_gpio->gpiob); - if (ret < 0) { - dev_err(vb_gpio->gpiob.dev, "could not add gpio b"); - goto err_gpiob; - } - - platform_set_drvdata(pdev, vb_gpio); - - return ret; - -err_gpiob: - ret = gpiochip_remove(&vb_gpio->gpioa); - -err_gpioa: - return ret; -} - -static int __devexit vprbrd_gpio_remove(struct platform_device *pdev) -{ - struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&vb_gpio->gpiob); - if (ret == 0) - ret = gpiochip_remove(&vb_gpio->gpioa); - - return ret; -} - -static struct platform_driver vprbrd_gpio_driver = { - .driver.name = "viperboard-gpio", - .driver.owner = THIS_MODULE, - .probe = vprbrd_gpio_probe, - .remove = __devexit_p(vprbrd_gpio_remove), -}; - -static int __init vprbrd_gpio_init(void) -{ - switch (gpioa_freq) { - case 1000000: - gpioa_clk = VPRBRD_GPIOA_CLK_1MHZ; - break; - case 100000: - gpioa_clk = VPRBRD_GPIOA_CLK_100KHZ; - break; - case 10000: - gpioa_clk = VPRBRD_GPIOA_CLK_10KHZ; - break; - case 1000: - gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ; - break; - case 100: - gpioa_clk = VPRBRD_GPIOA_CLK_100HZ; - break; - case 10: - gpioa_clk = VPRBRD_GPIOA_CLK_10HZ; - break; - default: - pr_warn("invalid gpioa_freq (%d)\n", gpioa_freq); - gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ; - } - - return platform_driver_register(&vprbrd_gpio_driver); -} -subsys_initcall(vprbrd_gpio_init); - -static void __exit vprbrd_gpio_exit(void) -{ - platform_driver_unregister(&vprbrd_gpio_driver); -} -module_exit(vprbrd_gpio_exit); - -MODULE_AUTHOR("Lars Poeschel "); -MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:viperboard-gpio"); diff --git a/trunk/drivers/gpu/drm/Kconfig b/trunk/drivers/gpu/drm/Kconfig index 983201b450f1..18321b68b880 100644 --- a/trunk/drivers/gpu/drm/Kconfig +++ b/trunk/drivers/gpu/drm/Kconfig @@ -210,5 +210,3 @@ source "drivers/gpu/drm/mgag200/Kconfig" source "drivers/gpu/drm/cirrus/Kconfig" source "drivers/gpu/drm/shmobile/Kconfig" - -source "drivers/gpu/drm/tegra/Kconfig" diff --git a/trunk/drivers/gpu/drm/Makefile b/trunk/drivers/gpu/drm/Makefile index 6f58c81cfcbc..2ff5cefe9ead 100644 --- a/trunk/drivers/gpu/drm/Makefile +++ b/trunk/drivers/gpu/drm/Makefile @@ -8,7 +8,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_context.o drm_dma.o \ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ - drm_agpsupport.o drm_scatter.o drm_pci.o \ + drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ @@ -16,11 +16,10 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o -drm-$(CONFIG_PCI) += ati_pcigart.o drm-usb-y := drm_usb.o -drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_helper.o +drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o @@ -49,5 +48,4 @@ obj-$(CONFIG_DRM_GMA500) += gma500/ obj-$(CONFIG_DRM_UDL) += udl/ obj-$(CONFIG_DRM_AST) += ast/ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ -obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-y += i2c/ diff --git a/trunk/drivers/gpu/drm/ast/ast_ttm.c b/trunk/drivers/gpu/drm/ast/ast_ttm.c index 3602731a6112..1a026ac2dfb4 100644 --- a/trunk/drivers/gpu/drm/ast/ast_ttm.c +++ b/trunk/drivers/gpu/drm/ast/ast_ttm.c @@ -186,11 +186,11 @@ static void ast_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg * static int ast_bo_move(struct ttm_buffer_object *bo, bool evict, bool interruptible, - bool no_wait_gpu, + bool no_wait_reserve, bool no_wait_gpu, struct ttm_mem_reg *new_mem) { int r; - r = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); + r = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); return r; } @@ -356,7 +356,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size, ttm_bo_type_device, &astbo->placement, - align >> PAGE_SHIFT, false, NULL, acc_size, + align >> PAGE_SHIFT, 0, false, NULL, acc_size, NULL, ast_bo_ttm_destroy); if (ret) return ret; @@ -383,7 +383,7 @@ int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr) ast_ttm_placement(bo, pl_flag); for (i = 0; i < bo->placement.num_placement; i++) bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) return ret; @@ -406,7 +406,7 @@ int ast_bo_unpin(struct ast_bo *bo) for (i = 0; i < bo->placement.num_placement ; i++) bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) return ret; @@ -431,7 +431,7 @@ int ast_bo_push_sysram(struct ast_bo *bo) for (i = 0; i < bo->placement.num_placement ; i++) bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) { DRM_ERROR("pushing to VRAM failed\n"); return ret; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c index dcd1a8c029eb..101e423c8991 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -35,15 +35,12 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { }; -static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev) +static void cirrus_kick_out_firmware_fb(struct pci_dev *pdev) { struct apertures_struct *ap; bool primary = false; ap = alloc_apertures(1); - if (!ap) - return -ENOMEM; - ap->ranges[0].base = pci_resource_start(pdev, 0); ap->ranges[0].size = pci_resource_len(pdev, 0); @@ -52,18 +49,12 @@ static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev) #endif remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); kfree(ap); - - return 0; } static int __devinit cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int ret; - - ret = cirrus_kick_out_firmware_fb(pdev); - if (ret) - return ret; + cirrus_kick_out_firmware_fb(pdev); return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c index 1413a26e4905..bc83f835c830 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -186,11 +186,11 @@ static void cirrus_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_re static int cirrus_bo_move(struct ttm_buffer_object *bo, bool evict, bool interruptible, - bool no_wait_gpu, + bool no_wait_reserve, bool no_wait_gpu, struct ttm_mem_reg *new_mem) { int r; - r = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); + r = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); return r; } @@ -361,7 +361,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size, ttm_bo_type_device, &cirrusbo->placement, - align >> PAGE_SHIFT, false, NULL, acc_size, + align >> PAGE_SHIFT, 0, false, NULL, acc_size, NULL, cirrus_bo_ttm_destroy); if (ret) return ret; @@ -388,7 +388,7 @@ int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr) cirrus_ttm_placement(bo, pl_flag); for (i = 0; i < bo->placement.num_placement; i++) bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) return ret; @@ -411,7 +411,7 @@ int cirrus_bo_unpin(struct cirrus_bo *bo) for (i = 0; i < bo->placement.num_placement ; i++) bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) return ret; @@ -436,7 +436,7 @@ int cirrus_bo_push_sysram(struct cirrus_bo *bo) for (i = 0; i < bo->placement.num_placement ; i++) bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false); + ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false); if (ret) { DRM_ERROR("pushing to VRAM failed\n"); return ret; diff --git a/trunk/drivers/gpu/drm/drm_crtc.c b/trunk/drivers/gpu/drm/drm_crtc.c index f2d667b8bee2..ef1b22144d37 100644 --- a/trunk/drivers/gpu/drm/drm_crtc.c +++ b/trunk/drivers/gpu/drm/drm_crtc.c @@ -470,8 +470,10 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - kfree(crtc->gamma_store); - crtc->gamma_store = NULL; + if (crtc->gamma_store) { + kfree(crtc->gamma_store); + crtc->gamma_store = NULL; + } drm_mode_object_put(dev, &crtc->base); list_del(&crtc->head); @@ -553,17 +555,16 @@ int drm_connector_init(struct drm_device *dev, INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); connector->edid_blob_ptr = NULL; - connector->status = connector_status_unknown; list_add_tail(&connector->head, &dev->mode_config.connector_list); dev->mode_config.num_connector++; if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) - drm_object_attach_property(&connector->base, + drm_connector_attach_property(connector, dev->mode_config.edid_property, 0); - drm_object_attach_property(&connector->base, + drm_connector_attach_property(connector, dev->mode_config.dpms_property, 0); out: @@ -2279,21 +2280,13 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) for (i = 0; i < num_planes; i++) { unsigned int width = r->width / (i != 0 ? hsub : 1); - unsigned int height = r->height / (i != 0 ? vsub : 1); - unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); if (!r->handles[i]) { DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); return -EINVAL; } - if ((uint64_t) width * cpp > UINT_MAX) - return -ERANGE; - - if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX) - return -ERANGE; - - if (r->pitches[i] < width * cpp) { + if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) { DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); return -EINVAL; } @@ -2330,11 +2323,6 @@ int drm_mode_addfb2(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (r->flags & ~DRM_MODE_FB_INTERLACED) { - DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); - return -EINVAL; - } - if ((config->min_width > r->width) || (r->width > config->max_width)) { DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", r->width, config->min_width, config->max_width); @@ -2928,6 +2916,27 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) } EXPORT_SYMBOL(drm_property_destroy); +void drm_connector_attach_property(struct drm_connector *connector, + struct drm_property *property, uint64_t init_val) +{ + drm_object_attach_property(&connector->base, property, init_val); +} +EXPORT_SYMBOL(drm_connector_attach_property); + +int drm_connector_property_set_value(struct drm_connector *connector, + struct drm_property *property, uint64_t value) +{ + return drm_object_property_set_value(&connector->base, property, value); +} +EXPORT_SYMBOL(drm_connector_property_set_value); + +int drm_connector_property_get_value(struct drm_connector *connector, + struct drm_property *property, uint64_t *val) +{ + return drm_object_property_get_value(&connector->base, property, val); +} +EXPORT_SYMBOL(drm_connector_property_get_value); + void drm_object_attach_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t init_val) @@ -3164,17 +3173,15 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, /* Delete edid, when there is none. */ if (!edid) { connector->edid_blob_ptr = NULL; - ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0); + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); return ret; } size = EDID_LENGTH * (1 + edid->extensions); connector->edid_blob_ptr = drm_property_create_blob(connector->dev, size, edid); - if (!connector->edid_blob_ptr) - return -EINVAL; - ret = drm_object_property_set_value(&connector->base, + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->base.id); @@ -3197,9 +3204,6 @@ static bool drm_property_change_is_valid(struct drm_property *property, for (i = 0; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]); return !(value & ~valid_mask); - } else if (property->flags & DRM_MODE_PROP_BLOB) { - /* Only the driver knows */ - return true; } else { int i; for (i = 0; i < property->num_values; i++) @@ -3241,7 +3245,7 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, /* store the property value if successful */ if (!ret) - drm_object_property_set_value(&connector->base, property, value); + drm_connector_property_set_value(connector, property, value); return ret; } @@ -3652,12 +3656,9 @@ void drm_mode_config_reset(struct drm_device *dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - connector->status = connector_status_unknown; - + list_for_each_entry(connector, &dev->mode_config.connector_list, head) if (connector->funcs->reset) connector->funcs->reset(connector); - } } EXPORT_SYMBOL(drm_mode_config_reset); diff --git a/trunk/drivers/gpu/drm/drm_crtc_helper.c b/trunk/drivers/gpu/drm/drm_crtc_helper.c index 7b2d378b2576..1227adf74dbc 100644 --- a/trunk/drivers/gpu/drm/drm_crtc_helper.c +++ b/trunk/drivers/gpu/drm/drm_crtc_helper.c @@ -39,35 +39,6 @@ #include #include -/** - * drm_helper_move_panel_connectors_to_head() - move panels to the front in the - * connector list - * @dev: drm device to operate on - * - * Some userspace presumes that the first connected connector is the main - * display, where it's supposed to display e.g. the login screen. For - * laptops, this should be the main panel. Use this function to sort all - * (eDP/LVDS) panels to the front of the connector list, instead of - * painstakingly trying to initialize them in the right order. - */ -void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) -{ - struct drm_connector *connector, *tmp; - struct list_head panel_list; - - INIT_LIST_HEAD(&panel_list); - - list_for_each_entry_safe(connector, tmp, - &dev->mode_config.connector_list, head) { - if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || - connector->connector_type == DRM_MODE_CONNECTOR_eDP) - list_move_tail(&connector->head, &panel_list); - } - - list_splice(&panel_list, &dev->mode_config.connector_list); -} -EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); - static bool drm_kms_helper_poll = true; module_param_named(poll, drm_kms_helper_poll, bool, 0600); @@ -93,21 +64,22 @@ static void drm_mode_validate_flag(struct drm_connector *connector, /** * drm_helper_probe_single_connector_modes - get complete set of display modes - * @connector: connector to probe + * @dev: DRM device * @maxX: max width for modes * @maxY: max height for modes * * LOCKING: * Caller must hold mode config lock. * - * Based on the helper callbacks implemented by @connector try to detect all - * valid modes. Modes will first be added to the connector's probed_modes list, - * then culled (based on validity and the @maxX, @maxY parameters) and put into - * the normal modes list. + * Based on @dev's mode_config layout, scan all the connectors and try to detect + * modes on them. Modes will first be added to the connector's probed_modes + * list, then culled (based on validity and the @maxX, @maxY parameters) and + * put into the normal modes list. * - * Intended to be use as a generic implementation of the ->probe() @connector - * callback for drivers that use the crtc helpers for output mode filtering and - * detection. + * Intended to be used either at bootup time or when major configuration + * changes have occurred. + * + * FIXME: take into account monitor limits * * RETURNS: * Number of modes found on @connector. @@ -137,13 +109,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, connector->funcs->force(connector); } else { connector->status = connector->funcs->detect(connector, true); - } - - /* Re-enable polling in case the global poll config changed. */ - if (drm_kms_helper_poll != dev->mode_config.poll_running) drm_kms_helper_poll_enable(dev); - - dev->mode_config.poll_running = drm_kms_helper_poll; + } if (connector->status == connector_status_disconnected) { DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", @@ -358,24 +325,17 @@ drm_crtc_prepare_encoders(struct drm_device *dev) } /** - * drm_crtc_helper_set_mode - internal helper to set a mode + * drm_crtc_set_mode - set a mode * @crtc: CRTC to program * @mode: mode to use - * @x: horizontal offset into the surface - * @y: vertical offset into the surface - * @old_fb: old framebuffer, for cleanup + * @x: width of mode + * @y: height of mode * * LOCKING: * Caller must hold mode config lock. * * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance - * to fixup or reject the mode prior to trying to set it. This is an internal - * helper that drivers could e.g. use to update properties that require the - * entire output pipe to be disabled and re-enabled in a new configuration. For - * example for changing whether audio is enabled on a hdmi link or for changing - * panel fitter or dither attributes. It is also called by the - * drm_crtc_helper_set_config() helper function to drive the mode setting - * sequence. + * to fixup or reject the mode prior to trying to set it. * * RETURNS: * True if the mode was set successfully, or false otherwise. @@ -531,19 +491,20 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) /** * drm_crtc_helper_set_config - set a new config from userspace - * @set: mode set configuration + * @crtc: CRTC to setup + * @crtc_info: user provided configuration + * @new_mode: new mode to set + * @connector_set: set of connectors for the new config + * @fb: new framebuffer * * LOCKING: * Caller must hold mode config lock. * - * Setup a new configuration, provided by the upper layers (either an ioctl call - * from userspace or internally e.g. from the fbdev suppport code) in @set, and - * enable it. This is the main helper functions for drivers that implement - * kernel mode setting with the crtc helper functions and the assorted - * ->prepare(), ->modeset() and ->commit() helper callbacks. + * Setup a new configuration, provided by the user in @crtc_info, and enable + * it. * * RETURNS: - * Returns 0 on success, -ERRNO on failure. + * Zero. (FIXME) */ int drm_crtc_helper_set_config(struct drm_mode_set *set) { @@ -839,14 +800,12 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) } /** - * drm_helper_connector_dpms() - connector dpms helper implementation - * @connector: affected connector - * @mode: DPMS mode + * drm_helper_connector_dpms + * @connector affected connector + * @mode DPMS mode * - * This is the main helper function provided by the crtc helper framework for - * implementing the DPMS connector attribute. It computes the new desired DPMS - * state for all encoders and crtcs in the output mesh and calls the ->dpms() - * callback provided by the driver appropriately. + * Calls the low-level connector DPMS function, then + * calls appropriate encoder and crtc DPMS functions as well */ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) { @@ -959,15 +918,6 @@ int drm_helper_resume_force_mode(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_resume_force_mode); -void drm_kms_helper_hotplug_event(struct drm_device *dev) -{ - /* send a uevent + call fbdev */ - drm_sysfs_hotplug_event(dev); - if (dev->mode_config.funcs->output_poll_changed) - dev->mode_config.funcs->output_poll_changed(dev); -} -EXPORT_SYMBOL(drm_kms_helper_hotplug_event); - #define DRM_OUTPUT_POLL_PERIOD (10*HZ) static void output_poll_execute(struct work_struct *work) { @@ -983,22 +933,20 @@ static void output_poll_execute(struct work_struct *work) mutex_lock(&dev->mode_config.mutex); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - /* Ignore forced connectors. */ - if (connector->force) + /* if this is HPD or polled don't check it - + TV out for instance */ + if (!connector->polled) continue; - /* Ignore HPD capable connectors and connectors where we don't - * want any hotplug detection at all for polling. */ - if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) - continue; - - repoll = true; + else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) + repoll = true; old_status = connector->status; /* if we are connected and don't want to poll for disconnect skip it */ if (old_status == connector_status_connected && - !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) + !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && + !(connector->polled & DRM_CONNECTOR_POLL_HPD)) continue; connector->status = connector->funcs->detect(connector, false); @@ -1012,8 +960,12 @@ static void output_poll_execute(struct work_struct *work) mutex_unlock(&dev->mode_config.mutex); - if (changed) - drm_kms_helper_hotplug_event(dev); + if (changed) { + /* send a uevent + call fbdev */ + drm_sysfs_hotplug_event(dev); + if (dev->mode_config.funcs->output_poll_changed) + dev->mode_config.funcs->output_poll_changed(dev); + } if (repoll) schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); @@ -1036,8 +988,7 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) return; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT)) + if (connector->polled) poll = true; } @@ -1063,34 +1014,12 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini); void drm_helper_hpd_irq_event(struct drm_device *dev) { - struct drm_connector *connector; - enum drm_connector_status old_status; - bool changed = false; - if (!dev->mode_config.poll_enabled) return; - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - - /* Only handle HPD capable connectors. */ - if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) - continue; - - old_status = connector->status; - - connector->status = connector->funcs->detect(connector, false); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", - connector->base.id, - drm_get_connector_name(connector), - old_status, connector->status); - if (old_status != connector->status) - changed = true; - } - - mutex_unlock(&dev->mode_config.mutex); - - if (changed) - drm_kms_helper_hotplug_event(dev); + /* kill timer and schedule immediate execution, this doesn't block */ + cancel_delayed_work(&dev->mode_config.output_poll_work); + if (drm_kms_helper_poll) + schedule_delayed_work(&dev->mode_config.output_poll_work, 0); } EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/trunk/drivers/gpu/drm/drm_dp_helper.c b/trunk/drivers/gpu/drm/drm_dp_i2c_helper.c similarity index 58% rename from trunk/drivers/gpu/drm/drm_dp_helper.c rename to trunk/drivers/gpu/drm/drm_dp_i2c_helper.c index 89e196627160..7f246f212457 100644 --- a/trunk/drivers/gpu/drm/drm_dp_helper.c +++ b/trunk/drivers/gpu/drm/drm_dp_i2c_helper.c @@ -30,15 +30,6 @@ #include #include -/** - * DOC: dp helpers - * - * These functions contain some common logic and helpers at various abstraction - * levels to deal with Display Port sink devices and related things like DP aux - * channel transfers, EDID reading over DP aux channels, decoding certain DPCD - * blocks, ... - */ - /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ static int i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, @@ -46,7 +37,7 @@ i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, { struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; int ret; - + ret = (*algo_data->aux_ch)(adapter, mode, write_byte, read_byte); return ret; @@ -191,6 +182,7 @@ i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) { (void) i2c_algo_dp_aux_address(adapter, 0, false); (void) i2c_algo_dp_aux_stop(adapter, false); + } static int @@ -202,23 +194,11 @@ i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) return 0; } -/** - * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper - * @adapter: i2c adapter to register - * - * This registers an i2c adapater that uses dp aux channel as it's underlaying - * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure - * and store it in the algo_data member of the @adapter argument. This will be - * used by the i2c over dp aux algorithm to drive the hardware. - * - * RETURNS: - * 0 on success, -ERRNO on failure. - */ int i2c_dp_aux_add_bus(struct i2c_adapter *adapter) { int error; - + error = i2c_dp_aux_prepare_bus(adapter); if (error) return error; @@ -226,123 +206,3 @@ i2c_dp_aux_add_bus(struct i2c_adapter *adapter) return error; } EXPORT_SYMBOL(i2c_dp_aux_add_bus); - -/* Helpers for DP link training */ -static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) -{ - return link_status[r - DP_LANE0_1_STATUS]; -} - -static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE], - int lane) -{ - int i = DP_LANE0_1_STATUS + (lane >> 1); - int s = (lane & 1) * 4; - u8 l = dp_link_status(link_status, i); - return (l >> s) & 0xf; -} - -bool drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], - int lane_count) -{ - u8 lane_align; - u8 lane_status; - int lane; - - lane_align = dp_link_status(link_status, - DP_LANE_ALIGN_STATUS_UPDATED); - if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) - return false; - for (lane = 0; lane < lane_count; lane++) { - lane_status = dp_get_lane_status(link_status, lane); - if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) - return false; - } - return true; -} -EXPORT_SYMBOL(drm_dp_channel_eq_ok); - -bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], - int lane_count) -{ - int lane; - u8 lane_status; - - for (lane = 0; lane < lane_count; lane++) { - lane_status = dp_get_lane_status(link_status, lane); - if ((lane_status & DP_LANE_CR_DONE) == 0) - return false; - } - return true; -} -EXPORT_SYMBOL(drm_dp_clock_recovery_ok); - -u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], - int lane) -{ - int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); - int s = ((lane & 1) ? - DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : - DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); - u8 l = dp_link_status(link_status, i); - - return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; -} -EXPORT_SYMBOL(drm_dp_get_adjust_request_voltage); - -u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], - int lane) -{ - int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); - int s = ((lane & 1) ? - DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : - DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); - u8 l = dp_link_status(link_status, i); - - return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; -} -EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis); - -void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) { - if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0) - udelay(100); - else - mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4); -} -EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay); - -void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) { - if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0) - udelay(400); - else - mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4); -} -EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay); - -u8 drm_dp_link_rate_to_bw_code(int link_rate) -{ - switch (link_rate) { - case 162000: - default: - return DP_LINK_BW_1_62; - case 270000: - return DP_LINK_BW_2_7; - case 540000: - return DP_LINK_BW_5_4; - } -} -EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code); - -int drm_dp_bw_code_to_link_rate(u8 link_bw) -{ - switch (link_bw) { - case DP_LINK_BW_1_62: - default: - return 162000; - case DP_LINK_BW_2_7: - return 270000; - case DP_LINK_BW_5_4: - return 540000; - } -} -EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index 5a3770fbd770..fadcd44ff196 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -307,9 +307,12 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, static bool drm_edid_is_zero(u8 *in_edid, int length) { - if (memchr_inv(in_edid, 0, length)) - return false; + int i; + u32 *raw_edid = (u32 *)in_edid; + for (i = 0; i < length / 4; i++) + if (*(raw_edid + i) != 0) + return false; return true; } @@ -1513,26 +1516,6 @@ u8 *drm_find_cea_extension(struct edid *edid) } EXPORT_SYMBOL(drm_find_cea_extension); -/* - * Looks for a CEA mode matching given drm_display_mode. - * Returns its CEA Video ID code, or 0 if not found. - */ -u8 drm_match_cea_mode(struct drm_display_mode *to_match) -{ - struct drm_display_mode *cea_mode; - u8 mode; - - for (mode = 0; mode < drm_num_cea_modes; mode++) { - cea_mode = (struct drm_display_mode *)&edid_cea_modes[mode]; - - if (drm_mode_equal(to_match, cea_mode)) - return mode + 1; - } - return 0; -} -EXPORT_SYMBOL(drm_match_cea_mode); - - static int do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) { @@ -1639,7 +1622,7 @@ parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db) if (len >= 12) connector->audio_latency[1] = db[12]; - DRM_DEBUG_KMS("HDMI: DVI dual %d, " + DRM_LOG_KMS("HDMI: DVI dual %d, " "max TMDS clock %d, " "latency present %d %d, " "video latency %d %d, " @@ -2079,22 +2062,3 @@ int drm_add_modes_noedid(struct drm_connector *connector, return num_modes; } EXPORT_SYMBOL(drm_add_modes_noedid); - -/** - * drm_mode_cea_vic - return the CEA-861 VIC of a given mode - * @mode: mode - * - * RETURNS: - * The VIC number, 0 in case it's not a CEA-861 mode. - */ -uint8_t drm_mode_cea_vic(const struct drm_display_mode *mode) -{ - uint8_t i; - - for (i = 0; i < drm_num_cea_modes; i++) - if (drm_mode_equal(mode, &edid_cea_modes[i])) - return i + 1; - - return 0; -} -EXPORT_SYMBOL(drm_mode_cea_vic); diff --git a/trunk/drivers/gpu/drm/drm_fb_helper.c b/trunk/drivers/gpu/drm/drm_fb_helper.c index 954d175bd7fa..4d58d7e6af3f 100644 --- a/trunk/drivers/gpu/drm/drm_fb_helper.c +++ b/trunk/drivers/gpu/drm/drm_fb_helper.c @@ -27,8 +27,6 @@ * Dave Airlie * Jesse Barnes */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -45,15 +43,6 @@ MODULE_LICENSE("GPL and additional rights"); static LIST_HEAD(kernel_fb_helper_list); -/** - * DOC: fbdev helpers - * - * The fb helper functions are useful to provide an fbdev on top of a drm kernel - * mode setting driver. They can be used mostly independantely from the crtc - * helper functions used by many drivers to implement the kernel mode setting - * interfaces. - */ - /* simple single crtc case helper function */ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) { @@ -106,16 +95,10 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) if (mode->force) { const char *s; switch (mode->force) { - case DRM_FORCE_OFF: - s = "OFF"; - break; - case DRM_FORCE_ON_DIGITAL: - s = "ON - dig"; - break; + case DRM_FORCE_OFF: s = "OFF"; break; + case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break; default: - case DRM_FORCE_ON: - s = "ON"; - break; + case DRM_FORCE_ON: s = "ON"; break; } DRM_INFO("forcing %s connector %s\n", @@ -282,7 +265,7 @@ int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, if (panic_timeout < 0) return 0; - pr_err("panic occurred, switching back to text console\n"); + printk(KERN_ERR "panic occurred, switching back to text console\n"); return drm_fb_helper_force_kernel_mode(); } EXPORT_SYMBOL(drm_fb_helper_panic); @@ -348,7 +331,7 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) for (j = 0; j < fb_helper->connector_count; j++) { connector = fb_helper->connector_info[j]->connector; connector->funcs->dpms(connector, dpms_mode); - drm_object_property_set_value(&connector->base, + drm_connector_property_set_value(connector, dev->mode_config.dpms_property, dpms_mode); } } @@ -450,7 +433,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) if (!list_empty(&fb_helper->kernel_fb_list)) { list_del(&fb_helper->kernel_fb_list); if (list_empty(&kernel_fb_helper_list)) { - pr_info("drm: unregistered panic notifier\n"); + printk(KERN_INFO "drm: unregistered panic notifier\n"); atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); @@ -741,9 +724,9 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* if driver picks 8 or 16 by default use that for both depth/bpp */ - if (preferred_bpp != sizes.surface_bpp) + if (preferred_bpp != sizes.surface_bpp) { sizes.surface_depth = sizes.surface_bpp = preferred_bpp; - + } /* first up get a count of crtcs now in use and new min/maxes width/heights */ for (i = 0; i < fb_helper->connector_count; i++) { struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; @@ -811,16 +794,18 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, info = fb_helper->fbdev; /* set the fb pointer */ - for (i = 0; i < fb_helper->crtc_count; i++) + for (i = 0; i < fb_helper->crtc_count; i++) { fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; + } if (new_fb) { info->var.pixclock = 0; - if (register_framebuffer(info) < 0) + if (register_framebuffer(info) < 0) { return -EINVAL; + } - dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); } else { drm_fb_helper_set_par(info); @@ -829,7 +814,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* Switch back to kernel console on panic */ /* multi card linked list maybe */ if (list_empty(&kernel_fb_helper_list)) { - dev_info(fb_helper->dev->dev, "registered panic notifier\n"); + printk(KERN_INFO "drm: registered panic notifier\n"); atomic_notifier_chain_register(&panic_notifier_list, &paniced); register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); @@ -1017,11 +1002,11 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict) { bool enable; - if (strict) + if (strict) { enable = connector->status == connector_status_connected; - else + } else { enable = connector->status != connector_status_disconnected; - + } return enable; } @@ -1206,8 +1191,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, for (c = 0; c < fb_helper->crtc_count; c++) { crtc = &fb_helper->crtc_info[c]; - if ((encoder->possible_crtcs & (1 << c)) == 0) + if ((encoder->possible_crtcs & (1 << c)) == 0) { continue; + } for (o = 0; o < n; o++) if (best_crtcs[o] == crtc) @@ -1260,11 +1246,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) sizeof(struct drm_display_mode *), GFP_KERNEL); enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), GFP_KERNEL); - if (!crtcs || !modes || !enabled) { - DRM_ERROR("Memory allocation failed\n"); - goto out; - } - drm_enable_connectors(fb_helper, enabled); @@ -1303,7 +1284,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) } } -out: kfree(crtcs); kfree(modes); kfree(enabled); @@ -1311,14 +1291,12 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) /** * drm_helper_initial_config - setup a sane initial connector configuration - * @fb_helper: fb_helper device struct - * @bpp_sel: bpp value to use for the framebuffer configuration + * @dev: DRM device * * LOCKING: - * Called at init time by the driver to set up the @fb_helper initial - * configuration, must take the mode config lock. + * Called at init time, must take mode config lock. * - * Scans the CRTCs and connectors and tries to put together an initial setup. + * Scan the CRTCs and connectors and try to put together an initial setup. * At the moment, this is a cloned configuration across all heads with * a new framebuffer object as the backing store. * @@ -1341,9 +1319,9 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) /* * we shouldn't end up with no modes here. */ - if (count == 0) - dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n"); - + if (count == 0) { + printk(KERN_INFO "No connectors reported connected with modes\n"); + } drm_setup_crtcs(fb_helper); return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); @@ -1352,7 +1330,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); /** * drm_fb_helper_hotplug_event - respond to a hotplug notification by - * probing all the outputs attached to the fb + * probing all the outputs attached to the fb. * @fb_helper: the drm_fb_helper * * LOCKING: diff --git a/trunk/drivers/gpu/drm/drm_hashtab.c b/trunk/drivers/gpu/drm/drm_hashtab.c index 80254547a3f8..c3745c4d46d8 100644 --- a/trunk/drivers/gpu/drm/drm_hashtab.c +++ b/trunk/drivers/gpu/drm/drm_hashtab.c @@ -67,8 +67,10 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) hashed_key = hash_long(key, ht->order); DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); h_list = &ht->table[hashed_key]; - hlist_for_each_entry(entry, list, h_list, head) + hlist_for_each(list, h_list) { + entry = hlist_entry(list, struct drm_hash_item, head); DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); + } } static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, @@ -81,7 +83,8 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, hashed_key = hash_long(key, ht->order); h_list = &ht->table[hashed_key]; - hlist_for_each_entry(entry, list, h_list, head) { + hlist_for_each(list, h_list) { + entry = hlist_entry(list, struct drm_hash_item, head); if (entry->key == key) return list; if (entry->key > key) @@ -90,24 +93,6 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, return NULL; } -static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht, - unsigned long key) -{ - struct drm_hash_item *entry; - struct hlist_head *h_list; - struct hlist_node *list; - unsigned int hashed_key; - - hashed_key = hash_long(key, ht->order); - h_list = &ht->table[hashed_key]; - hlist_for_each_entry_rcu(entry, list, h_list, head) { - if (entry->key == key) - return list; - if (entry->key > key) - break; - } - return NULL; -} int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) { @@ -120,7 +105,8 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) hashed_key = hash_long(key, ht->order); h_list = &ht->table[hashed_key]; parent = NULL; - hlist_for_each_entry(entry, list, h_list, head) { + hlist_for_each(list, h_list) { + entry = hlist_entry(list, struct drm_hash_item, head); if (entry->key == key) return -EINVAL; if (entry->key > key) @@ -128,9 +114,9 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) parent = list; } if (parent) { - hlist_add_after_rcu(parent, &item->head); + hlist_add_after(parent, &item->head); } else { - hlist_add_head_rcu(&item->head, h_list); + hlist_add_head(&item->head, h_list); } return 0; } @@ -170,7 +156,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, { struct hlist_node *list; - list = drm_ht_find_key_rcu(ht, key); + list = drm_ht_find_key(ht, key); if (!list) return -EINVAL; @@ -185,7 +171,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) list = drm_ht_find_key(ht, key); if (list) { - hlist_del_init_rcu(list); + hlist_del_init(list); return 0; } return -EINVAL; @@ -193,7 +179,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) { - hlist_del_init_rcu(&item->head); + hlist_del_init(&item->head); return 0; } EXPORT_SYMBOL(drm_ht_remove_item); diff --git a/trunk/drivers/gpu/drm/drm_ioctl.c b/trunk/drivers/gpu/drm/drm_ioctl.c index e77bd8b57df2..23dd97506f28 100644 --- a/trunk/drivers/gpu/drm/drm_ioctl.c +++ b/trunk/drivers/gpu/drm/drm_ioctl.c @@ -287,9 +287,6 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; break; - case DRM_CAP_TIMESTAMP_MONOTONIC: - req->value = drm_timestamp_monotonic; - break; default: return -EINVAL; } diff --git a/trunk/drivers/gpu/drm/drm_irq.c b/trunk/drivers/gpu/drm/drm_irq.c index 19c01ca3cc76..3a3d0ce891b9 100644 --- a/trunk/drivers/gpu/drm/drm_irq.c +++ b/trunk/drivers/gpu/drm/drm_irq.c @@ -106,7 +106,6 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) s64 diff_ns; int vblrc; struct timeval tvblank; - int count = DRM_TIMESTAMP_MAXRETRIES; /* Prevent vblank irq processing while disabling vblank irqs, * so no updates of timestamps or count can happen after we've @@ -132,10 +131,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) do { dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); - } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); - - if (!count) - vblrc = 0; + } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc)); /* Compute time difference to stored timestamp of last vblank * as updated by last invocation of drm_handle_vblank() in vblank irq. @@ -580,8 +576,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, unsigned flags, struct drm_crtc *refcrtc) { - ktime_t stime, etime, mono_time_offset; - struct timeval tv_etime; + struct timeval stime, raw_time; struct drm_display_mode *mode; int vbl_status, vtotal, vdisplay; int vpos, hpos, i; @@ -630,15 +625,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, preempt_disable(); /* Get system timestamp before query. */ - stime = ktime_get(); + do_gettimeofday(&stime); /* Get vertical and horizontal scanout pos. vpos, hpos. */ vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); /* Get system timestamp after query. */ - etime = ktime_get(); - if (!drm_timestamp_monotonic) - mono_time_offset = ktime_get_monotonic_offset(); + do_gettimeofday(&raw_time); preempt_enable(); @@ -649,7 +642,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, return -EIO; } - duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); + duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime); /* Accept result with < max_error nsecs timing uncertainty. */ if (duration_ns <= (s64) *max_error) @@ -696,20 +689,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, vbl_status |= 0x8; } - if (!drm_timestamp_monotonic) - etime = ktime_sub(etime, mono_time_offset); - - /* save this only for debugging purposes */ - tv_etime = ktime_to_timeval(etime); /* Subtract time delta from raw timestamp to get final * vblank_time timestamp for end of vblank. */ - etime = ktime_sub_ns(etime, delta_ns); - *vblank_time = ktime_to_timeval(etime); + *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns); DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", crtc, (int)vbl_status, hpos, vpos, - (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, + (long)raw_time.tv_sec, (long)raw_time.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, (int)duration_ns/1000, i); @@ -721,17 +708,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, } EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); -static struct timeval get_drm_timestamp(void) -{ - ktime_t now; - - now = ktime_get(); - if (!drm_timestamp_monotonic) - now = ktime_sub(now, ktime_get_monotonic_offset()); - - return ktime_to_timeval(now); -} - /** * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent * vblank interval. @@ -769,9 +745,9 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, } /* GPU high precision timestamp query unsupported or failed. - * Return current monotonic/gettimeofday timestamp as best estimate. + * Return gettimeofday timestamp as best estimate. */ - *tvblank = get_drm_timestamp(); + do_gettimeofday(tvblank); return 0; } @@ -826,47 +802,6 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, } EXPORT_SYMBOL(drm_vblank_count_and_time); -static void send_vblank_event(struct drm_device *dev, - struct drm_pending_vblank_event *e, - unsigned long seq, struct timeval *now) -{ - WARN_ON_SMP(!spin_is_locked(&dev->event_lock)); - e->event.sequence = seq; - e->event.tv_sec = now->tv_sec; - e->event.tv_usec = now->tv_usec; - - list_add_tail(&e->base.link, - &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - trace_drm_vblank_event_delivered(e->base.pid, e->pipe, - e->event.sequence); -} - -/** - * drm_send_vblank_event - helper to send vblank event after pageflip - * @dev: DRM device - * @crtc: CRTC in question - * @e: the event to send - * - * Updates sequence # and timestamp on event, and sends it to userspace. - * Caller must hold event lock. - */ -void drm_send_vblank_event(struct drm_device *dev, int crtc, - struct drm_pending_vblank_event *e) -{ - struct timeval now; - unsigned int seq; - if (crtc >= 0) { - seq = drm_vblank_count_and_time(dev, crtc, &now); - } else { - seq = 0; - - now = get_drm_timestamp(); - } - send_vblank_event(dev, e, seq, &now); -} -EXPORT_SYMBOL(drm_send_vblank_event); - /** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device @@ -1001,13 +936,6 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put); -/** - * drm_vblank_off - disable vblank events on a CRTC - * @dev: DRM device - * @crtc: CRTC in question - * - * Caller must hold event lock. - */ void drm_vblank_off(struct drm_device *dev, int crtc) { struct drm_pending_vblank_event *e, *t; @@ -1021,19 +949,22 @@ void drm_vblank_off(struct drm_device *dev, int crtc) /* Send any queued vblank events, lest the natives grow disquiet */ seq = drm_vblank_count_and_time(dev, crtc, &now); - - spin_lock(&dev->event_lock); list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { if (e->pipe != crtc) continue; DRM_DEBUG("Sending premature vblank event on disable: \ wanted %d, current %d\n", e->event.sequence, seq); - list_del(&e->base.link); + + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); - send_vblank_event(dev, e, seq, &now); + list_move_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, + e->event.sequence); } - spin_unlock(&dev->event_lock); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } @@ -1176,9 +1107,15 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) { + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, pipe); - send_vblank_event(dev, e, seq, &now); + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); vblwait->reply.sequence = seq; + trace_drm_vblank_event_delivered(current->pid, pipe, + vblwait->request.sequence); } else { /* drm_handle_vblank_events will call drm_vblank_put */ list_add_tail(&e->base.link, &dev->vblank_event_list); @@ -1319,9 +1256,14 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) DRM_DEBUG("vblank event on %d, current %d\n", e->event.sequence, seq); - list_del(&e->base.link); + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); - send_vblank_event(dev, e, seq, &now); + list_move_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, + e->event.sequence); } spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/trunk/drivers/gpu/drm/drm_modes.c b/trunk/drivers/gpu/drm/drm_modes.c index d8da30e90db5..59450f39bf96 100644 --- a/trunk/drivers/gpu/drm/drm_modes.c +++ b/trunk/drivers/gpu/drm/drm_modes.c @@ -46,7 +46,7 @@ * * Describe @mode using DRM_DEBUG. */ -void drm_mode_debug_printmodeline(const struct drm_display_mode *mode) +void drm_mode_debug_printmodeline(struct drm_display_mode *mode) { DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d " "0x%x 0x%x\n", @@ -558,7 +558,7 @@ EXPORT_SYMBOL(drm_mode_list_concat); * RETURNS: * @mode->hdisplay */ -int drm_mode_width(const struct drm_display_mode *mode) +int drm_mode_width(struct drm_display_mode *mode) { return mode->hdisplay; @@ -579,7 +579,7 @@ EXPORT_SYMBOL(drm_mode_width); * RETURNS: * @mode->vdisplay */ -int drm_mode_height(const struct drm_display_mode *mode) +int drm_mode_height(struct drm_display_mode *mode) { return mode->vdisplay; } @@ -768,7 +768,7 @@ EXPORT_SYMBOL(drm_mode_duplicate); * RETURNS: * True if the modes are equal, false otherwise. */ -bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) +bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2) { /* do clock check convert to PICOS so fb modes get matched * the same */ diff --git a/trunk/drivers/gpu/drm/drm_pci.c b/trunk/drivers/gpu/drm/drm_pci.c index 754bc96e10c7..ba33144257e5 100644 --- a/trunk/drivers/gpu/drm/drm_pci.c +++ b/trunk/drivers/gpu/drm/drm_pci.c @@ -470,7 +470,7 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) { struct pci_dev *root; int pos; - u32 lnkcap = 0, lnkcap2 = 0; + u32 lnkcap, lnkcap2; *mask = 0; if (!dev->pdev) diff --git a/trunk/drivers/gpu/drm/drm_stub.c b/trunk/drivers/gpu/drm/drm_stub.c index 200e104f1fa0..c236fd27eba6 100644 --- a/trunk/drivers/gpu/drm/drm_stub.c +++ b/trunk/drivers/gpu/drm/drm_stub.c @@ -46,24 +46,16 @@ EXPORT_SYMBOL(drm_vblank_offdelay); unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ EXPORT_SYMBOL(drm_timestamp_precision); -/* - * Default to use monotonic timestamps for wait-for-vblank and page-flip - * complete events. - */ -unsigned int drm_timestamp_monotonic = 1; - MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); -MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); module_param_named(debug, drm_debug, int, 0600); module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); -module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); struct idr drm_minors_idr; @@ -229,20 +221,20 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, if (!file_priv->master) return -EINVAL; - if (file_priv->minor->master) - return -EINVAL; - - mutex_lock(&dev->struct_mutex); - file_priv->minor->master = drm_master_get(file_priv->master); - file_priv->is_master = 1; - if (dev->driver->master_set) { - ret = dev->driver->master_set(dev, file_priv, false); - if (unlikely(ret != 0)) { - file_priv->is_master = 0; - drm_master_put(&file_priv->minor->master); + if (!file_priv->minor->master && + file_priv->minor->master != file_priv->master) { + mutex_lock(&dev->struct_mutex); + file_priv->minor->master = drm_master_get(file_priv->master); + file_priv->is_master = 1; + if (dev->driver->master_set) { + ret = dev->driver->master_set(dev, file_priv, false); + if (unlikely(ret != 0)) { + file_priv->is_master = 0; + drm_master_put(&file_priv->minor->master); + } } + mutex_unlock(&dev->struct_mutex); } - mutex_unlock(&dev->struct_mutex); return 0; } @@ -500,7 +492,10 @@ void drm_put_dev(struct drm_device *dev) drm_put_minor(&dev->primary); list_del(&dev->driver_item); - kfree(dev->devname); + if (dev->devname) { + kfree(dev->devname); + dev->devname = NULL; + } kfree(dev); } EXPORT_SYMBOL(drm_put_dev); diff --git a/trunk/drivers/gpu/drm/drm_sysfs.c b/trunk/drivers/gpu/drm/drm_sysfs.c index 02296653a058..05cd8fe062af 100644 --- a/trunk/drivers/gpu/drm/drm_sysfs.c +++ b/trunk/drivers/gpu/drm/drm_sysfs.c @@ -182,7 +182,7 @@ static ssize_t dpms_show(struct device *device, uint64_t dpms_status; int ret; - ret = drm_object_property_get_value(&connector->base, + ret = drm_connector_property_get_value(connector, dev->mode_config.dpms_property, &dpms_status); if (ret) @@ -277,7 +277,7 @@ static ssize_t subconnector_show(struct device *device, return 0; } - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); + ret = drm_connector_property_get_value(connector, prop, &subconnector); if (ret) return 0; @@ -318,7 +318,7 @@ static ssize_t select_subconnector_show(struct device *device, return 0; } - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); + ret = drm_connector_property_get_value(connector, prop, &subconnector); if (ret) return 0; diff --git a/trunk/drivers/gpu/drm/exynos/Kconfig b/trunk/drivers/gpu/drm/exynos/Kconfig index 1d1f1e5e33f0..fc345d4ebb03 100644 --- a/trunk/drivers/gpu/drm/exynos/Kconfig +++ b/trunk/drivers/gpu/drm/exynos/Kconfig @@ -10,12 +10,6 @@ config DRM_EXYNOS Choose this option if you have a Samsung SoC EXYNOS chipset. If M is selected the module will be called exynosdrm. -config DRM_EXYNOS_IOMMU - bool "EXYNOS DRM IOMMU Support" - depends on DRM_EXYNOS && EXYNOS_IOMMU && ARM_DMA_USE_IOMMU - help - Choose this option if you want to use IOMMU feature for DRM. - config DRM_EXYNOS_DMABUF bool "EXYNOS DRM DMABUF" depends on DRM_EXYNOS @@ -45,27 +39,3 @@ config DRM_EXYNOS_G2D depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D help Choose this option if you want to use Exynos G2D for DRM. - -config DRM_EXYNOS_IPP - bool "Exynos DRM IPP" - depends on DRM_EXYNOS - help - Choose this option if you want to use IPP feature for DRM. - -config DRM_EXYNOS_FIMC - bool "Exynos DRM FIMC" - depends on DRM_EXYNOS_IPP - help - Choose this option if you want to use Exynos FIMC for DRM. - -config DRM_EXYNOS_ROTATOR - bool "Exynos DRM Rotator" - depends on DRM_EXYNOS_IPP - help - Choose this option if you want to use Exynos Rotator for DRM. - -config DRM_EXYNOS_GSC - bool "Exynos DRM GSC" - depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 - help - Choose this option if you want to use Exynos GSC for DRM. diff --git a/trunk/drivers/gpu/drm/exynos/Makefile b/trunk/drivers/gpu/drm/exynos/Makefile index 639b49e1ec05..eb651ca8e2a8 100644 --- a/trunk/drivers/gpu/drm/exynos/Makefile +++ b/trunk/drivers/gpu/drm/exynos/Makefile @@ -8,7 +8,6 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ exynos_drm_plane.o -exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ @@ -16,9 +15,5 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ exynos_drm_hdmi.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o -exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o -exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o -exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o -exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o diff --git a/trunk/drivers/gpu/drm/exynos/exynos_ddc.c b/trunk/drivers/gpu/drm/exynos/exynos_ddc.c index bef43e0342a6..37e6ec704e1d 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_ddc.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_ddc.c @@ -48,7 +48,6 @@ static struct i2c_device_id ddc_idtable[] = { { }, }; -#ifdef CONFIG_OF static struct of_device_id hdmiddc_match_types[] = { { .compatible = "samsung,exynos5-hdmiddc", @@ -56,13 +55,12 @@ static struct of_device_id hdmiddc_match_types[] = { /* end node */ } }; -#endif struct i2c_driver ddc_driver = { .driver = { .name = "exynos-hdmiddc", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(hdmiddc_match_types), + .of_match_table = hdmiddc_match_types, }, .id_table = ddc_idtable, .probe = s5p_ddc_probe, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c index 9601bad47a2e..118c117b3226 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -33,64 +33,89 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, unsigned int flags, struct exynos_drm_gem_buf *buf) { + dma_addr_t start_addr; + unsigned int npages, i = 0; + struct scatterlist *sgl; int ret = 0; - enum dma_attr attr; - unsigned int nr_pages; DRM_DEBUG_KMS("%s\n", __FILE__); + if (IS_NONCONTIG_BUFFER(flags)) { + DRM_DEBUG_KMS("not support allocation type.\n"); + return -EINVAL; + } + if (buf->dma_addr) { DRM_DEBUG_KMS("already allocated.\n"); return 0; } - init_dma_attrs(&buf->dma_attrs); - - /* - * if EXYNOS_BO_CONTIG, fully physically contiguous memory - * region will be allocated else physically contiguous - * as possible. - */ - if (flags & EXYNOS_BO_CONTIG) - dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs); + if (buf->size >= SZ_1M) { + npages = buf->size >> SECTION_SHIFT; + buf->page_size = SECTION_SIZE; + } else if (buf->size >= SZ_64K) { + npages = buf->size >> 16; + buf->page_size = SZ_64K; + } else { + npages = buf->size >> PAGE_SHIFT; + buf->page_size = PAGE_SIZE; + } - /* - * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping - * else cachable mapping. - */ - if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE)) - attr = DMA_ATTR_WRITE_COMBINE; - else - attr = DMA_ATTR_NON_CONSISTENT; + buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!buf->sgt) { + DRM_ERROR("failed to allocate sg table.\n"); + return -ENOMEM; + } - dma_set_attr(attr, &buf->dma_attrs); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs); + ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); + if (ret < 0) { + DRM_ERROR("failed to initialize sg table.\n"); + kfree(buf->sgt); + buf->sgt = NULL; + return -ENOMEM; + } - buf->pages = dma_alloc_attrs(dev->dev, buf->size, - &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); - if (!buf->pages) { + buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, + &buf->dma_addr, GFP_KERNEL); + if (!buf->kvaddr) { DRM_ERROR("failed to allocate buffer.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err1; } - nr_pages = buf->size >> PAGE_SHIFT; - buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages); - if (!buf->sgt) { - DRM_ERROR("failed to get sg table.\n"); + buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); + if (!buf->pages) { + DRM_ERROR("failed to allocate pages.\n"); ret = -ENOMEM; - goto err_free_attrs; + goto err2; + } + + sgl = buf->sgt->sgl; + start_addr = buf->dma_addr; + + while (i < npages) { + buf->pages[i] = phys_to_page(start_addr); + sg_set_page(sgl, buf->pages[i], buf->page_size, 0); + sg_dma_address(sgl) = start_addr; + start_addr += buf->page_size; + sgl = sg_next(sgl); + i++; } - DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", + DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", + (unsigned long)buf->kvaddr, (unsigned long)buf->dma_addr, buf->size); return ret; - -err_free_attrs: - dma_free_attrs(dev->dev, buf->size, buf->pages, - (dma_addr_t)buf->dma_addr, &buf->dma_attrs); +err2: + dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, + (dma_addr_t)buf->dma_addr); buf->dma_addr = (dma_addr_t)NULL; +err1: + sg_free_table(buf->sgt); + kfree(buf->sgt); + buf->sgt = NULL; return ret; } @@ -100,12 +125,23 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, { DRM_DEBUG_KMS("%s.\n", __FILE__); + /* + * release only physically continuous memory and + * non-continuous memory would be released by exynos + * gem framework. + */ + if (IS_NONCONTIG_BUFFER(flags)) { + DRM_DEBUG_KMS("not support allocation type.\n"); + return; + } + if (!buf->dma_addr) { DRM_DEBUG_KMS("dma_addr is invalid.\n"); return; } - DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", + DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", + (unsigned long)buf->kvaddr, (unsigned long)buf->dma_addr, buf->size); @@ -114,8 +150,11 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, kfree(buf->sgt); buf->sgt = NULL; - dma_free_attrs(dev->dev, buf->size, buf->pages, - (dma_addr_t)buf->dma_addr, &buf->dma_attrs); + kfree(buf->pages); + buf->pages = NULL; + + dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, + (dma_addr_t)buf->dma_addr); buf->dma_addr = (dma_addr_t)NULL; } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h index 25cf16285033..3388e4eb4ba2 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h @@ -34,12 +34,12 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, void exynos_drm_fini_buf(struct drm_device *dev, struct exynos_drm_gem_buf *buffer); -/* allocate physical memory region and setup sgt. */ +/* allocate physical memory region and setup sgt and pages. */ int exynos_drm_alloc_buf(struct drm_device *dev, struct exynos_drm_gem_buf *buf, unsigned int flags); -/* release physical memory region, and sgt. */ +/* release physical memory region, sgt and pages. */ void exynos_drm_free_buf(struct drm_device *dev, unsigned int flags, struct exynos_drm_gem_buf *buffer); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 2efa4b031d73..fce245f64c4f 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -236,21 +236,16 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, goto out; } - spin_lock_irq(&dev->event_lock); list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); - spin_unlock_irq(&dev->event_lock); crtc->fb = fb; ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, NULL); if (ret) { crtc->fb = old_fb; - - spin_lock_irq(&dev->event_lock); drm_vblank_put(dev, exynos_crtc->pipe); list_del(&event->base.link); - spin_unlock_irq(&dev->event_lock); goto out; } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 61d5a8402eb8..fae1f2ec886c 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -30,108 +30,70 @@ #include -struct exynos_drm_dmabuf_attachment { - struct sg_table sgt; - enum dma_data_direction dir; -}; - -static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, - struct device *dev, - struct dma_buf_attachment *attach) +static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages, + unsigned int page_size) { - struct exynos_drm_dmabuf_attachment *exynos_attach; - - exynos_attach = kzalloc(sizeof(*exynos_attach), GFP_KERNEL); - if (!exynos_attach) - return -ENOMEM; - - exynos_attach->dir = DMA_NONE; - attach->priv = exynos_attach; + struct sg_table *sgt = NULL; + struct scatterlist *sgl; + int i, ret; - return 0; -} + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + goto out; -static void exynos_gem_detach_dma_buf(struct dma_buf *dmabuf, - struct dma_buf_attachment *attach) -{ - struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv; - struct sg_table *sgt; + ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL); + if (ret) + goto err_free_sgt; - if (!exynos_attach) - return; + if (page_size < PAGE_SIZE) + page_size = PAGE_SIZE; - sgt = &exynos_attach->sgt; + for_each_sg(sgt->sgl, sgl, nr_pages, i) + sg_set_page(sgl, pages[i], page_size, 0); - if (exynos_attach->dir != DMA_NONE) - dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, - exynos_attach->dir); + return sgt; - sg_free_table(sgt); - kfree(exynos_attach); - attach->priv = NULL; +err_free_sgt: + kfree(sgt); + sgt = NULL; +out: + return NULL; } static struct sg_table * exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) { - struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv; struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv; struct drm_device *dev = gem_obj->base.dev; struct exynos_drm_gem_buf *buf; - struct scatterlist *rd, *wr; struct sg_table *sgt = NULL; - unsigned int i; - int nents, ret; + unsigned int npages; + int nents; DRM_DEBUG_PRIME("%s\n", __FILE__); - if (WARN_ON(dir == DMA_NONE)) - return ERR_PTR(-EINVAL); - - /* just return current sgt if already requested. */ - if (exynos_attach->dir == dir) - return &exynos_attach->sgt; - - /* reattaching is not allowed. */ - if (WARN_ON(exynos_attach->dir != DMA_NONE)) - return ERR_PTR(-EBUSY); + mutex_lock(&dev->struct_mutex); buf = gem_obj->buffer; - if (!buf) { - DRM_ERROR("buffer is null.\n"); - return ERR_PTR(-ENOMEM); - } - - sgt = &exynos_attach->sgt; - ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL); - if (ret) { - DRM_ERROR("failed to alloc sgt.\n"); - return ERR_PTR(-ENOMEM); + /* there should always be pages allocated. */ + if (!buf->pages) { + DRM_ERROR("pages is null.\n"); + goto err_unlock; } - mutex_lock(&dev->struct_mutex); + npages = buf->size / buf->page_size; - rd = buf->sgt->sgl; - wr = sgt->sgl; - for (i = 0; i < sgt->orig_nents; ++i) { - sg_set_page(wr, sg_page(rd), rd->length, rd->offset); - rd = sg_next(rd); - wr = sg_next(wr); - } - - nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); - if (!nents) { - DRM_ERROR("failed to map sgl with iommu.\n"); - sgt = ERR_PTR(-EIO); + sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size); + if (!sgt) { + DRM_DEBUG_PRIME("exynos_pages_to_sg returned NULL!\n"); goto err_unlock; } + nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); - exynos_attach->dir = dir; - attach->priv = exynos_attach; - - DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size); + DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n", + npages, buf->size, buf->page_size); err_unlock: mutex_unlock(&dev->struct_mutex); @@ -142,7 +104,10 @@ static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach, struct sg_table *sgt, enum dma_data_direction dir) { - /* Nothing to do. */ + dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); + sg_free_table(sgt); + kfree(sgt); + sgt = NULL; } static void exynos_dmabuf_release(struct dma_buf *dmabuf) @@ -204,8 +169,6 @@ static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, } static struct dma_buf_ops exynos_dmabuf_ops = { - .attach = exynos_gem_attach_dma_buf, - .detach = exynos_gem_detach_dma_buf, .map_dma_buf = exynos_gem_map_dma_buf, .unmap_dma_buf = exynos_gem_unmap_dma_buf, .kmap = exynos_gem_dmabuf_kmap, @@ -233,6 +196,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, struct scatterlist *sgl; struct exynos_drm_gem_obj *exynos_gem_obj; struct exynos_drm_gem_buf *buffer; + struct page *page; int ret; DRM_DEBUG_PRIME("%s\n", __FILE__); @@ -269,27 +233,38 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, goto err_unmap_attach; } + buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL); + if (!buffer->pages) { + DRM_ERROR("failed to allocate pages.\n"); + ret = -ENOMEM; + goto err_free_buffer; + } + exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size); if (!exynos_gem_obj) { ret = -ENOMEM; - goto err_free_buffer; + goto err_free_pages; } sgl = sgt->sgl; - buffer->size = dma_buf->size; - buffer->dma_addr = sg_dma_address(sgl); - if (sgt->nents == 1) { + buffer->dma_addr = sg_dma_address(sgt->sgl); + buffer->size = sg_dma_len(sgt->sgl); + /* always physically continuous memory if sgt->nents is 1. */ exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; } else { - /* - * this case could be CONTIG or NONCONTIG type but for now - * sets NONCONTIG. - * TODO. we have to find a way that exporter can notify - * the type of its own buffer to importer. - */ + unsigned int i = 0; + + buffer->dma_addr = sg_dma_address(sgl); + while (i < sgt->nents) { + buffer->pages[i] = sg_page(sgl); + buffer->size += sg_dma_len(sgl); + sgl = sg_next(sgl); + i++; + } + exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; } @@ -302,6 +277,9 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, return &exynos_gem_obj->base; +err_free_pages: + kfree(buffer->pages); + buffer->pages = NULL; err_free_buffer: kfree(buffer); buffer = NULL; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c index e0a8e8024b01..1de7baafddd0 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -40,8 +40,6 @@ #include "exynos_drm_vidi.h" #include "exynos_drm_dmabuf.h" #include "exynos_drm_g2d.h" -#include "exynos_drm_ipp.h" -#include "exynos_drm_iommu.h" #define DRIVER_NAME "exynos" #define DRIVER_DESC "Samsung SoC DRM" @@ -51,9 +49,6 @@ #define VBLANK_OFF_DELAY 50000 -/* platform device pointer for eynos drm device. */ -static struct platform_device *exynos_drm_pdev; - static int exynos_drm_load(struct drm_device *dev, unsigned long flags) { struct exynos_drm_private *private; @@ -71,18 +66,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&private->pageflip_event_list); dev->dev_private = (void *)private; - /* - * create mapping to manage iommu table and set a pointer to iommu - * mapping structure to iommu_mapping of private data. - * also this iommu_mapping can be used to check if iommu is supported - * or not. - */ - ret = drm_create_iommu_mapping(dev); - if (ret < 0) { - DRM_ERROR("failed to create iommu mapping.\n"); - goto err_crtc; - } - drm_mode_config_init(dev); /* init kms poll for handling hpd */ @@ -97,7 +80,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) for (nr = 0; nr < MAX_CRTC; nr++) { ret = exynos_drm_crtc_create(dev, nr); if (ret) - goto err_release_iommu_mapping; + goto err_crtc; } for (nr = 0; nr < MAX_PLANE; nr++) { @@ -106,12 +89,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) plane = exynos_plane_init(dev, possible_crtcs, false); if (!plane) - goto err_release_iommu_mapping; + goto err_crtc; } ret = drm_vblank_init(dev, MAX_CRTC); if (ret) - goto err_release_iommu_mapping; + goto err_crtc; /* * probe sub drivers such as display controller and hdmi driver, @@ -143,8 +126,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) exynos_drm_device_unregister(dev); err_vblank: drm_vblank_cleanup(dev); -err_release_iommu_mapping: - drm_release_iommu_mapping(dev); err_crtc: drm_mode_config_cleanup(dev); kfree(private); @@ -161,8 +142,6 @@ static int exynos_drm_unload(struct drm_device *dev) drm_vblank_cleanup(dev); drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); - - drm_release_iommu_mapping(dev); kfree(dev->dev_private); dev->dev_private = NULL; @@ -250,14 +229,6 @@ static struct drm_ioctl_desc exynos_ioctls[] = { exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, - exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, - exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF, - exynos_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL, - exynos_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH), }; static const struct file_operations exynos_drm_driver_fops = { @@ -308,7 +279,6 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) { DRM_DEBUG_DRIVER("%s\n", __FILE__); - pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls); return drm_platform_init(&exynos_drm_driver, pdev); @@ -354,10 +324,6 @@ static int __init exynos_drm_init(void) ret = platform_driver_register(&exynos_drm_common_hdmi_driver); if (ret < 0) goto out_common_hdmi; - - ret = exynos_platform_device_hdmi_register(); - if (ret < 0) - goto out_common_hdmi_dev; #endif #ifdef CONFIG_DRM_EXYNOS_VIDI @@ -372,80 +338,24 @@ static int __init exynos_drm_init(void) goto out_g2d; #endif -#ifdef CONFIG_DRM_EXYNOS_FIMC - ret = platform_driver_register(&fimc_driver); - if (ret < 0) - goto out_fimc; -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - ret = platform_driver_register(&rotator_driver); - if (ret < 0) - goto out_rotator; -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - ret = platform_driver_register(&gsc_driver); - if (ret < 0) - goto out_gsc; -#endif - -#ifdef CONFIG_DRM_EXYNOS_IPP - ret = platform_driver_register(&ipp_driver); - if (ret < 0) - goto out_ipp; -#endif - ret = platform_driver_register(&exynos_drm_platform_driver); if (ret < 0) - goto out_drm; - - exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, - NULL, 0); - if (IS_ERR_OR_NULL(exynos_drm_pdev)) { - ret = PTR_ERR(exynos_drm_pdev); goto out; - } return 0; out: - platform_driver_unregister(&exynos_drm_platform_driver); - -out_drm: -#ifdef CONFIG_DRM_EXYNOS_IPP - platform_driver_unregister(&ipp_driver); -out_ipp: -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - platform_driver_unregister(&gsc_driver); -out_gsc: -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - platform_driver_unregister(&rotator_driver); -out_rotator: -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMC - platform_driver_unregister(&fimc_driver); -out_fimc: -#endif - #ifdef CONFIG_DRM_EXYNOS_G2D platform_driver_unregister(&g2d_driver); out_g2d: #endif #ifdef CONFIG_DRM_EXYNOS_VIDI - platform_driver_unregister(&vidi_driver); out_vidi: + platform_driver_unregister(&vidi_driver); #endif #ifdef CONFIG_DRM_EXYNOS_HDMI - exynos_platform_device_hdmi_unregister(); -out_common_hdmi_dev: platform_driver_unregister(&exynos_drm_common_hdmi_driver); out_common_hdmi: platform_driver_unregister(&mixer_driver); @@ -465,32 +375,13 @@ static void __exit exynos_drm_exit(void) { DRM_DEBUG_DRIVER("%s\n", __FILE__); - platform_device_unregister(exynos_drm_pdev); - platform_driver_unregister(&exynos_drm_platform_driver); -#ifdef CONFIG_DRM_EXYNOS_IPP - platform_driver_unregister(&ipp_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - platform_driver_unregister(&gsc_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - platform_driver_unregister(&rotator_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMC - platform_driver_unregister(&fimc_driver); -#endif - #ifdef CONFIG_DRM_EXYNOS_G2D platform_driver_unregister(&g2d_driver); #endif #ifdef CONFIG_DRM_EXYNOS_HDMI - exynos_platform_device_hdmi_unregister(); platform_driver_unregister(&exynos_drm_common_hdmi_driver); platform_driver_unregister(&mixer_driver); platform_driver_unregister(&hdmi_driver); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h index f5a97745bf93..a34231036496 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -74,6 +74,8 @@ enum exynos_drm_output_type { * @commit: apply hardware specific overlay data to registers. * @enable: enable hardware specific overlay. * @disable: disable hardware specific overlay. + * @wait_for_vblank: wait for vblank interrupt to make sure that + * hardware overlay is disabled. */ struct exynos_drm_overlay_ops { void (*mode_set)(struct device *subdrv_dev, @@ -81,6 +83,7 @@ struct exynos_drm_overlay_ops { void (*commit)(struct device *subdrv_dev, int zpos); void (*enable)(struct device *subdrv_dev, int zpos); void (*disable)(struct device *subdrv_dev, int zpos); + void (*wait_for_vblank)(struct device *subdrv_dev); }; /* @@ -107,6 +110,7 @@ struct exynos_drm_overlay_ops { * @pixel_format: fourcc pixel format of this overlay * @dma_addr: array of bus(accessed by dma) address to the memory region * allocated for a overlay. + * @vaddr: array of virtual memory addresss to this overlay. * @zpos: order of overlay layer(z position). * @default_win: a window to be enabled. * @color_key: color key on or off. @@ -138,6 +142,7 @@ struct exynos_drm_overlay { unsigned int pitch; uint32_t pixel_format; dma_addr_t dma_addr[MAX_FB_BUFFER]; + void __iomem *vaddr[MAX_FB_BUFFER]; int zpos; bool default_win; @@ -181,8 +186,6 @@ struct exynos_drm_display_ops { * @commit: set current hw specific display mode to hw. * @enable_vblank: specific driver callback for enabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt. - * @wait_for_vblank: wait for vblank interrupt to make sure that - * hardware overlay is updated. */ struct exynos_drm_manager_ops { void (*dpms)(struct device *subdrv_dev, int mode); @@ -197,7 +200,6 @@ struct exynos_drm_manager_ops { void (*commit)(struct device *subdrv_dev); int (*enable_vblank)(struct device *subdrv_dev); void (*disable_vblank)(struct device *subdrv_dev); - void (*wait_for_vblank)(struct device *subdrv_dev); }; /* @@ -229,28 +231,16 @@ struct exynos_drm_g2d_private { struct device *dev; struct list_head inuse_cmdlist; struct list_head event_list; - struct list_head userptr_list; -}; - -struct exynos_drm_ipp_private { - struct device *dev; - struct list_head event_list; + struct list_head gem_list; + unsigned int gem_nr; }; struct drm_exynos_file_private { struct exynos_drm_g2d_private *g2d_priv; - struct exynos_drm_ipp_private *ipp_priv; }; /* * Exynos drm private structure. - * - * @da_start: start address to device address space. - * with iommu, device address space starts from this address - * otherwise default one. - * @da_space_size: size of device address space. - * if 0 then default value is used for it. - * @da_space_order: order to device address space. */ struct exynos_drm_private { struct drm_fb_helper *fb_helper; @@ -265,10 +255,6 @@ struct exynos_drm_private { struct drm_crtc *crtc[MAX_CRTC]; struct drm_property *plane_zpos_property; struct drm_property *crtc_mode_property; - - unsigned long da_start; - unsigned long da_space_size; - unsigned long da_space_order; }; /* @@ -332,25 +318,10 @@ int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv); int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); -/* - * this function registers exynos drm hdmi platform device. It ensures only one - * instance of the device is created. - */ -extern int exynos_platform_device_hdmi_register(void); - -/* - * this function unregisters exynos drm hdmi platform device if it exists. - */ -void exynos_platform_device_hdmi_unregister(void); - extern struct platform_driver fimd_driver; extern struct platform_driver hdmi_driver; extern struct platform_driver mixer_driver; extern struct platform_driver exynos_drm_common_hdmi_driver; extern struct platform_driver vidi_driver; extern struct platform_driver g2d_driver; -extern struct platform_driver fimc_driver; -extern struct platform_driver rotator_driver; -extern struct platform_driver gsc_driver; -extern struct platform_driver ipp_driver; #endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 301485215a70..f2df06c603f7 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -234,32 +234,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) exynos_encoder->dpms = DRM_MODE_DPMS_ON; } -void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) -{ - struct exynos_drm_encoder *exynos_encoder; - struct exynos_drm_manager_ops *ops; - struct drm_device *dev = fb->dev; - struct drm_encoder *encoder; - - /* - * make sure that overlay data are updated to real hardware - * for all encoders. - */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - exynos_encoder = to_exynos_encoder(encoder); - ops = exynos_encoder->manager->ops; - - /* - * wait for vblank interrupt - * - this makes sure that overlay data are updated to - * real hardware. - */ - if (ops->wait_for_vblank) - ops->wait_for_vblank(exynos_encoder->manager->dev); - } -} - - static void exynos_drm_encoder_disable(struct drm_encoder *encoder) { struct drm_plane *plane; @@ -531,4 +505,14 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) if (overlay_ops && overlay_ops->disable) overlay_ops->disable(manager->dev, zpos); + + /* + * wait for vblank interrupt + * - this makes sure that hardware overlay is disabled to avoid + * for the dma accesses to memory after gem buffer was released + * because the setting for disabling the overlay will be updated + * at vsync. + */ + if (overlay_ops && overlay_ops->wait_for_vblank) + overlay_ops->wait_for_vblank(manager->dev); } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h index 88bb25a2a917..6470d9ddf5a1 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h @@ -46,6 +46,5 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data); void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data); void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data); void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb); #endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c index 5426cc5a5e8d..4ef4cd3f9936 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -30,13 +30,10 @@ #include #include #include -#include #include "exynos_drm_drv.h" #include "exynos_drm_fb.h" #include "exynos_drm_gem.h" -#include "exynos_drm_iommu.h" -#include "exynos_drm_encoder.h" #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) @@ -53,32 +50,6 @@ struct exynos_drm_fb { struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; }; -static int check_fb_gem_memory_type(struct drm_device *drm_dev, - struct exynos_drm_gem_obj *exynos_gem_obj) -{ - unsigned int flags; - - /* - * if exynos drm driver supports iommu then framebuffer can use - * all the buffer types. - */ - if (is_drm_iommu_supported(drm_dev)) - return 0; - - flags = exynos_gem_obj->flags; - - /* - * without iommu support, not support physically non-continuous memory - * for framebuffer. - */ - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - return -EINVAL; - } - - return 0; -} - static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) { struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); @@ -86,9 +57,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) DRM_DEBUG_KMS("%s\n", __FILE__); - /* make sure that overlay data are updated before relesing fb. */ - exynos_drm_encoder_complete_scanout(fb); - drm_framebuffer_cleanup(fb); for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { @@ -160,32 +128,23 @@ exynos_drm_framebuffer_init(struct drm_device *dev, struct drm_gem_object *obj) { struct exynos_drm_fb *exynos_fb; - struct exynos_drm_gem_obj *exynos_gem_obj; int ret; - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - return ERR_PTR(-EINVAL); - } - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); if (!exynos_fb) { DRM_ERROR("failed to allocate exynos drm framebuffer\n"); return ERR_PTR(-ENOMEM); } - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; - ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { DRM_ERROR("failed to initialize framebuffer\n"); return ERR_PTR(ret); } + drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); + exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); + return &exynos_fb->fb; } @@ -231,8 +190,9 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_gem_object *obj; + struct drm_framebuffer *fb; struct exynos_drm_fb *exynos_fb; - int i, ret; + int i; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -242,56 +202,30 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-ENOENT); } - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); - if (!exynos_fb) { - DRM_ERROR("failed to allocate exynos drm framebuffer\n"); - return ERR_PTR(-ENOMEM); + fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); + if (IS_ERR(fb)) { + drm_gem_object_unreference_unlocked(obj); + return fb; } - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); + exynos_fb = to_exynos_fb(fb); exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); for (i = 1; i < exynos_fb->buf_cnt; i++) { - struct exynos_drm_gem_obj *exynos_gem_obj; - int ret; - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]); if (!obj) { DRM_ERROR("failed to lookup gem object\n"); - kfree(exynos_fb); + exynos_drm_fb_destroy(fb); return ERR_PTR(-ENOENT); } - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - kfree(exynos_fb); - return ERR_PTR(ret); - } - exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); } - ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); - if (ret) { - for (i = 0; i < exynos_fb->buf_cnt; i++) { - struct exynos_drm_gem_obj *gem_obj; - - gem_obj = exynos_fb->exynos_gem_obj[i]; - drm_gem_object_unreference_unlocked(&gem_obj->base); - } - - kfree(exynos_fb); - return ERR_PTR(ret); - } - - return &exynos_fb->fb; + return fb; } struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, @@ -309,7 +243,9 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, if (!buffer) return NULL; - DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr); + DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", + (unsigned long)buffer->kvaddr, + (unsigned long)buffer->dma_addr); return buffer; } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index f433eb7533a9..e7466c4414cb 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -46,38 +46,8 @@ struct exynos_drm_fbdev { struct exynos_drm_gem_obj *exynos_gem_obj; }; -static int exynos_drm_fb_mmap(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct drm_fb_helper *helper = info->par; - struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); - struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; - struct exynos_drm_gem_buf *buffer = exynos_gem_obj->buffer; - unsigned long vm_size; - int ret; - - DRM_DEBUG_KMS("%s\n", __func__); - - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; - - vm_size = vma->vm_end - vma->vm_start; - - if (vm_size > buffer->size) - return -EINVAL; - - ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->pages, - buffer->dma_addr, buffer->size, &buffer->dma_attrs); - if (ret < 0) { - DRM_ERROR("failed to mmap.\n"); - return ret; - } - - return 0; -} - static struct fb_ops exynos_drm_fb_ops = { .owner = THIS_MODULE, - .fb_mmap = exynos_drm_fb_mmap, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, @@ -109,17 +79,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, return -EFAULT; } - /* map pages with kernel virtual space. */ - if (!buffer->kvaddr) { - unsigned int nr_pages = buffer->size >> PAGE_SHIFT; - buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - if (!buffer->kvaddr) { - DRM_ERROR("failed to map pages to kernel space.\n"); - return -EIO; - } - } - /* buffer count to framebuffer always is 1 at booting time. */ exynos_drm_fb_set_buf_cnt(fb, 1); @@ -128,8 +87,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; fbi->screen_base = buffer->kvaddr + offset; - fbi->fix.smem_start = (unsigned long) - (page_to_phys(sg_page(buffer->sgt->sgl)) + offset); + fbi->fix.smem_start = (unsigned long)(page_to_phys(buffer->pages[0]) + + offset); fbi->screen_size = size; fbi->fix.smem_len = size; @@ -175,7 +134,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, exynos_gem_obj = exynos_drm_gem_create(dev, 0, size); if (IS_ERR(exynos_gem_obj)) { ret = PTR_ERR(exynos_gem_obj); - goto err_release_framebuffer; + goto out; } exynos_fbdev->exynos_gem_obj = exynos_gem_obj; @@ -185,7 +144,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, if (IS_ERR_OR_NULL(helper->fb)) { DRM_ERROR("failed to create drm framebuffer.\n"); ret = PTR_ERR(helper->fb); - goto err_destroy_gem; + goto out; } helper->fbdev = fbi; @@ -197,24 +156,14 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) { DRM_ERROR("failed to allocate cmap.\n"); - goto err_destroy_framebuffer; + goto out; } ret = exynos_drm_fbdev_update(helper, helper->fb); - if (ret < 0) - goto err_dealloc_cmap; - - mutex_unlock(&dev->struct_mutex); - return ret; - -err_dealloc_cmap: - fb_dealloc_cmap(&fbi->cmap); -err_destroy_framebuffer: - drm_framebuffer_cleanup(helper->fb); -err_destroy_gem: - exynos_drm_gem_destroy(exynos_gem_obj); -err_release_framebuffer: - framebuffer_release(fbi); + if (ret < 0) { + fb_dealloc_cmap(&fbi->cmap); + goto out; + } /* * if failed, all resources allocated above would be released by @@ -316,13 +265,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev) static void exynos_drm_fbdev_destroy(struct drm_device *dev, struct drm_fb_helper *fb_helper) { - struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper); - struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; struct drm_framebuffer *fb; - if (exynos_gem_obj->buffer->kvaddr) - vunmap(exynos_gem_obj->buffer->kvaddr); - /* release drm framebuffer and real buffer */ if (fb_helper->fb && fb_helper->fb->funcs) { fb = fb_helper->fb; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.c deleted file mode 100644 index 61ea24296b52..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ /dev/null @@ -1,2001 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: - * Eunchul Kim - * Jinyoung Jeon - * Sangmin Lee - * - * 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. - * - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include "regs-fimc.h" -#include "exynos_drm_ipp.h" -#include "exynos_drm_fimc.h" - -/* - * FIMC is stand for Fully Interactive Mobile Camera and - * supports image scaler/rotator and input/output DMA operations. - * input DMA reads image data from the memory. - * output DMA writes image data to memory. - * FIMC supports image rotation and image effect functions. - * - * M2M operation : supports crop/scale/rotation/csc so on. - * Memory ----> FIMC H/W ----> Memory. - * Writeback operation : supports cloned screen with FIMD. - * FIMD ----> FIMC H/W ----> Memory. - * Output operation : supports direct display using local path. - * Memory ----> FIMC H/W ----> FIMD. - */ - -/* - * TODO - * 1. check suspend/resume api if needed. - * 2. need to check use case platform_device_id. - * 3. check src/dst size with, height. - * 4. added check_prepare api for right register. - * 5. need to add supported list in prop_list. - * 6. check prescaler/scaler optimization. - */ - -#define FIMC_MAX_DEVS 4 -#define FIMC_MAX_SRC 2 -#define FIMC_MAX_DST 32 -#define FIMC_SHFACTOR 10 -#define FIMC_BUF_STOP 1 -#define FIMC_BUF_START 2 -#define FIMC_REG_SZ 32 -#define FIMC_WIDTH_ITU_709 1280 -#define FIMC_REFRESH_MAX 60 -#define FIMC_REFRESH_MIN 12 -#define FIMC_CROP_MAX 8192 -#define FIMC_CROP_MIN 32 -#define FIMC_SCALE_MAX 4224 -#define FIMC_SCALE_MIN 32 - -#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev)) -#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\ - struct fimc_context, ippdrv); -#define fimc_read(offset) readl(ctx->regs + (offset)) -#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset)) - -enum fimc_wb { - FIMC_WB_NONE, - FIMC_WB_A, - FIMC_WB_B, -}; - -/* - * A structure of scaler. - * - * @range: narrow, wide. - * @bypass: unused scaler path. - * @up_h: horizontal scale up. - * @up_v: vertical scale up. - * @hratio: horizontal ratio. - * @vratio: vertical ratio. - */ -struct fimc_scaler { - bool range; - bool bypass; - bool up_h; - bool up_v; - u32 hratio; - u32 vratio; -}; - -/* - * A structure of scaler capability. - * - * find user manual table 43-1. - * @in_hori: scaler input horizontal size. - * @bypass: scaler bypass mode. - * @dst_h_wo_rot: target horizontal size without output rotation. - * @dst_h_rot: target horizontal size with output rotation. - * @rl_w_wo_rot: real width without input rotation. - * @rl_h_rot: real height without output rotation. - */ -struct fimc_capability { - /* scaler */ - u32 in_hori; - u32 bypass; - /* output rotator */ - u32 dst_h_wo_rot; - u32 dst_h_rot; - /* input rotator */ - u32 rl_w_wo_rot; - u32 rl_h_rot; -}; - -/* - * A structure of fimc driver data. - * - * @parent_clk: name of parent clock. - */ -struct fimc_driverdata { - char *parent_clk; -}; - -/* - * A structure of fimc context. - * - * @ippdrv: prepare initialization using ippdrv. - * @regs_res: register resources. - * @regs: memory mapped io registers. - * @lock: locking of operations. - * @sclk_fimc_clk: fimc source clock. - * @fimc_clk: fimc clock. - * @wb_clk: writeback a clock. - * @wb_b_clk: writeback b clock. - * @sc: scaler infomations. - * @odr: ordering of YUV. - * @ver: fimc version. - * @pol: porarity of writeback. - * @id: fimc id. - * @irq: irq number. - * @suspended: qos operations. - */ -struct fimc_context { - struct exynos_drm_ippdrv ippdrv; - struct resource *regs_res; - void __iomem *regs; - struct mutex lock; - struct clk *sclk_fimc_clk; - struct clk *fimc_clk; - struct clk *wb_clk; - struct clk *wb_b_clk; - struct fimc_scaler sc; - struct fimc_driverdata *ddata; - struct exynos_drm_ipp_pol pol; - int id; - int irq; - bool suspended; -}; - -static void fimc_sw_reset(struct fimc_context *ctx, bool pattern) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern); - - cfg = fimc_read(EXYNOS_CISRCFMT); - cfg |= EXYNOS_CISRCFMT_ITU601_8BIT; - if (pattern) - cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR; - - fimc_write(cfg, EXYNOS_CISRCFMT); - - /* s/w reset */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= (EXYNOS_CIGCTRL_SWRST); - fimc_write(cfg, EXYNOS_CIGCTRL); - - /* s/w reset complete */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~EXYNOS_CIGCTRL_SWRST; - fimc_write(cfg, EXYNOS_CIGCTRL); - - /* reset sequence */ - fimc_write(0x0, EXYNOS_CIFCNTSEQ); -} - -static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) -{ - u32 camblk_cfg; - - DRM_DEBUG_KMS("%s\n", __func__); - - camblk_cfg = readl(SYSREG_CAMERA_BLK); - camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK); - camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT); - - writel(camblk_cfg, SYSREG_CAMERA_BLK); -} - -static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK | - EXYNOS_CIGCTRL_SELCAM_ITU_MASK | - EXYNOS_CIGCTRL_SELCAM_MIPI_MASK | - EXYNOS_CIGCTRL_SELCAM_FIMC_MASK | - EXYNOS_CIGCTRL_SELWB_CAMIF_MASK | - EXYNOS_CIGCTRL_SELWRITEBACK_MASK); - - switch (wb) { - case FIMC_WB_A: - cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A | - EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK); - break; - case FIMC_WB_B: - cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B | - EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK); - break; - case FIMC_WB_NONE: - default: - cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A | - EXYNOS_CIGCTRL_SELWRITEBACK_A | - EXYNOS_CIGCTRL_SELCAM_MIPI_A | - EXYNOS_CIGCTRL_SELCAM_FIMC_ITU); - break; - } - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_set_polarity(struct fimc_context *ctx, - struct exynos_drm_ipp_pol *pol) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n", - __func__, pol->inv_pclk, pol->inv_vsync); - DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n", - __func__, pol->inv_href, pol->inv_hsync); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC | - EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC); - - if (pol->inv_pclk) - cfg |= EXYNOS_CIGCTRL_INVPOLPCLK; - if (pol->inv_vsync) - cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC; - if (pol->inv_href) - cfg |= EXYNOS_CIGCTRL_INVPOLHREF; - if (pol->inv_hsync) - cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC; - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - cfg = fimc_read(EXYNOS_CIGCTRL); - if (enable) - cfg |= EXYNOS_CIGCTRL_CAM_JPEG; - else - cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG; - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_handle_irq(struct fimc_context *ctx, bool enable, - bool overflow, bool level) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__, - enable, overflow, level); - - cfg = fimc_read(EXYNOS_CIGCTRL); - if (enable) { - cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL); - cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE; - if (overflow) - cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN; - if (level) - cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL; - } else - cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE); - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_clear_irq(struct fimc_context *ctx) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s\n", __func__); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= EXYNOS_CIGCTRL_IRQ_CLR; - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static bool fimc_check_ovf(struct fimc_context *ctx) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg, status, flag; - - status = fimc_read(EXYNOS_CISTATUS); - flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB | - EXYNOS_CISTATUS_OVFICR; - - DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag); - - if (status & flag) { - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | - EXYNOS_CIWDOFST_CLROVFICR); - - fimc_write(cfg, EXYNOS_CIWDOFST); - - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | - EXYNOS_CIWDOFST_CLROVFICR); - - fimc_write(cfg, EXYNOS_CIWDOFST); - - dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n", - ctx->id, status); - return true; - } - - return false; -} - -static bool fimc_check_frame_end(struct fimc_context *ctx) -{ - u32 cfg; - - cfg = fimc_read(EXYNOS_CISTATUS); - - DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg); - - if (!(cfg & EXYNOS_CISTATUS_FRAMEEND)) - return false; - - cfg &= ~(EXYNOS_CISTATUS_FRAMEEND); - fimc_write(cfg, EXYNOS_CISTATUS); - - return true; -} - -static int fimc_get_buf_id(struct fimc_context *ctx) -{ - u32 cfg; - int frame_cnt, buf_id; - - DRM_DEBUG_KMS("%s\n", __func__); - - cfg = fimc_read(EXYNOS_CISTATUS2); - frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg); - - if (frame_cnt == 0) - frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg); - - DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__, - EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg), - EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg)); - - if (frame_cnt == 0) { - DRM_ERROR("failed to get frame count.\n"); - return -EIO; - } - - buf_id = frame_cnt - 1; - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - return buf_id; -} - -static void fimc_handle_lastend(struct fimc_context *ctx, bool enable) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - cfg = fimc_read(EXYNOS_CIOCTRL); - if (enable) - cfg |= EXYNOS_CIOCTRL_LASTENDEN; - else - cfg &= ~EXYNOS_CIOCTRL_LASTENDEN; - - fimc_write(cfg, EXYNOS_CIOCTRL); -} - - -static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - /* RGB */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - default: - /* bypass */ - break; - } - - /* YUV */ - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK | - EXYNOS_MSCTRL_C_INT_IN_2PLANE | - EXYNOS_MSCTRL_ORDER422_YCBYCR); - - switch (fmt) { - case DRM_FORMAT_YUYV: - cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR; - break; - case DRM_FORMAT_YVYU: - cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB; - break; - case DRM_FORMAT_UYVY: - cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY; - break; - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUV444: - cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY; - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB | - EXYNOS_MSCTRL_C_INT_IN_2PLANE); - break; - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV16: - cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | - EXYNOS_MSCTRL_C_INT_IN_2PLANE); - break; - default: - dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_MSCTRL); - - return 0; -} - -static int fimc_src_set_fmt(struct device *dev, u32 fmt) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB; - - switch (fmt) { - case DRM_FORMAT_RGB565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_MSCTRL_INFORMAT_RGB; - break; - case DRM_FORMAT_YUV444: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; - break; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE; - break; - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422; - break; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV12MT: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; - break; - default: - dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_MSCTRL); - - cfg = fimc_read(EXYNOS_CIDMAPARAM); - cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; - - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; - - fimc_write(cfg, EXYNOS_CIDMAPARAM); - - return fimc_src_set_fmt_order(ctx, fmt); -} - -static int fimc_src_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip, bool *swap) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg1, cfg2; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg1 = fimc_read(EXYNOS_MSCTRL); - cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - - cfg2 = fimc_read(EXYNOS_CITRGFMT); - cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_90: - cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_180: - cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_270: - cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - fimc_write(cfg1, EXYNOS_MSCTRL); - fimc_write(cfg2, EXYNOS_CITRGFMT); - *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0; - - return 0; -} - -static int fimc_set_window(struct fimc_context *ctx, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - u32 cfg, h1, h2, v1, v2; - - /* cropped image */ - h1 = pos->x; - h2 = sz->hsize - pos->w - pos->x; - v1 = pos->y; - v2 = sz->vsize - pos->h - pos->y; - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", - __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize); - DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__, - h1, h2, v1, v2); - - /* - * set window offset 1, 2 size - * check figure 43-21 in user manual - */ - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK | - EXYNOS_CIWDOFST_WINVEROFST_MASK); - cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) | - EXYNOS_CIWDOFST_WINVEROFST(v1)); - cfg |= EXYNOS_CIWDOFST_WINOFSEN; - fimc_write(cfg, EXYNOS_CIWDOFST); - - cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) | - EXYNOS_CIWDOFST2_WINVEROFST2(v2)); - fimc_write(cfg, EXYNOS_CIWDOFST2); - - return 0; -} - -static int fimc_src_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - u32 cfg; - - DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n", - __func__, swap, sz->hsize, sz->vsize); - - /* original size */ - cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) | - EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize)); - - fimc_write(cfg, EXYNOS_ORGISIZE); - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__, - pos->x, pos->y, pos->w, pos->h); - - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - /* set input DMA image size */ - cfg = fimc_read(EXYNOS_CIREAL_ISIZE); - cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK | - EXYNOS_CIREAL_ISIZE_WIDTH_MASK); - cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) | - EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h)); - fimc_write(cfg, EXYNOS_CIREAL_ISIZE); - - /* - * set input FIFO image size - * for now, we support only ITU601 8 bit mode - */ - cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | - EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) | - EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize)); - fimc_write(cfg, EXYNOS_CISRCFMT); - - /* offset Y(RGB), Cb, Cr */ - cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIIYOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIIYOFF); - cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIICBOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIICBOFF); - cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIICROFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIICROFF); - - return fimc_set_window(ctx, &img_pos, &img_sz); -} - -static int fimc_src_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_type buf_type) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd; - struct drm_exynos_ipp_property *property; - struct drm_exynos_ipp_config *config; - - if (!c_node) { - DRM_ERROR("failed to get c_node.\n"); - return -EINVAL; - } - - property = &c_node->property; - if (!property) { - DRM_ERROR("failed to get property.\n"); - return -EINVAL; - } - - DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__, - property->prop_id, buf_id, buf_type); - - if (buf_id > FIMC_MAX_SRC) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_type) { - case IPP_BUF_ENQUEUE: - config = &property->config[EXYNOS_DRM_OPS_SRC]; - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - EXYNOS_CIIYSA(buf_id)); - - if (config->fmt == DRM_FORMAT_YVU420) { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICRSA(buf_id)); - } else { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICRSA(buf_id)); - } - break; - case IPP_BUF_DEQUEUE: - fimc_write(0x0, EXYNOS_CIIYSA(buf_id)); - fimc_write(0x0, EXYNOS_CIICBSA(buf_id)); - fimc_write(0x0, EXYNOS_CIICRSA(buf_id)); - break; - default: - /* bypass */ - break; - } - - return 0; -} - -static struct exynos_drm_ipp_ops fimc_src_ops = { - .set_fmt = fimc_src_set_fmt, - .set_transf = fimc_src_set_transf, - .set_size = fimc_src_set_size, - .set_addr = fimc_src_set_addr, -}; - -static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - /* RGB */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_RGB888: - cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_XRGB8888: - cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 | - EXYNOS_CISCCTRL_EXTRGB_EXTENSION); - fimc_write(cfg, EXYNOS_CISCCTRL); - break; - default: - /* bypass */ - break; - } - - /* YUV */ - cfg = fimc_read(EXYNOS_CIOCTRL); - cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK | - EXYNOS_CIOCTRL_ORDER422_MASK | - EXYNOS_CIOCTRL_YCBCR_PLANE_MASK); - - switch (fmt) { - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CIOCTRL_ALPHA_OUT; - break; - case DRM_FORMAT_YUYV: - cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR; - break; - case DRM_FORMAT_YVYU: - cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB; - break; - case DRM_FORMAT_UYVY: - cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY; - break; - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY; - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB; - cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; - break; - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV16: - cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; - cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; - break; - default: - dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CIOCTRL); - - return 0; -} - -static int fimc_dst_set_fmt(struct device *dev, u32 fmt) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = fimc_read(EXYNOS_CIEXTEN); - - if (fmt == DRM_FORMAT_AYUV) { - cfg |= EXYNOS_CIEXTEN_YUV444_OUT; - fimc_write(cfg, EXYNOS_CIEXTEN); - } else { - cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT; - fimc_write(cfg, EXYNOS_CIEXTEN); - - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB; - break; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE; - break; - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422; - break; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV21: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; - break; - default: - dev_err(ippdrv->dev, "inavlid target format 0x%x.\n", - fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CITRGFMT); - } - - cfg = fimc_read(EXYNOS_CIDMAPARAM); - cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; - - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; - - fimc_write(cfg, EXYNOS_CIDMAPARAM); - - return fimc_dst_set_fmt_order(ctx, fmt); -} - -static int fimc_dst_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip, bool *swap) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK; - cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_90: - cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_180: - cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR | - EXYNOS_CITRGFMT_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_270: - cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE | - EXYNOS_CITRGFMT_FLIP_X_MIRROR | - EXYNOS_CITRGFMT_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CITRGFMT); - *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0; - - return 0; -} - -static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift) -{ - DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst); - - if (src >= dst * 64) { - DRM_ERROR("failed to make ratio and shift.\n"); - return -EINVAL; - } else if (src >= dst * 32) { - *ratio = 32; - *shift = 5; - } else if (src >= dst * 16) { - *ratio = 16; - *shift = 4; - } else if (src >= dst * 8) { - *ratio = 8; - *shift = 3; - } else if (src >= dst * 4) { - *ratio = 4; - *shift = 2; - } else if (src >= dst * 2) { - *ratio = 2; - *shift = 1; - } else { - *ratio = 1; - *shift = 0; - } - - return 0; -} - -static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc, - struct drm_exynos_pos *src, struct drm_exynos_pos *dst) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg, cfg_ext, shfactor; - u32 pre_dst_width, pre_dst_height; - u32 pre_hratio, hfactor, pre_vratio, vfactor; - int ret = 0; - u32 src_w, src_h, dst_w, dst_h; - - cfg_ext = fimc_read(EXYNOS_CITRGFMT); - if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) { - src_w = src->h; - src_h = src->w; - } else { - src_w = src->w; - src_h = src->h; - } - - if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) { - dst_w = dst->h; - dst_h = dst->w; - } else { - dst_w = dst->w; - dst_h = dst->h; - } - - ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio horizontal.\n"); - return ret; - } - - ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio vertical.\n"); - return ret; - } - - pre_dst_width = src_w / pre_hratio; - pre_dst_height = src_h / pre_vratio; - DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__, - pre_dst_width, pre_dst_height); - DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n", - __func__, pre_hratio, hfactor, pre_vratio, vfactor); - - sc->hratio = (src_w << 14) / (dst_w << hfactor); - sc->vratio = (src_h << 14) / (dst_h << vfactor); - sc->up_h = (dst_w >= src_w) ? true : false; - sc->up_v = (dst_h >= src_h) ? true : false; - DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n", - __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v); - - shfactor = FIMC_SHFACTOR - (hfactor + vfactor); - DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor); - - cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) | - EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) | - EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio)); - fimc_write(cfg, EXYNOS_CISCPRERATIO); - - cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) | - EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height)); - fimc_write(cfg, EXYNOS_CISCPREDST); - - return ret; -} - -static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc) -{ - u32 cfg, cfg_ext; - - DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n", - __func__, sc->range, sc->bypass, sc->up_h, sc->up_v); - DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n", - __func__, sc->hratio, sc->vratio); - - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS | - EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V | - EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK | - EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK | - EXYNOS_CISCCTRL_CSCR2Y_WIDE | - EXYNOS_CISCCTRL_CSCY2R_WIDE); - - if (sc->range) - cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE | - EXYNOS_CISCCTRL_CSCY2R_WIDE); - if (sc->bypass) - cfg |= EXYNOS_CISCCTRL_SCALERBYPASS; - if (sc->up_h) - cfg |= EXYNOS_CISCCTRL_SCALEUP_H; - if (sc->up_v) - cfg |= EXYNOS_CISCCTRL_SCALEUP_V; - - cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) | - EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6))); - fimc_write(cfg, EXYNOS_CISCCTRL); - - cfg_ext = fimc_read(EXYNOS_CIEXTEN); - cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK; - cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK; - cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) | - EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio)); - fimc_write(cfg_ext, EXYNOS_CIEXTEN); -} - -static int fimc_dst_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - u32 cfg; - - DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n", - __func__, swap, sz->hsize, sz->vsize); - - /* original size */ - cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) | - EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize)); - - fimc_write(cfg, EXYNOS_ORGOSIZE); - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", - __func__, pos->x, pos->y, pos->w, pos->h); - - /* CSC ITU */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~EXYNOS_CIGCTRL_CSC_MASK; - - if (sz->hsize >= FIMC_WIDTH_ITU_709) - cfg |= EXYNOS_CIGCTRL_CSC_ITU709; - else - cfg |= EXYNOS_CIGCTRL_CSC_ITU601; - - fimc_write(cfg, EXYNOS_CIGCTRL); - - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - /* target image size */ - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK | - EXYNOS_CITRGFMT_TARGETV_MASK); - cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) | - EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h)); - fimc_write(cfg, EXYNOS_CITRGFMT); - - /* target area */ - cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h); - fimc_write(cfg, EXYNOS_CITAREA); - - /* offset Y(RGB), Cb, Cr */ - cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOYOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOYOFF); - cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOCBOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOCBOFF); - cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOCROFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOCROFF); - - return 0; -} - -static int fimc_dst_get_buf_seq(struct fimc_context *ctx) -{ - u32 cfg, i, buf_num = 0; - u32 mask = 0x00000001; - - cfg = fimc_read(EXYNOS_CIFCNTSEQ); - - for (i = 0; i < FIMC_REG_SZ; i++) - if (cfg & (mask << i)) - buf_num++; - - DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num); - - return buf_num; -} - -static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, - enum drm_exynos_ipp_buf_type buf_type) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - bool enable; - u32 cfg; - u32 mask = 0x00000001 << buf_id; - int ret = 0; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__, - buf_id, buf_type); - - mutex_lock(&ctx->lock); - - /* mask register set */ - cfg = fimc_read(EXYNOS_CIFCNTSEQ); - - switch (buf_type) { - case IPP_BUF_ENQUEUE: - enable = true; - break; - case IPP_BUF_DEQUEUE: - enable = false; - break; - default: - dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); - ret = -EINVAL; - goto err_unlock; - } - - /* sequence id */ - cfg &= (~mask); - cfg |= (enable << buf_id); - fimc_write(cfg, EXYNOS_CIFCNTSEQ); - - /* interrupt enable */ - if (buf_type == IPP_BUF_ENQUEUE && - fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START) - fimc_handle_irq(ctx, true, false, true); - - /* interrupt disable */ - if (buf_type == IPP_BUF_DEQUEUE && - fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP) - fimc_handle_irq(ctx, false, false, true); - -err_unlock: - mutex_unlock(&ctx->lock); - return ret; -} - -static int fimc_dst_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_type buf_type) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd; - struct drm_exynos_ipp_property *property; - struct drm_exynos_ipp_config *config; - - if (!c_node) { - DRM_ERROR("failed to get c_node.\n"); - return -EINVAL; - } - - property = &c_node->property; - if (!property) { - DRM_ERROR("failed to get property.\n"); - return -EINVAL; - } - - DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__, - property->prop_id, buf_id, buf_type); - - if (buf_id > FIMC_MAX_DST) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_type) { - case IPP_BUF_ENQUEUE: - config = &property->config[EXYNOS_DRM_OPS_DST]; - - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - EXYNOS_CIOYSA(buf_id)); - - if (config->fmt == DRM_FORMAT_YVU420) { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIOCBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIOCRSA(buf_id)); - } else { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIOCBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIOCRSA(buf_id)); - } - break; - case IPP_BUF_DEQUEUE: - fimc_write(0x0, EXYNOS_CIOYSA(buf_id)); - fimc_write(0x0, EXYNOS_CIOCBSA(buf_id)); - fimc_write(0x0, EXYNOS_CIOCRSA(buf_id)); - break; - default: - /* bypass */ - break; - } - - return fimc_dst_set_buf_seq(ctx, buf_id, buf_type); -} - -static struct exynos_drm_ipp_ops fimc_dst_ops = { - .set_fmt = fimc_dst_set_fmt, - .set_transf = fimc_dst_set_transf, - .set_size = fimc_dst_set_size, - .set_addr = fimc_dst_set_addr, -}; - -static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable) -{ - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - if (enable) { - clk_enable(ctx->sclk_fimc_clk); - clk_enable(ctx->fimc_clk); - clk_enable(ctx->wb_clk); - ctx->suspended = false; - } else { - clk_disable(ctx->sclk_fimc_clk); - clk_disable(ctx->fimc_clk); - clk_disable(ctx->wb_clk); - ctx->suspended = true; - } - - return 0; -} - -static irqreturn_t fimc_irq_handler(int irq, void *dev_id) -{ - struct fimc_context *ctx = dev_id; - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd; - struct drm_exynos_ipp_event_work *event_work = - c_node->event_work; - int buf_id; - - DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id); - - fimc_clear_irq(ctx); - if (fimc_check_ovf(ctx)) - return IRQ_NONE; - - if (!fimc_check_frame_end(ctx)) - return IRQ_NONE; - - buf_id = fimc_get_buf_id(ctx); - if (buf_id < 0) - return IRQ_HANDLED; - - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) { - DRM_ERROR("failed to dequeue.\n"); - return IRQ_HANDLED; - } - - event_work->ippdrv = ippdrv; - event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id; - queue_work(ippdrv->event_workq, (struct work_struct *)event_work); - - return IRQ_HANDLED; -} - -static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv) -{ - struct drm_exynos_ipp_prop_list *prop_list; - - DRM_DEBUG_KMS("%s\n", __func__); - - prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL); - if (!prop_list) { - DRM_ERROR("failed to alloc property list.\n"); - return -ENOMEM; - } - - prop_list->version = 1; - prop_list->writeback = 1; - prop_list->refresh_min = FIMC_REFRESH_MIN; - prop_list->refresh_max = FIMC_REFRESH_MAX; - prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) | - (1 << EXYNOS_DRM_FLIP_VERTICAL) | - (1 << EXYNOS_DRM_FLIP_HORIZONTAL); - prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) | - (1 << EXYNOS_DRM_DEGREE_90) | - (1 << EXYNOS_DRM_DEGREE_180) | - (1 << EXYNOS_DRM_DEGREE_270); - prop_list->csc = 1; - prop_list->crop = 1; - prop_list->crop_max.hsize = FIMC_CROP_MAX; - prop_list->crop_max.vsize = FIMC_CROP_MAX; - prop_list->crop_min.hsize = FIMC_CROP_MIN; - prop_list->crop_min.vsize = FIMC_CROP_MIN; - prop_list->scale = 1; - prop_list->scale_max.hsize = FIMC_SCALE_MAX; - prop_list->scale_max.vsize = FIMC_SCALE_MAX; - prop_list->scale_min.hsize = FIMC_SCALE_MIN; - prop_list->scale_min.vsize = FIMC_SCALE_MIN; - - ippdrv->prop_list = prop_list; - - return 0; -} - -static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip) -{ - switch (flip) { - case EXYNOS_DRM_FLIP_NONE: - case EXYNOS_DRM_FLIP_VERTICAL: - case EXYNOS_DRM_FLIP_HORIZONTAL: - return true; - default: - DRM_DEBUG_KMS("%s:invalid flip\n", __func__); - return false; - } -} - -static int fimc_ippdrv_check_property(struct device *dev, - struct drm_exynos_ipp_property *property) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list; - struct drm_exynos_ipp_config *config; - struct drm_exynos_pos *pos; - struct drm_exynos_sz *sz; - bool swap; - int i; - - DRM_DEBUG_KMS("%s\n", __func__); - - for_each_ipp_ops(i) { - if ((i == EXYNOS_DRM_OPS_SRC) && - (property->cmd == IPP_CMD_WB)) - continue; - - config = &property->config[i]; - pos = &config->pos; - sz = &config->sz; - - /* check for flip */ - if (!fimc_check_drm_flip(config->flip)) { - DRM_ERROR("invalid flip.\n"); - goto err_property; - } - - /* check for degree */ - switch (config->degree) { - case EXYNOS_DRM_DEGREE_90: - case EXYNOS_DRM_DEGREE_270: - swap = true; - break; - case EXYNOS_DRM_DEGREE_0: - case EXYNOS_DRM_DEGREE_180: - swap = false; - break; - default: - DRM_ERROR("invalid degree.\n"); - goto err_property; - } - - /* check for buffer bound */ - if ((pos->x + pos->w > sz->hsize) || - (pos->y + pos->h > sz->vsize)) { - DRM_ERROR("out of buf bound.\n"); - goto err_property; - } - - /* check for crop */ - if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) { - if (swap) { - if ((pos->h < pp->crop_min.hsize) || - (sz->vsize > pp->crop_max.hsize) || - (pos->w < pp->crop_min.vsize) || - (sz->hsize > pp->crop_max.vsize)) { - DRM_ERROR("out of crop size.\n"); - goto err_property; - } - } else { - if ((pos->w < pp->crop_min.hsize) || - (sz->hsize > pp->crop_max.hsize) || - (pos->h < pp->crop_min.vsize) || - (sz->vsize > pp->crop_max.vsize)) { - DRM_ERROR("out of crop size.\n"); - goto err_property; - } - } - } - - /* check for scale */ - if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) { - if (swap) { - if ((pos->h < pp->scale_min.hsize) || - (sz->vsize > pp->scale_max.hsize) || - (pos->w < pp->scale_min.vsize) || - (sz->hsize > pp->scale_max.vsize)) { - DRM_ERROR("out of scale size.\n"); - goto err_property; - } - } else { - if ((pos->w < pp->scale_min.hsize) || - (sz->hsize > pp->scale_max.hsize) || - (pos->h < pp->scale_min.vsize) || - (sz->vsize > pp->scale_max.vsize)) { - DRM_ERROR("out of scale size.\n"); - goto err_property; - } - } - } - } - - return 0; - -err_property: - for_each_ipp_ops(i) { - if ((i == EXYNOS_DRM_OPS_SRC) && - (property->cmd == IPP_CMD_WB)) - continue; - - config = &property->config[i]; - pos = &config->pos; - sz = &config->sz; - - DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n", - i ? "dst" : "src", config->flip, config->degree, - pos->x, pos->y, pos->w, pos->h, - sz->hsize, sz->vsize); - } - - return -EINVAL; -} - -static void fimc_clear_addr(struct fimc_context *ctx) -{ - int i; - - DRM_DEBUG_KMS("%s:\n", __func__); - - for (i = 0; i < FIMC_MAX_SRC; i++) { - fimc_write(0, EXYNOS_CIIYSA(i)); - fimc_write(0, EXYNOS_CIICBSA(i)); - fimc_write(0, EXYNOS_CIICRSA(i)); - } - - for (i = 0; i < FIMC_MAX_DST; i++) { - fimc_write(0, EXYNOS_CIOYSA(i)); - fimc_write(0, EXYNOS_CIOCBSA(i)); - fimc_write(0, EXYNOS_CIOCRSA(i)); - } -} - -static int fimc_ippdrv_reset(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s\n", __func__); - - /* reset h/w block */ - fimc_sw_reset(ctx, false); - - /* reset scaler capability */ - memset(&ctx->sc, 0x0, sizeof(ctx->sc)); - - fimc_clear_addr(ctx); - - return 0; -} - -static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd; - struct drm_exynos_ipp_property *property; - struct drm_exynos_ipp_config *config; - struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX]; - struct drm_exynos_ipp_set_wb set_wb; - int ret, i; - u32 cfg0, cfg1; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - if (!c_node) { - DRM_ERROR("failed to get c_node.\n"); - return -EINVAL; - } - - property = &c_node->property; - if (!property) { - DRM_ERROR("failed to get property.\n"); - return -EINVAL; - } - - fimc_handle_irq(ctx, true, false, true); - - for_each_ipp_ops(i) { - config = &property->config[i]; - img_pos[i] = config->pos; - } - - ret = fimc_set_prescaler(ctx, &ctx->sc, - &img_pos[EXYNOS_DRM_OPS_SRC], - &img_pos[EXYNOS_DRM_OPS_DST]); - if (ret) { - dev_err(dev, "failed to set precalser.\n"); - return ret; - } - - /* If set ture, we can save jpeg about screen */ - fimc_handle_jpeg(ctx, false); - fimc_set_scaler(ctx, &ctx->sc); - fimc_set_polarity(ctx, &ctx->pol); - - switch (cmd) { - case IPP_CMD_M2M: - fimc_set_type_ctrl(ctx, FIMC_WB_NONE); - fimc_handle_lastend(ctx, false); - - /* setup dma */ - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK; - cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY; - fimc_write(cfg0, EXYNOS_MSCTRL); - break; - case IPP_CMD_WB: - fimc_set_type_ctrl(ctx, FIMC_WB_A); - fimc_handle_lastend(ctx, true); - - /* setup FIMD */ - fimc_set_camblk_fimd0_wb(ctx); - - set_wb.enable = 1; - set_wb.refresh = property->refresh_rate; - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb); - break; - case IPP_CMD_OUTPUT: - default: - ret = -EINVAL; - dev_err(dev, "invalid operations.\n"); - return ret; - } - - /* Reset status */ - fimc_write(0x0, EXYNOS_CISTATUS); - - cfg0 = fimc_read(EXYNOS_CIIMGCPT); - cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC; - cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC; - - /* Scaler */ - cfg1 = fimc_read(EXYNOS_CISCCTRL); - cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK; - cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE | - EXYNOS_CISCCTRL_SCALERSTART); - - fimc_write(cfg1, EXYNOS_CISCCTRL); - - /* Enable image capture*/ - cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN; - fimc_write(cfg0, EXYNOS_CIIMGCPT); - - /* Disable frame end irq */ - cfg0 = fimc_read(EXYNOS_CIGCTRL); - cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE; - fimc_write(cfg0, EXYNOS_CIGCTRL); - - cfg0 = fimc_read(EXYNOS_CIOCTRL); - cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK; - fimc_write(cfg0, EXYNOS_CIOCTRL); - - if (cmd == IPP_CMD_M2M) { - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 |= EXYNOS_MSCTRL_ENVID; - fimc_write(cfg0, EXYNOS_MSCTRL); - - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 |= EXYNOS_MSCTRL_ENVID; - fimc_write(cfg0, EXYNOS_MSCTRL); - } - - return 0; -} - -static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct drm_exynos_ipp_set_wb set_wb = {0, 0}; - u32 cfg; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - switch (cmd) { - case IPP_CMD_M2M: - /* Source clear */ - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~EXYNOS_MSCTRL_INPUT_MASK; - cfg &= ~EXYNOS_MSCTRL_ENVID; - fimc_write(cfg, EXYNOS_MSCTRL); - break; - case IPP_CMD_WB: - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb); - break; - case IPP_CMD_OUTPUT: - default: - dev_err(dev, "invalid operations.\n"); - break; - } - - fimc_handle_irq(ctx, false, false, true); - - /* reset sequence */ - fimc_write(0x0, EXYNOS_CIFCNTSEQ); - - /* Scaler disable */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_SCALERSTART; - fimc_write(cfg, EXYNOS_CISCCTRL); - - /* Disable image capture */ - cfg = fimc_read(EXYNOS_CIIMGCPT); - cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); - fimc_write(cfg, EXYNOS_CIIMGCPT); - - /* Enable frame end irq */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE; - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static int __devinit fimc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_context *ctx; - struct clk *parent_clk; - struct resource *res; - struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_fimc_pdata *pdata; - struct fimc_driverdata *ddata; - int ret; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data specified.\n"); - return -EINVAL; - } - - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ddata = (struct fimc_driverdata *) - platform_get_device_id(pdev)->driver_data; - - /* clock control */ - ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc"); - if (IS_ERR(ctx->sclk_fimc_clk)) { - dev_err(dev, "failed to get src fimc clock.\n"); - ret = PTR_ERR(ctx->sclk_fimc_clk); - goto err_ctx; - } - clk_enable(ctx->sclk_fimc_clk); - - ctx->fimc_clk = clk_get(dev, "fimc"); - if (IS_ERR(ctx->fimc_clk)) { - dev_err(dev, "failed to get fimc clock.\n"); - ret = PTR_ERR(ctx->fimc_clk); - clk_disable(ctx->sclk_fimc_clk); - clk_put(ctx->sclk_fimc_clk); - goto err_ctx; - } - - ctx->wb_clk = clk_get(dev, "pxl_async0"); - if (IS_ERR(ctx->wb_clk)) { - dev_err(dev, "failed to get writeback a clock.\n"); - ret = PTR_ERR(ctx->wb_clk); - clk_disable(ctx->sclk_fimc_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - goto err_ctx; - } - - ctx->wb_b_clk = clk_get(dev, "pxl_async1"); - if (IS_ERR(ctx->wb_b_clk)) { - dev_err(dev, "failed to get writeback b clock.\n"); - ret = PTR_ERR(ctx->wb_b_clk); - clk_disable(ctx->sclk_fimc_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - goto err_ctx; - } - - parent_clk = clk_get(dev, ddata->parent_clk); - - if (IS_ERR(parent_clk)) { - dev_err(dev, "failed to get parent clock.\n"); - ret = PTR_ERR(parent_clk); - clk_disable(ctx->sclk_fimc_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - goto err_ctx; - } - - if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) { - dev_err(dev, "failed to set parent.\n"); - ret = -EINVAL; - clk_put(parent_clk); - clk_disable(ctx->sclk_fimc_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - goto err_ctx; - } - - clk_put(parent_clk); - clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate); - - /* resource memory */ - ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!ctx->regs_res) { - dev_err(dev, "failed to find registers.\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res); - if (!ctx->regs) { - dev_err(dev, "failed to map registers.\n"); - ret = -ENXIO; - goto err_clk; - } - - /* resource irq */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "failed to request irq resource.\n"); - ret = -ENOENT; - goto err_get_regs; - } - - ctx->irq = res->start; - ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler, - IRQF_ONESHOT, "drm_fimc", ctx); - if (ret < 0) { - dev_err(dev, "failed to request irq.\n"); - goto err_get_regs; - } - - /* context initailization */ - ctx->id = pdev->id; - ctx->pol = pdata->pol; - ctx->ddata = ddata; - - ippdrv = &ctx->ippdrv; - ippdrv->dev = dev; - ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops; - ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops; - ippdrv->check_property = fimc_ippdrv_check_property; - ippdrv->reset = fimc_ippdrv_reset; - ippdrv->start = fimc_ippdrv_start; - ippdrv->stop = fimc_ippdrv_stop; - ret = fimc_init_prop_list(ippdrv); - if (ret < 0) { - dev_err(dev, "failed to init property list.\n"); - goto err_get_irq; - } - - DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id, - (int)ippdrv); - - mutex_init(&ctx->lock); - platform_set_drvdata(pdev, ctx); - - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - ret = exynos_drm_ippdrv_register(ippdrv); - if (ret < 0) { - dev_err(dev, "failed to register drm fimc device.\n"); - goto err_ippdrv_register; - } - - dev_info(&pdev->dev, "drm fimc registered successfully.\n"); - - return 0; - -err_ippdrv_register: - devm_kfree(dev, ippdrv->prop_list); - pm_runtime_disable(dev); -err_get_irq: - free_irq(ctx->irq, ctx); -err_get_regs: - devm_iounmap(dev, ctx->regs); -err_clk: - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); -err_ctx: - devm_kfree(dev, ctx); - return ret; -} - -static int __devexit fimc_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - - devm_kfree(dev, ippdrv->prop_list); - exynos_drm_ippdrv_unregister(ippdrv); - mutex_destroy(&ctx->lock); - - pm_runtime_set_suspended(dev); - pm_runtime_disable(dev); - - free_irq(ctx->irq, ctx); - devm_iounmap(dev, ctx->regs); - - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - - devm_kfree(dev, ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int fimc_suspend(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - if (pm_runtime_suspended(dev)) - return 0; - - return fimc_clk_ctrl(ctx, false); -} - -static int fimc_resume(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - if (!pm_runtime_suspended(dev)) - return fimc_clk_ctrl(ctx, true); - - return 0; -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int fimc_runtime_suspend(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - return fimc_clk_ctrl(ctx, false); -} - -static int fimc_runtime_resume(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - return fimc_clk_ctrl(ctx, true); -} -#endif - -static struct fimc_driverdata exynos4210_fimc_data = { - .parent_clk = "mout_mpll", -}; - -static struct fimc_driverdata exynos4410_fimc_data = { - .parent_clk = "mout_mpll_user", -}; - -static struct platform_device_id fimc_driver_ids[] = { - { - .name = "exynos4210-fimc", - .driver_data = (unsigned long)&exynos4210_fimc_data, - }, { - .name = "exynos4412-fimc", - .driver_data = (unsigned long)&exynos4410_fimc_data, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, fimc_driver_ids); - -static const struct dev_pm_ops fimc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume) - SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) -}; - -struct platform_driver fimc_driver = { - .probe = fimc_probe, - .remove = __devexit_p(fimc_remove), - .id_table = fimc_driver_ids, - .driver = { - .name = "exynos-drm-fimc", - .owner = THIS_MODULE, - .pm = &fimc_pm_ops, - }, -}; - diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.h deleted file mode 100644 index dc970fa0d888..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * - * Authors: - * Eunchul Kim - * Jinyoung Jeon - * Sangmin Lee - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (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 (including the next - * paragraph) 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 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 _EXYNOS_DRM_FIMC_H_ -#define _EXYNOS_DRM_FIMC_H_ - -/* - * TODO - * FIMD output interface notifier callback. - */ - -#endif /* _EXYNOS_DRM_FIMC_H_ */ diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c index bf0d9baca2bc..e08478f19f1a 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include