diff options
1452 files changed, 64787 insertions, 19147 deletions
diff --git a/Documentation/RCU/00-INDEX b/Documentation/RCU/00-INDEX index 461481dfb7c3..7dc0695a8f90 100644 --- a/Documentation/RCU/00-INDEX +++ b/Documentation/RCU/00-INDEX @@ -16,6 +16,8 @@ RTFP.txt - List of RCU papers (bibliography) going back to 1980. torture.txt - RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST) +trace.txt + - CONFIG_RCU_TRACE debugfs files and formats UP.txt - RCU on Uniprocessor Systems whatisRCU.txt diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt new file mode 100644 index 000000000000..068848240a8b --- /dev/null +++ b/Documentation/RCU/trace.txt @@ -0,0 +1,413 @@ +CONFIG_RCU_TRACE debugfs Files and Formats + + +The rcupreempt and rcutree implementations of RCU provide debugfs trace +output that summarizes counters and state. This information is useful for +debugging RCU itself, and can sometimes also help to debug abuses of RCU. +Note that the rcuclassic implementation of RCU does not provide debugfs +trace output. + +The following sections describe the debugfs files and formats for +preemptable RCU (rcupreempt) and hierarchical RCU (rcutree). + + +Preemptable RCU debugfs Files and Formats + +This implementation of RCU provides three debugfs files under the +top-level directory RCU: rcu/rcuctrs (which displays the per-CPU +counters used by preemptable RCU) rcu/rcugp (which displays grace-period +counters), and rcu/rcustats (which internal counters for debugging RCU). + +The output of "cat rcu/rcuctrs" looks as follows: + +CPU last cur F M + 0 5 -5 0 0 + 1 -1 0 0 0 + 2 0 1 0 0 + 3 0 1 0 0 + 4 0 1 0 0 + 5 0 1 0 0 + 6 0 2 0 0 + 7 0 -1 0 0 + 8 0 1 0 0 +ggp = 26226, state = waitzero + +The per-CPU fields are as follows: + +o "CPU" gives the CPU number. Offline CPUs are not displayed. + +o "last" gives the value of the counter that is being decremented + for the current grace period phase. In the example above, + the counters sum to 4, indicating that there are still four + RCU read-side critical sections still running that started + before the last counter flip. + +o "cur" gives the value of the counter that is currently being + both incremented (by rcu_read_lock()) and decremented (by + rcu_read_unlock()). In the example above, the counters sum to + 1, indicating that there is only one RCU read-side critical section + still running that started after the last counter flip. + +o "F" indicates whether RCU is waiting for this CPU to acknowledge + a counter flip. In the above example, RCU is not waiting on any, + which is consistent with the state being "waitzero" rather than + "waitack". + +o "M" indicates whether RCU is waiting for this CPU to execute a + memory barrier. In the above example, RCU is not waiting on any, + which is consistent with the state being "waitzero" rather than + "waitmb". + +o "ggp" is the global grace-period counter. + +o "state" is the RCU state, which can be one of the following: + + o "idle": there is no grace period in progress. + + o "waitack": RCU just incremented the global grace-period + counter, which has the effect of reversing the roles of + the "last" and "cur" counters above, and is waiting for + all the CPUs to acknowledge the flip. Once the flip has + been acknowledged, CPUs will no longer be incrementing + what are now the "last" counters, so that their sum will + decrease monotonically down to zero. + + o "waitzero": RCU is waiting for the sum of the "last" counters + to decrease to zero. + + o "waitmb": RCU is waiting for each CPU to execute a memory + barrier, which ensures that instructions from a given CPU's + last RCU read-side critical section cannot be reordered + with instructions following the memory-barrier instruction. + +The output of "cat rcu/rcugp" looks as follows: + +oldggp=48870 newggp=48873 + +Note that reading from this file provokes a synchronize_rcu(). The +"oldggp" value is that of "ggp" from rcu/rcuctrs above, taken before +executing the synchronize_rcu(), and the "newggp" value is also the +"ggp" value, but taken after the synchronize_rcu() command returns. + + +The output of "cat rcu/rcugp" looks as follows: + +na=1337955 nl=40 wa=1337915 wl=44 da=1337871 dl=0 dr=1337871 di=1337871 +1=50989 e1=6138 i1=49722 ie1=82 g1=49640 a1=315203 ae1=265563 a2=49640 +z1=1401244 ze1=1351605 z2=49639 m1=5661253 me1=5611614 m2=49639 + +These are counters tracking internal preemptable-RCU events, however, +some of them may be useful for debugging algorithms using RCU. In +particular, the "nl", "wl", and "dl" values track the number of RCU +callbacks in various states. The fields are as follows: + +o "na" is the total number of RCU callbacks that have been enqueued + since boot. + +o "nl" is the number of RCU callbacks waiting for the previous + grace period to end so that they can start waiting on the next + grace period. + +o "wa" is the total number of RCU callbacks that have started waiting + for a grace period since boot. "na" should be roughly equal to + "nl" plus "wa". + +o "wl" is the number of RCU callbacks currently waiting for their + grace period to end. + +o "da" is the total number of RCU callbacks whose grace periods + have completed since boot. "wa" should be roughly equal to + "wl" plus "da". + +o "dr" is the total number of RCU callbacks that have been removed + from the list of callbacks ready to invoke. "dr" should be roughly + equal to "da". + +o "di" is the total number of RCU callbacks that have been invoked + since boot. "di" should be roughly equal to "da", though some + early versions of preemptable RCU had a bug so that only the + last CPU's count of invocations was displayed, rather than the + sum of all CPU's counts. + +o "1" is the number of calls to rcu_try_flip(). This should be + roughly equal to the sum of "e1", "i1", "a1", "z1", and "m1" + described below. In other words, the number of times that + the state machine is visited should be equal to the sum of the + number of times that each state is visited plus the number of + times that the state-machine lock acquisition failed. + +o "e1" is the number of times that rcu_try_flip() was unable to + acquire the fliplock. + +o "i1" is the number of calls to rcu_try_flip_idle(). + +o "ie1" is the number of times rcu_try_flip_idle() exited early + due to the calling CPU having no work for RCU. + +o "g1" is the number of times that rcu_try_flip_idle() decided + to start a new grace period. "i1" should be roughly equal to + "ie1" plus "g1". + +o "a1" is the number of calls to rcu_try_flip_waitack(). + +o "ae1" is the number of times that rcu_try_flip_waitack() found + that at least one CPU had not yet acknowledge the new grace period + (AKA "counter flip"). + +o "a2" is the number of time rcu_try_flip_waitack() found that + all CPUs had acknowledged. "a1" should be roughly equal to + "ae1" plus "a2". (This particular output was collected on + a 128-CPU machine, hence the smaller-than-usual fraction of + calls to rcu_try_flip_waitack() finding all CPUs having already + acknowledged.) + +o "z1" is the number of calls to rcu_try_flip_waitzero(). + +o "ze1" is the number of times that rcu_try_flip_waitzero() found + that not all of the old RCU read-side critical sections had + completed. + +o "z2" is the number of times that rcu_try_flip_waitzero() finds + the sum of the counters equal to zero, in other words, that + all of the old RCU read-side critical sections had completed. + The value of "z1" should be roughly equal to "ze1" plus + "z2". + +o "m1" is the number of calls to rcu_try_flip_waitmb(). + +o "me1" is the number of times that rcu_try_flip_waitmb() finds + that at least one CPU has not yet executed a memory barrier. + +o "m2" is the number of times that rcu_try_flip_waitmb() finds that + all CPUs have executed a memory barrier. + + +Hierarchical RCU debugfs Files and Formats + +This implementation of RCU provides three debugfs files under the +top-level directory RCU: rcu/rcudata (which displays fields in struct +rcu_data), rcu/rcugp (which displays grace-period counters), and +rcu/rcuhier (which displays the struct rcu_node hierarchy). + +The output of "cat rcu/rcudata" looks as follows: + +rcu: + 0 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=1 rp=3c2a dt=23301/73 dn=2 df=1882 of=0 ri=2126 ql=2 b=10 + 1 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=3 rp=39a6 dt=78073/1 dn=2 df=1402 of=0 ri=1875 ql=46 b=10 + 2 c=4010 g=4010 pq=1 pqc=4010 qp=0 rpfq=-5 rp=1d12 dt=16646/0 dn=2 df=3140 of=0 ri=2080 ql=0 b=10 + 3 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=2b50 dt=21159/1 dn=2 df=2230 of=0 ri=1923 ql=72 b=10 + 4 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1644 dt=5783/1 dn=2 df=3348 of=0 ri=2805 ql=7 b=10 + 5 c=4012 g=4013 pq=0 pqc=4011 qp=1 rpfq=3 rp=1aac dt=5879/1 dn=2 df=3140 of=0 ri=2066 ql=10 b=10 + 6 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=ed8 dt=5847/1 dn=2 df=3797 of=0 ri=1266 ql=10 b=10 + 7 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1fa2 dt=6199/1 dn=2 df=2795 of=0 ri=2162 ql=28 b=10 +rcu_bh: + 0 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-145 rp=21d6 dt=23301/73 dn=2 df=0 of=0 ri=0 ql=0 b=10 + 1 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-170 rp=20ce dt=78073/1 dn=2 df=26 of=0 ri=5 ql=0 b=10 + 2 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-83 rp=fbd dt=16646/0 dn=2 df=28 of=0 ri=4 ql=0 b=10 + 3 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-105 rp=178c dt=21159/1 dn=2 df=28 of=0 ri=2 ql=0 b=10 + 4 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-30 rp=b54 dt=5783/1 dn=2 df=32 of=0 ri=0 ql=0 b=10 + 5 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-29 rp=df5 dt=5879/1 dn=2 df=30 of=0 ri=3 ql=0 b=10 + 6 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-28 rp=788 dt=5847/1 dn=2 df=32 of=0 ri=0 ql=0 b=10 + 7 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-53 rp=1098 dt=6199/1 dn=2 df=30 of=0 ri=3 ql=0 b=10 + +The first section lists the rcu_data structures for rcu, the second for +rcu_bh. Each section has one line per CPU, or eight for this 8-CPU system. +The fields are as follows: + +o The number at the beginning of each line is the CPU number. + CPUs numbers followed by an exclamation mark are offline, + but have been online at least once since boot. There will be + no output for CPUs that have never been online, which can be + a good thing in the surprisingly common case where NR_CPUS is + substantially larger than the number of actual CPUs. + +o "c" is the count of grace periods that this CPU believes have + completed. CPUs in dynticks idle mode may lag quite a ways + behind, for example, CPU 4 under "rcu" above, which has slept + through the past 25 RCU grace periods. It is not unusual to + see CPUs lagging by thousands of grace periods. + +o "g" is the count of grace periods that this CPU believes have + started. Again, CPUs in dynticks idle mode may lag behind. + If the "c" and "g" values are equal, this CPU has already + reported a quiescent state for the last RCU grace period that + it is aware of, otherwise, the CPU believes that it owes RCU a + quiescent state. + +o "pq" indicates that this CPU has passed through a quiescent state + for the current grace period. It is possible for "pq" to be + "1" and "c" different than "g", which indicates that although + the CPU has passed through a quiescent state, either (1) this + CPU has not yet reported that fact, (2) some other CPU has not + yet reported for this grace period, or (3) both. + +o "pqc" indicates which grace period the last-observed quiescent + state for this CPU corresponds to. This is important for handling + the race between CPU 0 reporting an extended dynticks-idle + quiescent state for CPU 1 and CPU 1 suddenly waking up and + reporting its own quiescent state. If CPU 1 was the last CPU + for the current grace period, then the CPU that loses this race + will attempt to incorrectly mark CPU 1 as having checked in for + the next grace period! + +o "qp" indicates that RCU still expects a quiescent state from + this CPU. + +o "rpfq" is the number of rcu_pending() calls on this CPU required + to induce this CPU to invoke force_quiescent_state(). + +o "rp" is low-order four hex digits of the count of how many times + rcu_pending() has been invoked on this CPU. + +o "dt" is the current value of the dyntick counter that is incremented + when entering or leaving dynticks idle state, either by the + scheduler or by irq. The number after the "/" is the interrupt + nesting depth when in dyntick-idle state, or one greater than + the interrupt-nesting depth otherwise. + + This field is displayed only for CONFIG_NO_HZ kernels. + +o "dn" is the current value of the dyntick counter that is incremented + when entering or leaving dynticks idle state via NMI. If both + the "dt" and "dn" values are even, then this CPU is in dynticks + idle mode and may be ignored by RCU. If either of these two + counters is odd, then RCU must be alert to the possibility of + an RCU read-side critical section running on this CPU. + + This field is displayed only for CONFIG_NO_HZ kernels. + +o "df" is the number of times that some other CPU has forced a + quiescent state on behalf of this CPU due to this CPU being in + dynticks-idle state. + + This field is displayed only for CONFIG_NO_HZ kernels. + +o "of" is the number of times that some other CPU has forced a + quiescent state on behalf of this CPU due to this CPU being + offline. In a perfect world, this might neve happen, but it + turns out that offlining and onlining a CPU can take several grace + periods, and so there is likely to be an extended period of time + when RCU believes that the CPU is online when it really is not. + Please note that erring in the other direction (RCU believing a + CPU is offline when it is really alive and kicking) is a fatal + error, so it makes sense to err conservatively. + +o "ri" is the number of times that RCU has seen fit to send a + reschedule IPI to this CPU in order to get it to report a + quiescent state. + +o "ql" is the number of RCU callbacks currently residing on + this CPU. This is the total number of callbacks, regardless + of what state they are in (new, waiting for grace period to + start, waiting for grace period to end, ready to invoke). + +o "b" is the batch limit for this CPU. If more than this number + of RCU callbacks is ready to invoke, then the remainder will + be deferred. + + +The output of "cat rcu/rcugp" looks as follows: + +rcu: completed=33062 gpnum=33063 +rcu_bh: completed=464 gpnum=464 + +Again, this output is for both "rcu" and "rcu_bh". The fields are +taken from the rcu_state structure, and are as follows: + +o "completed" is the number of grace periods that have completed. + It is comparable to the "c" field from rcu/rcudata in that a + CPU whose "c" field matches the value of "completed" is aware + that the corresponding RCU grace period has completed. + +o "gpnum" is the number of grace periods that have started. It is + comparable to the "g" field from rcu/rcudata in that a CPU + whose "g" field matches the value of "gpnum" is aware that the + corresponding RCU grace period has started. + + If these two fields are equal (as they are for "rcu_bh" above), + then there is no grace period in progress, in other words, RCU + is idle. On the other hand, if the two fields differ (as they + do for "rcu" above), then an RCU grace period is in progress. + + +The output of "cat rcu/rcuhier" looks as follows, with very long lines: + +c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 +1/1 0:127 ^0 +3/3 0:35 ^0 0/0 36:71 ^1 0/0 72:107 ^2 0/0 108:127 ^3 +3/3f 0:5 ^0 2/3 6:11 ^1 0/0 12:17 ^2 0/0 18:23 ^3 0/0 24:29 ^4 0/0 30:35 ^5 0/0 36:41 ^0 0/0 42:47 ^1 0/0 48:53 ^2 0/0 54:59 ^3 0/0 60:65 ^4 0/0 66:71 ^5 0/0 72:77 ^0 0/0 78:83 ^1 0/0 84:89 ^2 0/0 90:95 ^3 0/0 96:101 ^4 0/0 102:107 ^5 0/0 108:113 ^0 0/0 114:119 ^1 0/0 120:125 ^2 0/0 126:127 ^3 +rcu_bh: +c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 +0/1 0:127 ^0 +0/3 0:35 ^0 0/0 36:71 ^1 0/0 72:107 ^2 0/0 108:127 ^3 +0/3f 0:5 ^0 0/3 6:11 ^1 0/0 12:17 ^2 0/0 18:23 ^3 0/0 24:29 ^4 0/0 30:35 ^5 0/0 36:41 ^0 0/0 42:47 ^1 0/0 48:53 ^2 0/0 54:59 ^3 0/0 60:65 ^4 0/0 66:71 ^5 0/0 72:77 ^0 0/0 78:83 ^1 0/0 84:89 ^2 0/0 90:95 ^3 0/0 96:101 ^4 0/0 102:107 ^5 0/0 108:113 ^0 0/0 114:119 ^1 0/0 120:125 ^2 0/0 126:127 ^3 + +This is once again split into "rcu" and "rcu_bh" portions. The fields are +as follows: + +o "c" is exactly the same as "completed" under rcu/rcugp. + +o "g" is exactly the same as "gpnum" under rcu/rcugp. + +o "s" is the "signaled" state that drives force_quiescent_state()'s + state machine. + +o "jfq" is the number of jiffies remaining for this grace period + before force_quiescent_state() is invoked to help push things + along. Note that CPUs in dyntick-idle mode thoughout the grace + period will not report on their own, but rather must be check by + some other CPU via force_quiescent_state(). + +o "j" is the low-order four hex digits of the jiffies counter. + Yes, Paul did run into a number of problems that turned out to + be due to the jiffies counter no longer counting. Why do you ask? + +o "nfqs" is the number of calls to force_quiescent_state() since + boot. + +o "nfqsng" is the number of useless calls to force_quiescent_state(), + where there wasn't actually a grace period active. This can + happen due to races. The number in parentheses is the difference + between "nfqs" and "nfqsng", or the number of times that + force_quiescent_state() actually did some real work. + +o "fqlh" is the number of calls to force_quiescent_state() that + exited immediately (without even being counted in nfqs above) + due to contention on ->fqslock. + +o Each element of the form "1/1 0:127 ^0" represents one struct + rcu_node. Each line represents one level of the hierarchy, from + root to leaves. It is best to think of the rcu_data structures + as forming yet another level after the leaves. Note that there + might be either one, two, or three levels of rcu_node structures, + depending on the relationship between CONFIG_RCU_FANOUT and + CONFIG_NR_CPUS. + + o The numbers separated by the "/" are the qsmask followed + by the qsmaskinit. The qsmask will have one bit + set for each entity in the next lower level that + has not yet checked in for the current grace period. + The qsmaskinit will have one bit for each entity that is + currently expected to check in during each grace period. + The value of qsmaskinit is assigned to that of qsmask + at the beginning of each grace period. + + For example, for "rcu", the qsmask of the first entry + of the lowest level is 0x14, meaning that we are still + waiting for CPUs 2 and 4 to check in for the current + grace period. + + o The numbers separated by the ":" are the range of CPUs + served by this struct rcu_node. This can be helpful + in working out how the hierarchy is wired together. + + For example, the first entry at the lowest level shows + "0:5", indicating that it covers CPUs 0 through 5. + + o The number after the "^" indicates the bit in the + next higher level rcu_node structure that this + rcu_node structure corresponds to. + + For example, the first entry at the lowest level shows + "^0", indicating that it corresponds to bit zero in + the first entry at the middle level. diff --git a/Documentation/arm/pxa/mfp.txt b/Documentation/arm/pxa/mfp.txt new file mode 100644 index 000000000000..a179e5bc02c9 --- /dev/null +++ b/Documentation/arm/pxa/mfp.txt @@ -0,0 +1,286 @@ + MFP Configuration for PXA2xx/PXA3xx Processors + + Eric Miao <eric.miao@marvell.com> + +MFP stands for Multi-Function Pin, which is the pin-mux logic on PXA3xx and +later PXA series processors. This document describes the existing MFP API, +and how board/platform driver authors could make use of it. + + Basic Concept +=============== + +Unlike the GPIO alternate function settings on PXA25x and PXA27x, a new MFP +mechanism is introduced from PXA3xx to completely move the pin-mux functions +out of the GPIO controller. In addition to pin-mux configurations, the MFP +also controls the low power state, driving strength, pull-up/down and event +detection of each pin. Below is a diagram of internal connections between +the MFP logic and the remaining SoC peripherals: + + +--------+ + | |--(GPIO19)--+ + | GPIO | | + | |--(GPIO...) | + +--------+ | + | +---------+ + +--------+ +------>| | + | PWM2 |--(PWM_OUT)-------->| MFP | + +--------+ +------>| |-------> to external PAD + | +---->| | + +--------+ | | +-->| | + | SSP2 |---(TXD)----+ | | +---------+ + +--------+ | | + | | + +--------+ | | + | Keypad |--(MKOUT4)----+ | + +--------+ | + | + +--------+ | + | UART2 |---(TXD)--------+ + +--------+ + +NOTE: the external pad is named as MFP_PIN_GPIO19, it doesn't necessarily +mean it's dedicated for GPIO19, only as a hint that internally this pin +can be routed from GPIO19 of the GPIO controller. + +To better understand the change from PXA25x/PXA27x GPIO alternate function +to this new MFP mechanism, here are several key points: + + 1. GPIO controller on PXA3xx is now a dedicated controller, same as other + internal controllers like PWM, SSP and UART, with 128 internal signals + which can be routed to external through one or more MFPs (e.g. GPIO<0> + can be routed through either MFP_PIN_GPIO0 as well as MFP_PIN_GPIO0_2, + see arch/arm/mach-pxa/mach/include/mfp-pxa300.h) + + 2. Alternate function configuration is removed from this GPIO controller, + the remaining functions are pure GPIO-specific, i.e. + + - GPIO signal level control + - GPIO direction control + - GPIO level change detection + + 3. Low power state for each pin is now controlled by MFP, this means the + PGSRx registers on PXA2xx are now useless on PXA3xx + + 4. Wakeup detection is now controlled by MFP, PWER does not control the + wakeup from GPIO(s) any more, depending on the sleeping state, ADxER + (as defined in pxa3xx-regs.h) controls the wakeup from MFP + +NOTE: with such a clear separation of MFP and GPIO, by GPIO<xx> we normally +mean it is a GPIO signal, and by MFP<xxx> or pin xxx, we mean a physical +pad (or ball). + + MFP API Usage +=============== + +For board code writers, here are some guidelines: + +1. include ONE of the following header files in your <board>.c: + + - #include <mach/mfp-pxa25x.h> + - #include <mach/mfp-pxa27x.h> + - #include <mach/mfp-pxa300.h> + - #include <mach/mfp-pxa320.h> + - #include <mach/mfp-pxa930.h> + + NOTE: only one file in your <board>.c, depending on the processors used, + because pin configuration definitions may conflict in these file (i.e. + same name, different meaning and settings on different processors). E.g. + for zylonite platform, which support both PXA300/PXA310 and PXA320, two + separate files are introduced: zylonite_pxa300.c and zylonite_pxa320.c + (in addition to handle MFP configuration differences, they also handle + the other differences between the two combinations). + + NOTE: PXA300 and PXA310 are almost identical in pin configurations (with + PXA310 supporting some additional ones), thus the difference is actually + covered in a single mfp-pxa300.h. + +2. prepare an array for the initial pin configurations, e.g.: + + static unsigned long mainstone_pin_config[] __initdata = { + /* Chip Select */ + GPIO15_nCS_1, + + /* LCD - 16bpp Active TFT */ + GPIOxx_TFT_LCD_16BPP, + GPIO16_PWM0_OUT, /* Backlight */ + + /* MMC */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + + ... + + /* GPIO */ + GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, + }; + + a) once the pin configurations are passed to pxa{2xx,3xx}_mfp_config(), + and written to the actual registers, they are useless and may discard, + adding '__initdata' will help save some additional bytes here. + + b) when there is only one possible pin configurations for a component, + some simplified definitions can be used, e.g. GPIOxx_TFT_LCD_16BPP on + PXA25x and PXA27x processors + + c) if by board design, a pin can be configured to wake up the system + from low power state, it can be 'OR'ed with any of: + + WAKEUP_ON_EDGE_BOTH + WAKEUP_ON_EDGE_RISE + WAKEUP_ON_EDGE_FALL + WAKEUP_ON_LEVEL_HIGH - specifically for enabling of keypad GPIOs, + + to indicate that this pin has the capability of wake-up the system, + and on which edge(s). This, however, doesn't necessarily mean the + pin _will_ wakeup the system, it will only when set_irq_wake() is + invoked with the corresponding GPIO IRQ (GPIO_IRQ(xx) or gpio_to_irq()) + and eventually calls gpio_set_wake() for the actual register setting. + + d) although PXA3xx MFP supports edge detection on each pin, the + internal logic will only wakeup the system when those specific bits + in ADxER registers are set, which can be well mapped to the + corresponding peripheral, thus set_irq_wake() can be called with + the peripheral IRQ to enable the wakeup. + + + MFP on PXA3xx +=============== + +Every external I/O pad on PXA3xx (excluding those for special purpose) has +one MFP logic associated, and is controlled by one MFP register (MFPR). + +The MFPR has the following bit definitions (for PXA300/PXA310/PXA320): + + 31 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +-------------------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RESERVED |PS|PU|PD| DRIVE |SS|SD|SO|EC|EF|ER|--| AF_SEL | + +-------------------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + Bit 3: RESERVED + Bit 4: EDGE_RISE_EN - enable detection of rising edge on this pin + Bit 5: EDGE_FALL_EN - enable detection of falling edge on this pin + Bit 6: EDGE_CLEAR - disable edge detection on this pin + Bit 7: SLEEP_OE_N - enable outputs during low power modes + Bit 8: SLEEP_DATA - output data on the pin during low power modes + Bit 9: SLEEP_SEL - selection control for low power modes signals + Bit 13: PULLDOWN_EN - enable the internal pull-down resistor on this pin + Bit 14: PULLUP_EN - enable the internal pull-up resistor on this pin + Bit 15: PULL_SEL - pull state controlled by selected alternate function + (0) or by PULL{UP,DOWN}_EN bits (1) + + Bit 0 - 2: AF_SEL - alternate function selection, 8 possibilities, from 0-7 + Bit 10-12: DRIVE - drive strength and slew rate + 0b000 - fast 1mA + 0b001 - fast 2mA + 0b002 - fast 3mA + 0b003 - fast 4mA + 0b004 - slow 6mA + 0b005 - fast 6mA + 0b006 - slow 10mA + 0b007 - fast 10mA + + MFP Design for PXA2xx/PXA3xx +============================== + +Due to the difference of pin-mux handling between PXA2xx and PXA3xx, a unified +MFP API is introduced to cover both series of processors. + +The basic idea of this design is to introduce definitions for all possible pin +configurations, these definitions are processor and platform independent, and +the actual API invoked to convert these definitions into register settings and +make them effective there-after. + + Files Involved + -------------- + + - arch/arm/mach-pxa/include/mach/mfp.h + + for + 1. Unified pin definitions - enum constants for all configurable pins + 2. processor-neutral bit definitions for a possible MFP configuration + + - arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h + + for PXA3xx specific MFPR register bit definitions and PXA3xx common pin + configurations + + - arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h + + for PXA2xx specific definitions and PXA25x/PXA27x common pin configurations + + - arch/arm/mach-pxa/include/mach/mfp-pxa25x.h + arch/arm/mach-pxa/include/mach/mfp-pxa27x.h + arch/arm/mach-pxa/include/mach/mfp-pxa300.h + arch/arm/mach-pxa/include/mach/mfp-pxa320.h + arch/arm/mach-pxa/include/mach/mfp-pxa930.h + + for processor specific definitions + + - arch/arm/mach-pxa/mfp-pxa3xx.c + - arch/arm/mach-pxa/mfp-pxa2xx.c + + for implementation of the pin configuration to take effect for the actual + processor. + + Pin Configuration + ----------------- + + The following comments are copied from mfp.h (see the actual source code + for most updated info) + + /* + * a possible MFP configuration is represented by a 32-bit integer + * + * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) + * bit 10..12 - Alternate Function Selection + * bit 13..15 - Drive Strength + * bit 16..18 - Low Power Mode State + * bit 19..20 - Low Power Mode Edge Detection + * bit 21..22 - Run Mode Pull State + * + * to facilitate the definition, the following macros are provided + * + * MFP_CFG_DEFAULT - default MFP configuration value, with + * alternate function = 0, + * drive strength = fast 3mA (MFP_DS03X) + * low power mode = default + * edge detection = none + * + * MFP_CFG - default MFPR value with alternate function + * MFP_CFG_DRV - default MFPR value with alternate function and + * pin drive strength + * MFP_CFG_LPM - default MFPR value with alternate function and + * low power mode + * MFP_CFG_X - default MFPR value with alternate function, + * pin drive strength and low power mode + */ + + Examples of pin configurations are: + + #define GPIO94_SSP3_RXD MFP_CFG_X(GPIO94, AF1, DS08X, FLOAT) + + which reads GPIO94 can be configured as SSP3_RXD, with alternate function + selection of 1, driving strength of 0b101, and a float state in low power + modes. + + NOTE: this is the default setting of this pin being configured as SSP3_RXD + which can be modified a bit in board code, though it is not recommended to + do so, simply because this default setting is usually carefully encoded, + and is supposed to work in most cases. + + Register Settings + ----------------- + + Register settings on PXA3xx for a pin configuration is actually very + straight-forward, most bits can be converted directly into MFPR value + in a easier way. Two sets of MFPR values are calculated: the run-time + ones and the low power mode ones, to allow different settings. + + The conversion from a generic pin configuration to the actual register + settings on PXA2xx is a bit complicated: many registers are involved, + including GAFRx, GPDRx, PGSRx, PWER, PKWR, PFER and PRER. Please see + mfp-pxa2xx.c for how the conversion is made. diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 4dbb8be1c991..3c5434c83daf 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -914,7 +914,7 @@ I/O scheduler, a.k.a. elevator, is implemented in two layers. Generic dispatch queue and specific I/O schedulers. Unless stated otherwise, elevator is used to refer to both parts and I/O scheduler to specific I/O schedulers. -Block layer implements generic dispatch queue in ll_rw_blk.c and elevator.c. +Block layer implements generic dispatch queue in block/*.c. The generic dispatch queue is responsible for properly ordering barrier requests, requeueing, handling non-fs requests and all other subtleties. @@ -926,8 +926,8 @@ be built inside the kernel. Each queue can choose different one and can also change to another one dynamically. A block layer call to the i/o scheduler follows the convention elv_xxx(). This -calls elevator_xxx_fn in the elevator switch (drivers/block/elevator.c). Oh, -xxx and xxx might not match exactly, but use your imagination. If an elevator +calls elevator_xxx_fn in the elevator switch (block/elevator.c). Oh, xxx +and xxx might not match exactly, but use your imagination. If an elevator doesn't implement a function, the switch does nothing or some minimal house keeping work. diff --git a/Documentation/fb/pxafb.txt b/Documentation/fb/pxafb.txt index db9b8500b43b..d143a0a749f9 100644 --- a/Documentation/fb/pxafb.txt +++ b/Documentation/fb/pxafb.txt @@ -5,9 +5,13 @@ The driver supports the following options, either via options=<OPTIONS> when modular or video=pxafb:<OPTIONS> when built in. For example: - modprobe pxafb options=mode:640x480-8,passive + modprobe pxafb options=vmem:2M,mode:640x480-8,passive or on the kernel command line - video=pxafb:mode:640x480-8,passive + video=pxafb:vmem:2M,mode:640x480-8,passive + +vmem: VIDEO_MEM_SIZE + Amount of video memory to allocate (can be suffixed with K or M + for kilobytes or megabytes) mode:XRESxYRES[-BPP] XRES == LCCR1_PPL + 1 @@ -52,3 +56,87 @@ outputen:POLARITY pixclockpol:POLARITY pixel clock polarity 0 => falling edge, 1 => rising edge + + +Overlay Support for PXA27x and later LCD controllers +==================================================== + + PXA27x and later processors support overlay1 and overlay2 on-top of the + base framebuffer (although under-neath the base is also possible). They + support palette and no-palette RGB formats, as well as YUV formats (only + available on overlay2). These overlays have dedicated DMA channels and + behave in a similar way as a framebuffer. + + However, there are some differences between these overlay framebuffers + and normal framebuffers, as listed below: + + 1. overlay can start at a 32-bit word aligned position within the base + framebuffer, which means they have a start (x, y). This information + is encoded into var->nonstd (no, var->xoffset and var->yoffset are + not for such purpose). + + 2. overlay framebuffer is allocated dynamically according to specified + 'struct fb_var_screeninfo', the amount is decided by: + + var->xres_virtual * var->yres_virtual * bpp + + bpp = 16 -- for RGB565 or RGBT555 + = 24 -- for YUV444 packed + = 24 -- for YUV444 planar + = 16 -- for YUV422 planar (1 pixel = 1 Y + 1/2 Cb + 1/2 Cr) + = 12 -- for YUV420 planar (1 pixel = 1 Y + 1/4 Cb + 1/4 Cr) + + NOTE: + + a. overlay does not support panning in x-direction, thus + var->xres_virtual will always be equal to var->xres + + b. line length of overlay(s) must be on a 32-bit word boundary, + for YUV planar modes, it is a requirement for the component + with minimum bits per pixel, e.g. for YUV420, Cr component + for one pixel is actually 2-bits, it means the line length + should be a multiple of 16-pixels + + c. starting horizontal position (XPOS) should start on a 32-bit + word boundary, otherwise the fb_check_var() will just fail. + + d. the rectangle of the overlay should be within the base plane, + otherwise fail + + Applications should follow the sequence below to operate an overlay + framebuffer: + + a. open("/dev/fb[1-2]", ...) + b. ioctl(fd, FBIOGET_VSCREENINFO, ...) + c. modify 'var' with desired parameters: + 1) var->xres and var->yres + 2) larger var->yres_virtual if more memory is required, + usually for double-buffering + 3) var->nonstd for starting (x, y) and color format + 4) var->{red, green, blue, transp} if RGB mode is to be used + d. ioctl(fd, FBIOPUT_VSCREENINFO, ...) + e. ioctl(fd, FBIOGET_FSCREENINFO, ...) + f. mmap + g. ... + + 3. for YUV planar formats, these are actually not supported within the + framebuffer framework, application has to take care of the offsets + and lengths of each component within the framebuffer. + + 4. var->nonstd is used to pass starting (x, y) position and color format, + the detailed bit fields are shown below: + + 31 23 20 10 0 + +-----------------+---+----------+----------+ + | ... unused ... |FOR| XPOS | YPOS | + +-----------------+---+----------+----------+ + + FOR - color format, as defined by OVERLAY_FORMAT_* in pxafb.h + 0 - RGB + 1 - YUV444 PACKED + 2 - YUV444 PLANAR + 3 - YUV422 PLANAR + 4 - YUR420 PLANAR + + XPOS - starting horizontal position + YPOS - starting vertical position diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 804520633fcf..f2dbbf3bdeab 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -481,51 +481,6 @@ static unsigned long load_initrd(const char *name, unsigned long mem) /* We return the initrd size. */ return len; } - -/* Once we know how much memory we have we can construct simple linear page - * tables which set virtual == physical which will get the Guest far enough - * into the boot to create its own. - * - * We lay them out of the way, just below the initrd (which is why we need to - * know its size here). */ -static unsigned long setup_pagetables(unsigned long mem, - unsigned long initrd_size) -{ - unsigned long *pgdir, *linear; - unsigned int mapped_pages, i, linear_pages; - unsigned int ptes_per_page = getpagesize()/sizeof(void *); - - mapped_pages = mem/getpagesize(); - - /* Each PTE page can map ptes_per_page pages: how many do we need? */ - linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page; - - /* We put the toplevel page directory page at the top of memory. */ - pgdir = from_guest_phys(mem) - initrd_size - getpagesize(); - - /* Now we use the next linear_pages pages as pte pages */ - linear = (void *)pgdir - linear_pages*getpagesize(); - - /* Linear mapping is easy: put every page's address into the mapping in - * order. PAGE_PRESENT contains the flags Present, Writable and - * Executable. */ - for (i = 0; i < mapped_pages; i++) - linear[i] = ((i * getpagesize()) | PAGE_PRESENT); - - /* The top level points to the linear page table pages above. */ - for (i = 0; i < mapped_pages; i += ptes_per_page) { - pgdir[i/ptes_per_page] - = ((to_guest_phys(linear) + i*sizeof(void *)) - | PAGE_PRESENT); - } - - verbose("Linear mapping of %u pages in %u pte pages at %#lx\n", - mapped_pages, linear_pages, to_guest_phys(linear)); - - /* We return the top level (guest-physical) address: the kernel needs - * to know where it is. */ - return to_guest_phys(pgdir); -} /*:*/ /* Simple routine to roll all the commandline arguments together with spaces @@ -548,13 +503,13 @@ static void concat(char *dst, char *args[]) /*L:185 This is where we actually tell the kernel to initialize the Guest. We * saw the arguments it expects when we looked at initialize() in lguest_user.c: - * the base of Guest "physical" memory, the top physical page to allow, the - * top level pagetable and the entry point for the Guest. */ -static int tell_kernel(unsigned long pgdir, unsigned long start) + * the base of Guest "physical" memory, the top physical page to allow and the + * entry point for the Guest. */ +static int tell_kernel(unsigned long start) { unsigned long args[] = { LHREQ_INITIALIZE, (unsigned long)guest_base, - guest_limit / getpagesize(), pgdir, start }; + guest_limit / getpagesize(), start }; int fd; verbose("Guest: %p - %p (%#lx)\n", @@ -1030,7 +985,7 @@ static void update_device_status(struct device *dev) /* Zero out the virtqueues. */ for (vq = dev->vq; vq; vq = vq->next) { memset(vq->vring.desc, 0, - vring_size(vq->config.num, getpagesize())); + vring_size(vq->config.num, LGUEST_VRING_ALIGN)); lg_last_avail(vq) = 0; } } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { @@ -1211,7 +1166,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, void *p; /* First we need some memory for this virtqueue. */ - pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1) + pages = (vring_size(num_descs, LGUEST_VRING_ALIGN) + getpagesize() - 1) / getpagesize(); p = get_pages(pages); @@ -1228,7 +1183,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, vq->config.pfn = to_guest_phys(p) / getpagesize(); /* Initialize the vring. */ - vring_init(&vq->vring, num_descs, p, getpagesize()); + vring_init(&vq->vring, num_descs, p, LGUEST_VRING_ALIGN); /* Append virtqueue to this device's descriptor. We use * device_config() to get the end of the device's current virtqueues; @@ -1941,7 +1896,7 @@ int main(int argc, char *argv[]) { /* Memory, top-level pagetable, code startpoint and size of the * (optional) initrd. */ - unsigned long mem = 0, pgdir, start, initrd_size = 0; + unsigned long mem = 0, start, initrd_size = 0; /* Two temporaries and the /dev/lguest file descriptor. */ int i, c, lguest_fd; /* The boot information for the Guest. */ @@ -2040,9 +1995,6 @@ int main(int argc, char *argv[]) boot->hdr.type_of_loader = 0xFF; } - /* Set up the initial linear pagetables, starting below the initrd. */ - pgdir = setup_pagetables(mem, initrd_size); - /* The Linux boot header contains an "E820" memory map: ours is a * simple, single region. */ boot->e820_entries = 1; @@ -2064,7 +2016,7 @@ int main(int argc, char *argv[]) /* We tell the kernel to initialize the Guest: this returns the open * /dev/lguest file descriptor. */ - lguest_fd = tell_kernel(pgdir, start); + lguest_fd = tell_kernel(start); /* We clone off a thread, which wakes the Launcher whenever one of the * input file descriptors needs attention. We call this the Waker, and diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt index 4ba4664ce5c3..9cb9138f7a79 100644 --- a/Documentation/lockstat.txt +++ b/Documentation/lockstat.txt @@ -71,35 +71,50 @@ Look at the current lock statistics: # less /proc/lock_stat -01 lock_stat version 0.2 +01 lock_stat version 0.3 02 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 03 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total 04 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 05 -06 &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 -07 &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 -08 -------------------------- -09 &inode->i_data.tree_lock 0 [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190 -10 -11 ............................................................................................................................................................................................... -12 -13 dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 -14 ----------- -15 dcache_lock 180 [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230 -16 dcache_lock 165 [<ffffffff802c002a>] d_alloc+0x15a/0x210 -17 dcache_lock 33 [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70 -18 dcache_lock 1 [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130 +06 &mm->mmap_sem-W: 233 538 18446744073708 22924.27 607243.51 1342 45806 1.71 8595.89 1180582.34 +07 &mm->mmap_sem-R: 205 587 18446744073708 28403.36 731975.00 1940 412426 0.58 187825.45 6307502.88 +08 --------------- +09 &mm->mmap_sem 487 [<ffffffff8053491f>] do_page_fault+0x466/0x928 +10 &mm->mmap_sem 179 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d +11 &mm->mmap_sem 279 [<ffffffff80210a57>] sys_mmap+0x75/0xce +12 &mm->mmap_sem 76 [<ffffffff802a490b>] sys_munmap+0x32/0x59 +13 --------------- +14 &mm->mmap_sem 270 [<ffffffff80210a57>] sys_mmap+0x75/0xce +15 &mm->mmap_sem 431 [<ffffffff8053491f>] do_page_fault+0x466/0x928 +16 &mm->mmap_sem 138 [<ffffffff802a490b>] sys_munmap+0x32/0x59 +17 &mm->mmap_sem 145 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d +18 +19 ............................................................................................................................................................................................... +20 +21 dcache_lock: 621 623 0.52 118.26 1053.02 6745 91930 0.29 316.29 118423.41 +22 ----------- +23 dcache_lock 179 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54 +24 dcache_lock 113 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb +25 dcache_lock 99 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44 +26 dcache_lock 104 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a +27 ----------- +28 dcache_lock 192 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54 +29 dcache_lock 98 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44 +30 dcache_lock 72 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb +31 dcache_lock 112 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a This excerpt shows the first two lock class statistics. Line 01 shows the output version - each time the format changes this will be updated. Line 02-04 -show the header with column descriptions. Lines 05-10 and 13-18 show the actual +show the header with column descriptions. Lines 05-18 and 20-31 show the actual statistics. These statistics come in two parts; the actual stats separated by a -short separator (line 08, 14) from the contention points. +short separator (line 08, 13) from the contention points. -The first lock (05-10) is a read/write lock, and shows two lines above the +The first lock (05-18) is a read/write lock, and shows two lines above the short separator. The contention points don't match the column descriptors, -they have two: contentions and [<IP>] symbol. +they have two: contentions and [<IP>] symbol. The second set of contention +points are the points we're contending with. +The integer part of the time values is in us. View the top contending locks: diff --git a/MAINTAINERS b/MAINTAINERS index 08d0ab7fa161..ceb32ee51f9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1755,6 +1755,13 @@ L: linuxppc-dev@ozlabs.org L: linux-i2c@vger.kernel.org S: Maintained +FREESCALE IMX / MXC FRAMEBUFFER DRIVER +P: Sascha Hauer +M: kernel@pengutronix.de +L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +S: Maintained + FREESCALE SOC FS_ENET DRIVER P: Pantelis Antoniou M: pantelis.antoniou@gmail.com @@ -205,13 +205,14 @@ ifeq ($(ARCH),x86_64) SRCARCH := x86 endif -# Where to locate arch specific headers +# Additional ARCH settings for sparc ifeq ($(ARCH),sparc64) - hdr-arch := sparc -else - hdr-arch := $(SRCARCH) + SRCARCH := sparc endif +# Where to locate arch specific headers +hdr-arch := $(SRCARCH) + KCONFIG_CONFIG ?= .config # SHELL used by kbuild diff --git a/arch/Kconfig b/arch/Kconfig index 471e72dbaf8b..2e13aa261929 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -6,6 +6,8 @@ config OPROFILE tristate "OProfile system profiling (EXPERIMENTAL)" depends on PROFILING depends on HAVE_OPROFILE + select TRACING + select RING_BUFFER help OProfile is a profiling system capable of profiling the whole system, include the kernel, kernel modules, libraries, diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h index e971ab000f95..eda9b909aa05 100644 --- a/arch/alpha/include/asm/io.h +++ b/arch/alpha/include/asm/io.h @@ -96,9 +96,6 @@ static inline dma_addr_t __deprecated isa_page_to_bus(struct page *page) return page_to_phys(page); } -/* This depends on working iommu. */ -#define BIO_VMERGE_BOUNDARY (alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0) - /* Maximum PIO space address supported? */ #define IO_SPACE_LIMIT 0xffff diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9722f8bb506c..d6ebe39934b5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -156,7 +156,6 @@ config ARCH_MTD_XIP bool config GENERIC_HARDIRQS_NO__DO_IRQ - bool def_bool y if OPROFILE @@ -201,6 +200,7 @@ choice config ARCH_AAEC2000 bool "Agilent AAEC-2000 based" + select CPU_ARM920T select ARM_AMBA select HAVE_CLK help @@ -210,6 +210,7 @@ config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select ARM_AMBA select HAVE_CLK + select COMMON_CLKDEV select ICST525 help Support for ARM's Integrator platform. @@ -218,6 +219,7 @@ config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARM_AMBA select HAVE_CLK + select COMMON_CLKDEV select ICST307 select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -229,6 +231,7 @@ config ARCH_VERSATILE select ARM_AMBA select ARM_VIC select HAVE_CLK + select COMMON_CLKDEV select ICST307 select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -243,22 +246,15 @@ config ARCH_AT91 This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. -config ARCH_CLPS7500 - bool "Cirrus CL-PS7500FE" - select TIMER_ACORN - select ISA - select NO_IOPORT - select ARCH_SPARSEMEM_ENABLE - help - Support for the Cirrus Logic PS7500FE system-on-a-chip. - config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x-based" + select CPU_ARM720T help Support for Cirrus Logic 711x/721x based boards. config ARCH_EBSA110 bool "EBSA-110" + select CPU_SA110 select ISA select NO_IOPORT help @@ -269,16 +265,19 @@ config ARCH_EBSA110 config ARCH_EP93XX bool "EP93xx-based" + select CPU_ARM920T select ARM_AMBA select ARM_VIC select GENERIC_GPIO select HAVE_CLK + select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB help This enables support for the Cirrus EP93xx series of CPUs. config ARCH_FOOTBRIDGE bool "FootBridge" + select CPU_SA110 select FOOTBRIDGE help Support for systems based on the DC21285 companion chip @@ -286,18 +285,23 @@ config ARCH_FOOTBRIDGE config ARCH_NETX bool "Hilscher NetX based" + select CPU_ARM926T select ARM_VIC + select GENERIC_CLOCKEVENTS + select GENERIC_TIME help This enables support for systems based on the Hilscher NetX Soc config ARCH_H720X bool "Hynix HMS720x-based" + select CPU_ARM720T select ISA_DMA_API help This enables support for systems based on the Hynix HMS720x config ARCH_IMX bool "IMX" + select CPU_ARM920T select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -307,6 +311,7 @@ config ARCH_IMX config ARCH_IOP13XX bool "IOP13xx-based" depends on MMU + select CPU_XSC3 select PLAT_IOP select PCI select ARCH_SUPPORTS_MSI @@ -317,6 +322,7 @@ config ARCH_IOP13XX config ARCH_IOP32X bool "IOP32x-based" depends on MMU + select CPU_XSCALE select PLAT_IOP select PCI select GENERIC_GPIO @@ -328,6 +334,7 @@ config ARCH_IOP32X config ARCH_IOP33X bool "IOP33x-based" depends on MMU + select CPU_XSCALE select PLAT_IOP select PCI select GENERIC_GPIO @@ -338,6 +345,7 @@ config ARCH_IOP33X config ARCH_IXP23XX bool "IXP23XX-based" depends on MMU + select CPU_XSC3 select PCI help Support for Intel's IXP23xx (XScale) family of processors. @@ -345,6 +353,7 @@ config ARCH_IXP23XX config ARCH_IXP2000 bool "IXP2400/2800-based" depends on MMU + select CPU_XSCALE select PCI help Support for Intel's IXP2400/2800 (XScale) family of processors. @@ -352,6 +361,7 @@ config ARCH_IXP2000 config ARCH_IXP4XX bool "IXP4xx-based" depends on MMU + select CPU_XSCALE select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -361,6 +371,7 @@ config ARCH_IXP4XX config ARCH_L7200 bool "LinkUp-L7200" + select CPU_ARM720T select FIQ help Say Y here if you intend to run this kernel on a LinkUp Systems @@ -374,7 +385,9 @@ config ARCH_L7200 config ARCH_KIRKWOOD bool "Marvell Kirkwood" + select CPU_FEROCEON select PCI + select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION @@ -384,13 +397,16 @@ config ARCH_KIRKWOOD config ARCH_KS8695 bool "Micrel/Kendin KS8695" + select CPU_ARM922T select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based System-on-Chip devices. config ARCH_NS9XXX bool "NetSilicon NS9xxx" + select CPU_ARM926T select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -403,6 +419,7 @@ config ARCH_NS9XXX config ARCH_LOKI bool "Marvell Loki (88RC8480)" + select CPU_FEROCEON select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION @@ -411,7 +428,9 @@ config ARCH_LOKI config ARCH_MV78XX0 bool "Marvell MV78xx0" + select CPU_FEROCEON select PCI + select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION @@ -432,6 +451,7 @@ config ARCH_MXC config ARCH_ORION5X bool "Marvell Orion" depends on MMU + select CPU_FEROCEON select PCI select GENERIC_GPIO select GENERIC_TIME @@ -444,6 +464,7 @@ config ARCH_ORION5X config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" + select CPU_ARM926T select HAVE_CLK help This enables support for Philips PNX4008 mobile platform. @@ -454,6 +475,7 @@ config ARCH_PXA select ARCH_MTD_XIP select GENERIC_GPIO select HAVE_CLK + select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -477,6 +499,7 @@ config ARCH_RPC config ARCH_SA1100 bool "SA1100-based" + select CPU_SA1100 select ISA select ARCH_SPARSEMEM_ENABLE select ARCH_MTD_XIP @@ -498,8 +521,16 @@ config ARCH_S3C2410 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or the Samsung SMDK2410 development board (and derivatives). +config ARCH_S3C64XX + bool "Samsung S3C64XX" + select GENERIC_GPIO + select HAVE_CLK + help + Samsung S3C64XX series based systems + config ARCH_SHARK bool "Shark" + select CPU_SA110 select ISA select ISA_DMA select ZONE_DMA @@ -510,6 +541,7 @@ config ARCH_SHARK config ARCH_LH7A40X bool "Sharp LH7A40X" + select CPU_ARM922T select ARCH_DISCONTIGMEM_ENABLE if !LH7A40X_CONTIGMEM select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM help @@ -520,6 +552,7 @@ config ARCH_LH7A40X config ARCH_DAVINCI bool "TI DaVinci" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO @@ -541,6 +574,7 @@ config ARCH_OMAP config ARCH_MSM bool "Qualcomm MSM" + select CPU_V6 select GENERIC_TIME select GENERIC_CLOCKEVENTS help @@ -549,6 +583,13 @@ config ARCH_MSM interface to the ARM9 modem processor which runs the baseband stack and controls some vital subsystems (clock and power control, etc). +config ARCH_W90X900 + bool "Nuvoton W90X900 CPU" + select CPU_ARM926T + help + Support for Nuvoton (Winbond logic dept.) ARM9 processor,You + can login www.mcuos.com or www.nuvoton.com to know more. + endchoice source "arch/arm/mach-clps711x/Kconfig" @@ -590,6 +631,7 @@ source "arch/arm/mach-orion5x/Kconfig" source "arch/arm/mach-kirkwood/Kconfig" source "arch/arm/plat-s3c24xx/Kconfig" +source "arch/arm/plat-s3c64xx/Kconfig" source "arch/arm/plat-s3c/Kconfig" if ARCH_S3C2410 @@ -601,6 +643,11 @@ source "arch/arm/mach-s3c2442/Kconfig" source "arch/arm/mach-s3c2443/Kconfig" endif +if ARCH_S3C64XX +source "arch/arm/mach-s3c6400/Kconfig" +source "arch/arm/mach-s3c6410/Kconfig" +endif + source "arch/arm/mach-lh7a40x/Kconfig" source "arch/arm/mach-imx/Kconfig" @@ -627,6 +674,8 @@ source "arch/arm/mach-ks8695/Kconfig" source "arch/arm/mach-msm/Kconfig" +source "arch/arm/mach-w90x900/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool @@ -781,7 +830,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP) + depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP) default y help Enable support for local timers on SMP platforms, rather then the diff --git a/arch/arm/Makefile b/arch/arm/Makefile index bd6e28115ebb..24e0f0187697 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -76,6 +76,7 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +tune-$(CONFIG_CPU_FEROCEON) :=$(call cc-option,-mtune=marvell-f,-mtune=xscale) tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) ifeq ($(CONFIG_AEABI),y) @@ -96,7 +97,6 @@ textofs-y := 0x00008000 machine-$(CONFIG_ARCH_RPC) := rpc machine-$(CONFIG_ARCH_EBSA110) := ebsa110 - machine-$(CONFIG_ARCH_CLPS7500) := clps7500 machine-$(CONFIG_FOOTBRIDGE) := footbridge machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SA1100) := sa1100 @@ -121,7 +121,10 @@ endif machine-$(CONFIG_ARCH_OMAP3) := omap2 plat-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 + machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx s3c + machine-$(CONFIG_ARCH_S3C64XX) := s3c6400 s3c6410 + plat-$(CONFIG_PLAT_S3C64XX) := s3c64xx s3c machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_IMX) := imx @@ -139,11 +142,13 @@ endif plat-$(CONFIG_ARCH_MXC) := mxc machine-$(CONFIG_ARCH_MX2) := mx2 machine-$(CONFIG_ARCH_MX3) := mx3 + machine-$(CONFIG_ARCH_MX1) := mx1 machine-$(CONFIG_ARCH_ORION5X) := orion5x plat-$(CONFIG_PLAT_ORION) := orion machine-$(CONFIG_ARCH_MSM) := msm machine-$(CONFIG_ARCH_LOKI) := loki machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0 + machine-$(CONFIG_ARCH_W90X900) := w90x900 ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index c47f2a3f8f8f..fbe5eef1f6c9 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -23,10 +23,6 @@ ifeq ($(CONFIG_ARCH_L7200),y) OBJS += head-l7200.o endif -ifeq ($(CONFIG_ARCH_CLPS7500),y) -HEAD = head-clps7500.o -endif - ifeq ($(CONFIG_ARCH_P720T),y) # Borrow this code from SA1100 OBJS += head-sa1100.o diff --git a/arch/arm/boot/compressed/head-clps7500.S b/arch/arm/boot/compressed/head-clps7500.S deleted file mode 100644 index 4f3c78ac30a0..000000000000 --- a/arch/arm/boot/compressed/head-clps7500.S +++ /dev/null @@ -1,86 +0,0 @@ -/* - * linux/arch/arm/boot/compressed/head-clps7500.S - * - * Copyright (C) 1999, 2000, 2001 Nexus Electronics Ltd - */ - - - /* There are three different ways the kernel can be - booted on a 7500 system: from Angel (loaded in RAM), from - 16-bit ROM or from 32-bit Flash. Luckily, a single kernel - image does for them all. */ - /* This branch is taken if the CPU memory width matches the - actual device in use. The default at power on is 16 bits - so we must be prepared for a mismatch. */ - .section ".start", "ax" -2: - b 1f - .word 0xffff - .word 0xb632 @ mov r11, #0x03200000 - .word 0xe3a0 - .word 0x0000 @ mov r0, #0 - .word 0xe3a0 - .word 0x0080 @ strb r0, [r11, #0x80] - .word 0xe5cb - .word 0xf000 @ mov pc, #0 - .word 0xe3a0 -1: - adr r1, 2b - teq r1, #0 - bne .Langel - /* This is a direct-from-ROM boot. Copy the kernel into - RAM and run it there. */ - mov r0, #0x30 - mcr p15, 0, r0, c1, c0, 0 - mov r0, #0x13 - msr cpsr_cxsf, r0 - mov r12, #0x03000000 @ point to LEDs - orr r12, r12, #0x00020000 - orr r12, r12, #0xba00 - mov r0, #0x5500 - str r0, [r12] - mov r0, #0x10000000 - orr r0, r0, #0x8000 - mov r4, r0 - ldr r2, =_end -2: - ldr r3, [r1], #4 - str r3, [r0], #4 - teq r0, r2 - bne 2b - mov r0, #0xff00 - str r0, [r12] -1: - mov r12, #0x03000000 @ point to LEDs - orr r12, r12, #0x00020000 - orr r12, r12, #0xba00 - mov r0, #0xfe00 - str r0, [r12] - - adr lr, 1f - mov r0, #0 - mov r1, #14 /* MACH_TYPE_CLPS7500 */ - mov pc, lr -.Langel: -#ifdef CONFIG_ANGELBOOT - /* Call Angel to switch into SVC mode. */ - mov r0, #0x17 - swi 0x123456 -#endif - /* Ensure all interrupts are off and MMU disabled */ - mrs r0, cpsr - orr r0, r0, #0xc0 - msr cpsr_cxsf, r0 - - adr lr, 1b - orr lr, lr, #0x10000000 - mov r0, #0x30 @ MMU off - mcr p15, 0, r0, c1, c0, 0 - mov r0, r0 - mov pc, lr - - .ltorg - -1: -/* And the rest */ -#include "head.S" diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 84a1e0496a3c..77d614232d81 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -624,6 +624,12 @@ proc_types: b __armv4_mmu_cache_off b __armv4_mmu_cache_flush + .word 0x56056930 + .word 0xff0ffff0 @ PXA935 + b __armv4_mmu_cache_on + b __armv4_mmu_cache_off + b __armv4_mmu_cache_flush + .word 0x56050000 @ Feroceon .word 0xff0f0000 b __armv4_mmu_cache_on @@ -717,6 +723,9 @@ __armv7_mmu_cache_off: bl __armv7_mmu_cache_flush mov r0, #0 mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB + mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB mov pc, r12 __arm6_mmu_cache_off: @@ -778,12 +787,13 @@ __armv6_mmu_cache_flush: __armv7_mmu_cache_flush: mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 tst r10, #0xf << 16 @ hierarchical cache (ARMv7) - beq hierarchical mov r10, #0 + beq hierarchical mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D b iflush hierarchical: - stmfd sp!, {r0-r5, r7, r9-r11} + mcr p15, 0, r10, c7, c10, 5 @ DMB + stmfd sp!, {r0-r5, r7, r9, r11} mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr mov r3, r3, lsr #23 @ left align loc bit field @@ -820,12 +830,14 @@ skip: cmp r3, r10 bgt loop1 finished: + ldmfd sp!, {r0-r5, r7, r9, r11} mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - ldmfd sp!, {r0-r5, r7, r9-r11} iflush: + mcr p15, 0, r10, c7, c10, 4 @ DSB mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB - mcr p15, 0, r10, c7, c10, 4 @ drain WB + mcr p15, 0, r10, c7, c10, 4 @ DSB + mcr p15, 0, r10, c7, c5, 4 @ ISB mov pc, lr __armv5tej_mmu_cache_flush: diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 65ce8fff29db..3fc08413fff0 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -86,6 +86,8 @@ static void putstr(const char *ptr) #define __ptr_t void * +#define memzero(s,n) __memzero(s,n) + /* * Optimised C version of memzero for the ARM. */ diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 86b5e6982660..a2cd9beaf37d 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -33,3 +33,6 @@ config SHARPSL_PM config SHARP_SCOOP bool + +config COMMON_CLKDEV + bool diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 325e4b6a6afb..7cb7961d81cb 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_SHARP_SCOOP) += scoop.o obj-$(CONFIG_ARCH_IXP2000) += uengine.o obj-$(CONFIG_ARCH_IXP23XX) += uengine.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o +obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c new file mode 100644 index 000000000000..17a17b49a45b --- /dev/null +++ b/arch/arm/common/clkdev.c @@ -0,0 +1,128 @@ +/* + * arch/arm/common/clkdev.c + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/mutex.h> + +#include <asm/clkdev.h> +#include <mach/clkdev.h> + +static LIST_HEAD(clocks); +static DEFINE_MUTEX(clocks_mutex); + +static struct clk *clk_find(const char *dev_id, const char *con_id) +{ + struct clk_lookup *p; + struct clk *clk = NULL; + int match, best = 0; + + list_for_each_entry(p, &clocks, node) { + if ((p->dev_id && !dev_id) || (p->con_id && !con_id)) + continue; + match = 0; + if (p->dev_id) + match += 2 * (strcmp(p->dev_id, dev_id) == 0); + if (p->con_id) + match += 1 * (strcmp(p->con_id, con_id) == 0); + if (match == 0) + continue; + + if (match > best) { + clk = p->clk; + best = match; + } + } + return clk; +} + +struct clk *clk_get(struct device *dev, const char *con_id) +{ + const char *dev_id = dev ? dev_name(dev) : NULL; + struct clk *clk; + + mutex_lock(&clocks_mutex); + clk = clk_find(dev_id, con_id); + if (clk && !__clk_get(clk)) + clk = NULL; + mutex_unlock(&clocks_mutex); + + return clk ? clk : ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + __clk_put(clk); +} +EXPORT_SYMBOL(clk_put); + +void clkdev_add(struct clk_lookup *cl) +{ + mutex_lock(&clocks_mutex); + list_add_tail(&cl->node, &clocks); + mutex_unlock(&clocks_mutex); +} +EXPORT_SYMBOL(clkdev_add); + +#define MAX_DEV_ID 20 +#define MAX_CON_ID 16 + +struct clk_lookup_alloc { + struct clk_lookup cl; + char dev_id[MAX_DEV_ID]; + char con_id[MAX_CON_ID]; +}; + +struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, + const char *dev_fmt, ...) +{ + struct clk_lookup_alloc *cla; + + cla = kzalloc(sizeof(*cla), GFP_KERNEL); + if (!cla) + return NULL; + + cla->cl.clk = clk; + if (con_id) { + strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); + cla->cl.con_id = cla->con_id; + } + + if (dev_fmt) { + va_list ap; + + va_start(ap, dev_fmt); + vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); + cla->cl.dev_id = cla->dev_id; + va_end(ap); + } + + return &cla->cl; +} +EXPORT_SYMBOL(clkdev_alloc); + +/* + * clkdev_drop - remove a clock dynamically allocated + */ +void clkdev_drop(struct clk_lookup *cl) +{ + mutex_lock(&clocks_mutex); + list_del(&cl->node); + mutex_unlock(&clocks_mutex); + kfree(cl); +} +EXPORT_SYMBOL(clkdev_drop); diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 7c6b4b99a2df..2293f0ce061e 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -1108,6 +1108,7 @@ void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf) locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); spin_unlock_irqrestore(&lchip->lock, flags); } +EXPORT_SYMBOL(locomo_frontlight_set); /* * LoCoMo "Register Access Bus." diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index f1e4b8f60cab..ecf0bfbab107 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -69,12 +69,12 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, /* * Make sure we clear all existing interrupts */ - writel(0, base + VIC_VECT_ADDR); + writel(0, base + VIC_PL190_VECT_ADDR); for (i = 0; i < 19; i++) { unsigned int value; - value = readl(base + VIC_VECT_ADDR); - writel(value, base + VIC_VECT_ADDR); + value = readl(base + VIC_PL190_VECT_ADDR); + writel(value, base + VIC_PL190_VECT_ADDR); } for (i = 0; i < 16; i++) { @@ -82,7 +82,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, writel(VIC_VECT_CNTL_ENABLE | i, reg); } - writel(32, base + VIC_DEF_VECT_ADDR); + writel(32, base + VIC_PL190_DEF_VECT_ADDR); for (i = 0; i < 32; i++) { unsigned int irq = irq_start + i; diff --git a/arch/arm/configs/eseries_pxa_defconfig b/arch/arm/configs/eseries_pxa_defconfig index 2307587a38a9..b6c5cbbf4c85 100644 --- a/arch/arm/configs/eseries_pxa_defconfig +++ b/arch/arm/configs/eseries_pxa_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26 -# Sat Jul 26 22:28:46 2008 +# Linux kernel version: 2.6.28-rc8 +# Wed Dec 24 23:35:45 2008 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -22,8 +22,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ZONE_DMA=y CONFIG_ARCH_MTD_XIP=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 @@ -48,8 +46,7 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set @@ -58,13 +55,12 @@ CONFIG_SYSCTL=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_KALLSYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -CONFIG_COMPAT_BRK=y +# CONFIG_COMPAT_BRK is not set CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y @@ -73,6 +69,7 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -80,15 +77,10 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set -# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set -# CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set CONFIG_HAVE_CLK=y -CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -112,14 +104,15 @@ CONFIG_BLOCK=y # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_CLASSIC_RCU=y +CONFIG_FREEZER=y # # System Type @@ -129,7 +122,6 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set @@ -160,7 +152,8 @@ CONFIG_ARCH_PXA=y # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Intel PXA2xx/PXA3xx Implementations @@ -169,8 +162,10 @@ CONFIG_ARCH_PXA=y # CONFIG_ARCH_LUBBOCK is not set # CONFIG_MACH_LOGICPD_PXA270 is not set # CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_MP900C is not set # CONFIG_ARCH_PXA_IDP is not set # CONFIG_PXA_SHARPSL is not set +# CONFIG_ARCH_VIPER is not set CONFIG_ARCH_PXA_ESERIES=y CONFIG_MACH_E330=y CONFIG_MACH_E350=y @@ -178,7 +173,8 @@ CONFIG_MACH_E740=y CONFIG_MACH_E750=y CONFIG_MACH_E400=y CONFIG_MACH_E800=y -# CONFIG_MACH_TRIZEPS4 is not set +# CONFIG_TRIZEPS_PXA is not set +# CONFIG_MACH_H5000 is not set # CONFIG_MACH_EM_X270 is not set # CONFIG_MACH_COLIBRI is not set # CONFIG_MACH_ZYLONITE is not set @@ -186,12 +182,15 @@ CONFIG_MACH_E800=y # CONFIG_MACH_TAVOREVB is not set # CONFIG_MACH_SAAR is not set # CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_CM_X300 is not set # CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_MIOA701 is not set # CONFIG_MACH_PCM027 is not set # CONFIG_ARCH_PXA_PALM is not set # CONFIG_PXA_EZX is not set CONFIG_PXA25x=y # CONFIG_PXA_PWM is not set +CONFIG_PXA_HAVE_BOARD_IRQS=y # # Boot options @@ -222,6 +221,7 @@ CONFIG_CPU_CP15_MMU=y # CONFIG_OUTER_CACHE is not set CONFIG_IWMMXT=y CONFIG_XSCALE_PMU=y +CONFIG_COMMON_CLKDEV=y # # Bus support @@ -237,6 +237,7 @@ CONFIG_PCMCIA_IOCTL=y # # PC-card bridges # +CONFIG_PCMCIA_PXA2XX=m # # Kernel Features @@ -245,25 +246,30 @@ CONFIG_TICK_ONESHOT=y # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 # CONFIG_PREEMPT is not set CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -277,9 +283,10 @@ CONFIG_KEXEC=y CONFIG_ATAGS_PROC=y # -# CPU Frequency scaling +# CPU Power Management # # CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -296,6 +303,8 @@ CONFIG_FPE_NWFPE=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -309,10 +318,6 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y - -# -# Networking -# CONFIG_NET=y # @@ -339,7 +344,7 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y +# CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y @@ -350,25 +355,7 @@ CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=y -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6 is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # CONFIG_IP_DCCP is not set @@ -376,6 +363,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -421,25 +409,18 @@ CONFIG_IRDA_FAST_RR=y # # Dongle support # -# CONFIG_KINGSUN_DONGLE is not set -# CONFIG_KSDAZZLE_DONGLE is not set -# CONFIG_KS959_DONGLE is not set # # FIR device drivers # -# CONFIG_USB_IRDA is not set -# CONFIG_SIGMATEL_FIR is not set CONFIG_PXA_FICP=y -# CONFIG_MCS_FIR is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y CONFIG_CFG80211=m CONFIG_NL80211=y +CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_MAC80211=m @@ -448,7 +429,9 @@ CONFIG_MAC80211=m # Rate control algorithm selection # CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set CONFIG_MAC80211_RC_DEFAULT="pid" # CONFIG_MAC80211_MESH is not set # CONFIG_MAC80211_LEDS is not set @@ -539,11 +522,12 @@ CONFIG_MTD_NAND=m # CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=m # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_SHARPSL is not set +CONFIG_MTD_NAND_TMIO=m # CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set # CONFIG_MTD_ONENAND is not set # @@ -556,13 +540,13 @@ CONFIG_BLK_DEV=y CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -632,37 +616,25 @@ CONFIG_NETDEVICES=y CONFIG_WLAN_80211=y # CONFIG_PCMCIA_RAYCS is not set # CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set CONFIG_HERMES=m CONFIG_PCMCIA_HERMES=m # CONFIG_PCMCIA_SPECTRUM is not set # CONFIG_ATMEL is not set # CONFIG_AIRO_CS is not set # CONFIG_PCMCIA_WL3501 is not set -# CONFIG_USB_ZD1201 is not set -# CONFIG_USB_NET_RNDIS_WLAN is not set -# CONFIG_RTL8187 is not set # CONFIG_MAC80211_HWSIM is not set # CONFIG_P54_COMMON is not set # CONFIG_IWLWIFI_LEDS is not set # CONFIG_HOSTAP is not set # CONFIG_B43 is not set # CONFIG_B43LEGACY is not set -# CONFIG_ZD1211RW is not set # CONFIG_RT2X00 is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set CONFIG_NET_PCMCIA=y # CONFIG_PCMCIA_3C589 is not set # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_FMVJ18X is not set -CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_PCNET is not set # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set @@ -714,13 +686,11 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_PENMOUNT is not set # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set -# CONFIG_TOUCHSCREEN_UCB1400 is not set CONFIG_TOUCHSCREEN_WM97XX=m CONFIG_TOUCHSCREEN_WM9705=y CONFIG_TOUCHSCREEN_WM9712=y CONFIG_TOUCHSCREEN_WM9713=y # CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set -# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set # CONFIG_INPUT_MISC is not set @@ -749,11 +719,13 @@ CONFIG_DEVKMEM=y # # Non-8250 serial port support # -# CONFIG_SERIAL_PXA is not set +CONFIG_SERIAL_PXA=y +# CONFIG_SERIAL_PXA_CONSOLE is not set +CONFIG_SERIAL_CORE=y CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set # CONFIG_R3964 is not set @@ -773,6 +745,10 @@ CONFIG_GPIOLIB=y # CONFIG_GPIO_SYSFS is not set # +# Memory mapped GPIO expanders: +# + +# # I2C GPIO expanders: # @@ -786,12 +762,14 @@ CONFIG_GPIOLIB=y # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # @@ -799,8 +777,13 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE=y # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +CONFIG_MFD_TMIO=y +CONFIG_MFD_T7L66XB=y +CONFIG_MFD_TC6387XB=y CONFIG_MFD_TC6393XB=y # @@ -827,6 +810,7 @@ CONFIG_MFD_TC6393XB=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y @@ -851,8 +835,10 @@ CONFIG_FB_PXA=y # CONFIG_FB_PXA_PARAMETERS is not set # CONFIG_FB_MBX is not set CONFIG_FB_W100=y -# CONFIG_FB_AM200EPD is not set +# CONFIG_FB_TMIO is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_ILI9320 is not set @@ -886,6 +872,7 @@ CONFIG_FONT_MINI_4x6=y # CONFIG_FONT_10x18 is not set # CONFIG_LOGO is not set CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m @@ -899,14 +886,18 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SND_VERBOSE_PRINTK=y # CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_AC97_CODEC=m CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_MTPAV is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_AC97_POWER_SAVE is not set CONFIG_SND_ARM=y +CONFIG_SND_PXA2XX_LIB=m +CONFIG_SND_PXA2XX_LIB_AC97=y # CONFIG_SND_PXA2XX_AC97 is not set -# CONFIG_SND_USB is not set # CONFIG_SND_PCMCIA is not set CONFIG_SND_SOC=m CONFIG_SND_SOC_AC97_BUS=y @@ -920,133 +911,19 @@ CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set # CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set # -# USB Input Devices +# Special HID drivers # -CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -CONFIG_USB_DEVICE_CLASS=y -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set -# CONFIG_USB_OTG is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# may also be needed; see USB_STORAGE Help for more information -# -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -CONFIG_USB_MON=y - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGET is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_ISIGHTFW is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG_FILES is not set -CONFIG_USB_GADGET_SELECTED=y -# CONFIG_USB_GADGET_AMD5536UDC is not set -# CONFIG_USB_GADGET_ATMEL_USBA is not set -# CONFIG_USB_GADGET_FSL_USB2 is not set -# CONFIG_USB_GADGET_NET2280 is not set -CONFIG_USB_GADGET_PXA25X=y -CONFIG_USB_PXA25X=y -CONFIG_USB_PXA25X_SMALL=y -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_PXA27X is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_S3C2410 is not set -# CONFIG_USB_GADGET_AT91 is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_GADGET_DUALSPEED is not set -# CONFIG_USB_ZERO is not set -CONFIG_USB_ETH=m -# CONFIG_USB_ETH_RNDIS is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_HID_COMPAT=y +# CONFIG_USB_SUPPORT is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_UNSAFE_RESUME=y # -# MMC/SD Card Drivers +# MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_BOUNCE=y @@ -1054,14 +931,18 @@ CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_MMC_TEST is not set # -# MMC/SD Host Controller Drivers +# MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_PXA is not set # CONFIG_MMC_SDHCI is not set +CONFIG_MMC_TMIO=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set # CONFIG_NEW_LEDS is not set CONFIG_RTC_LIB=y # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set # CONFIG_UIO is not set # @@ -1070,11 +951,17 @@ CONFIG_RTC_LIB=y CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set -# CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=m +CONFIG_FS_MBCACHE=m # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set CONFIG_DNOTIFY=y @@ -1106,6 +993,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set @@ -1142,6 +1030,7 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1228,13 +1117,15 @@ CONFIG_FRAME_WARN=1024 # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_MEMORY_INIT is not set CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_LATENCYTOP is not set -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_DEBUG_USER is not set @@ -1244,15 +1135,23 @@ CONFIG_HAVE_ARCH_KGDB=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set @@ -1324,14 +1223,17 @@ CONFIG_CRYPTO_ARC4=m # # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=y # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set diff --git a/arch/arm/configs/h5000_defconfig b/arch/arm/configs/h5000_defconfig new file mode 100644 index 000000000000..649baa370495 --- /dev/null +++ b/arch/arm/configs/h5000_defconfig @@ -0,0 +1,996 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc6 +# Tue Sep 16 16:13:48 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +# CONFIG_UID16 is not set +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Intel PXA2xx/PXA3xx Implementations +# +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +# CONFIG_ARCH_PXA_ESERIES is not set +CONFIG_MACH_H5000=y +# CONFIG_MACH_TRIZEPS4 is not set +# CONFIG_MACH_EM_X270 is not set +# CONFIG_MACH_COLIBRI is not set +# CONFIG_MACH_ZYLONITE is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set +# CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_EZX is not set +CONFIG_PXA25x=y +# CONFIG_PXA_PWM is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +# CONFIG_IWMMXT is not set +CONFIG_XSCALE_PMU=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="keepinitrd" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_APM_EMULATION=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PXA2XX is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_NETDEVICES is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_APMPOWER is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_USB_GADGET_PXA25X=y +CONFIG_USB_PXA25X=y +CONFIG_USB_PXA25X_SMALL=y +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +# CONFIG_USB_ETH_RNDIS is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_SA1100=y +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index e3357ba10f1f..ab8b1e0d0dac 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -1,11 +1,11 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc5 -# Sun Jun 22 15:51:25 2008 +# Linux kernel version: 2.6.28-rc7 +# Thu Dec 4 15:27:39 2008 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y @@ -22,8 +22,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -49,14 +48,17 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set # CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y +# CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -73,9 +75,12 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set +CONFIG_PCI_QUIRKS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y # CONFIG_MARKERS is not set @@ -85,8 +90,7 @@ CONFIG_KPROBES=y CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_DMA_ATTRS is not set -CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -97,12 +101,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -117,6 +122,7 @@ CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # System Type @@ -128,7 +134,6 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -158,7 +163,7 @@ CONFIG_ARCH_KIRKWOOD=y # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set +# CONFIG_ARCH_MSM is not set # # Marvell Kirkwood Implementations @@ -199,6 +204,7 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_DCACHE_DISABLE is not set CONFIG_OUTER_CACHE=y CONFIG_CACHE_FEROCEON_L2=y +# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set # # Bus support @@ -217,25 +223,30 @@ CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -248,6 +259,11 @@ CONFIG_CMDLINE="" # CONFIG_KEXEC is not set # +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# # Floating point emulation # @@ -260,6 +276,8 @@ CONFIG_CMDLINE="" # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -268,10 +286,6 @@ CONFIG_BINFMT_ELF=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y - -# -# Networking -# CONFIG_NET=y # @@ -322,6 +336,15 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +CONFIG_NET_DSA=y +# CONFIG_NET_DSA_TAG_DSA is not set +CONFIG_NET_DSA_TAG_EDSA=y +# CONFIG_NET_DSA_TAG_TRAILER is not set +CONFIG_NET_DSA_MV88E6XXX=y +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +CONFIG_NET_DSA_MV88E6123_61_65=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -343,12 +366,12 @@ CONFIG_NET_PKTGEN=m # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set # CONFIG_RFKILL is not set @@ -365,6 +388,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -453,7 +478,7 @@ CONFIG_M25PXX_USE_FAST_READ=y # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set CONFIG_MTD_NAND_IDS=y @@ -561,6 +586,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_DH is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_SATA_PMP=y @@ -619,7 +645,6 @@ CONFIG_SATA_MV=y # CONFIG_PATA_SIS is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set -# CONFIG_PATA_PLATFORM is not set # CONFIG_PATA_SCH is not set # CONFIG_MD is not set # CONFIG_FUSION is not set @@ -627,11 +652,14 @@ CONFIG_SATA_MV=y # # IEEE 1394 (FireWire) support # + +# +# Enable only one of the two stacks, unless you know what you are doing +# # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -639,7 +667,23 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # CONFIG_VETH is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set @@ -650,12 +694,16 @@ CONFIG_MII=y # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set # CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set @@ -676,14 +724,12 @@ CONFIG_NET_PCI=y # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -CONFIG_E1000=y -CONFIG_E1000_NAPI=y -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000 is not set # CONFIG_E1000E is not set -# CONFIG_E1000E_ENABLED is not set # CONFIG_IP1000 is not set # CONFIG_IGB is not set # CONFIG_NS83820 is not set @@ -699,6 +745,8 @@ CONFIG_E1000_NAPI=y CONFIG_MV643XX_ETH=y # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_JME is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set @@ -765,7 +813,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_NOZOMI is not set @@ -775,7 +827,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 # CONFIG_SERIAL_8250_EXTENDED is not set @@ -800,44 +852,64 @@ CONFIG_DEVPORT=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y # # I2C Hardware Bus support # + +# +# PC SMBus host controller drivers +# # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_GPIO is not set # CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISCH is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_TINY_USB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Graphics adapter I2C/DDC channel drivers +# # CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# # CONFIG_I2C_PCA_PLATFORM is not set -CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_STUB is not set # # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set +# CONFIG_AT24 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set @@ -864,20 +936,26 @@ CONFIG_SPI_ORION=y # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set # # Multimedia devices @@ -910,8 +988,10 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_DISPLAY_SUPPORT is not set # -# Sound +# Console display driver support # +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y @@ -922,9 +1002,36 @@ CONFIG_HID=y # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_BRIGHT=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DELL=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -940,8 +1047,9 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -956,20 +1064,23 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=y +CONFIG_USB_PRINTER=m # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -992,7 +1103,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# CONFIG_USB_MON is not set # # USB port drivers @@ -1005,7 +1115,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1023,8 +1133,12 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y # CONFIG_LEDS_CLASS is not set @@ -1038,6 +1152,8 @@ CONFIG_NEW_LEDS=y # CONFIG_LEDS_TRIGGERS is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set # @@ -1056,7 +1172,6 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_MAX6900 is not set -CONFIG_RTC_DRV_MV=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_X1205 is not set @@ -1064,29 +1179,39 @@ CONFIG_RTC_DRV_MV=y # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set # # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # +CONFIG_RTC_DRV_MV=y CONFIG_DMADEVICES=y # @@ -1099,6 +1224,8 @@ CONFIG_DMA_ENGINE=y # DMA Clients # # CONFIG_NET_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_REGULATOR is not set # CONFIG_UIO is not set # @@ -1109,11 +1236,12 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1131,7 +1259,7 @@ CONFIG_INOTIFY_USER=y # # CD-ROM/DVD Filesystems # -CONFIG_ISO9660_FS=y +CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_ZISOFS is not set CONFIG_UDF_FS=m @@ -1140,9 +1268,9 @@ CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems # -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set @@ -1152,6 +1280,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set @@ -1182,6 +1311,7 @@ CONFIG_JFFS2_RTIME=y CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -1192,13 +1322,13 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1210,24 +1340,8 @@ CONFIG_SUNRPC=y # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -1284,11 +1398,14 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1300,21 +1417,40 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set @@ -1326,6 +1462,7 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_ASYNC_CORE=y CONFIG_CRYPTO=y @@ -1333,8 +1470,12 @@ CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_RNG=m CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set @@ -1373,6 +1514,10 @@ CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -1403,6 +1548,11 @@ CONFIG_CRYPTO_PCBC=m # # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set @@ -1410,10 +1560,9 @@ CONFIG_CRYPTO_HW=y # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=y CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/arm/configs/ks8695_defconfig b/arch/arm/configs/ks8695_defconfig index 6077f2cb88e4..d25c41bab06c 100644 --- a/arch/arm/configs/ks8695_defconfig +++ b/arch/arm/configs/ks8695_defconfig @@ -1,39 +1,67 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc4 -# Thu May 25 15:42:51 2006 +# Linux kernel version: 2.6.27-simtec-micrel1 +# Fri Dec 5 10:30:27 2008 # CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" -CONFIG_UID16=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -41,30 +69,50 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set -CONFIG_OBSOLETE_INTERMODULE=y - -# -# Loadable module support -# CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y - -# -# Block layer -# +CONFIG_BLOCK=y +# CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -78,60 +126,77 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y # # System Type # +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +CONFIG_ARCH_KS8695=y +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_AT91 is not set -CONFIG_ARCH_KS8695=y +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# # # Kendin/Micrel KS8695 Implementations # CONFIG_MACH_KS8695=y -# CONFIG_MACH_DSM320 is not set -# CONFIG_MACH_CM4002 is not set -# CONFIG_MACH_CM4008 is not set -# CONFIG_MACH_CM40xx is not set -# CONFIG_MACH_LITE300 is not set -# CONFIG_MACH_SE4200 is not set -# CONFIG_MACH_MANGA_KS8695 is not set +CONFIG_MACH_DSM320=y # # Processor Type # CONFIG_CPU_32=y CONFIG_CPU_ARM922T=y -CONFIG_CPU_32v4=y +CONFIG_CPU_32v4T=y CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_V4WT=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y # # Processor Features @@ -140,16 +205,16 @@ CONFIG_CPU_TLB_V4WBI=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set # # Bus support # CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y CONFIG_PCI_DEBUG=y - -# -# PCCARD (PCMCIA/CardBus) support -# CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set CONFIG_PCMCIA=y @@ -173,9 +238,12 @@ CONFIG_PCCARD_NONSTATIC=y # # Kernel Features # +# CONFIG_TICK_ONESHOT is not set # CONFIG_PREEMPT is not set CONFIG_HZ=100 -# CONFIG_AEABI is not set +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -184,7 +252,14 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y # @@ -194,6 +269,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw" # CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set # # Floating point emulation @@ -202,8 +278,7 @@ CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev # # At least one emulation must be selected # -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_NWFPE is not set # CONFIG_FPE_FASTFPE is not set # @@ -212,34 +287,33 @@ CONFIG_FPE_NWFPE=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set # # Power management options # # CONFIG_PM is not set -# CONFIG_APM is not set - -# -# Networking -# +CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -250,28 +324,21 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -282,13 +349,8 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set # @@ -296,9 +358,21 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -307,36 +381,40 @@ CONFIG_TCP_CONG_BIC=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers # CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set # # RAM/ROM/Flash chip drivers @@ -355,22 +433,25 @@ CONFIG_MTD_CFI_I1=y CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I4 is not set # CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_PLATRAM is not set # @@ -388,29 +469,15 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# # CONFIG_MTD_NAND is not set - -# -# OneNAND Flash Device Drivers -# # CONFIG_MTD_ONENAND is not set # -# Parallel port support +# UBI - Unsorted block images # +# CONFIG_MTD_UBI is not set # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -422,13 +489,17 @@ CONFIG_MTD_CFI_UTIL=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -436,127 +507,85 @@ CONFIG_BLK_DEV_INITRD=y # # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# # CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # -# I2O device support +# Enable only one of the two stacks, unless you know what you are doing # +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# ARCnet devices -# +# CONFIG_VETH is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_ARM_KS8695_ETHER=y +CONFIG_MII=y +# CONFIG_AX88796 is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set - -# -# Tulip family network device support -# # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set # CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# PCMCIA network device support -# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_PRISM54=m +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set # CONFIG_NET_PCMCIA is not set - -# -# Wan interfaces -# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -566,7 +595,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -576,6 +604,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -589,9 +618,13 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -609,132 +642,113 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set +CONFIG_HW_RANDOM=m # CONFIG_NVRAM is not set -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set - -# # PCMCIA character devices # # CONFIG_SYNCLINK_CS is not set # CONFIG_CARDMAN_4000 is not set # CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Misc devices -# +# CONFIG_WATCHDOG is not set # -# LED devices +# Sonics Silicon Backplane # -# CONFIG_NEW_LEDS is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# LED drivers +# Multifunction device drivers # +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set # -# LED Triggers +# Multimedia devices # # -# Multimedia devices +# Multimedia core support # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set # -# Digital Video Broadcasting Devices +# Multimedia drivers # -# CONFIG_DVB is not set +# CONFIG_DAB is not set # # Graphics support # +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Console display driver support +# Display device support # -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y +# CONFIG_DISPLAY_SUPPORT is not set # -# Sound +# Console display driver support # +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # CONFIG_SOUND is not set - -# -# USB support -# +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# Enable Host or Gadget support to see Inventra options # # -# USB Gadget Support +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # -# Real Time Clock +# Voltage and Current regulators # -CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set # # File systems @@ -743,16 +757,16 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -774,10 +788,11 @@ CONFIG_DNOTIFY=y # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -790,67 +805,113 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# -# CONFIG_NFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# # CONFIG_NLS is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set +# CONFIG_DLM is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set CONFIG_FRAME_POINTER=y -# CONFIG_UNWIND_INFO is not set -CONFIG_FORCED_INLINING=y +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y # CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set @@ -859,21 +920,103 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set # -# Cryptographic options +# Ciphers # -# CONFIG_CRYPTO is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set # -# Hardware crypto devices +# Compression # +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set # # Library routines # +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/mx31moboard_defconfig b/arch/arm/configs/mx31moboard_defconfig new file mode 100644 index 000000000000..e90f86d6deef --- /dev/null +++ b/arch/arm/configs/mx31moboard_defconfig @@ -0,0 +1,790 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc5 +# Fri Oct 24 11:41:22 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +CONFIG_ARCH_MXC=y +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Freescale MXC Implementations +# +# CONFIG_ARCH_MX2 is not set +CONFIG_ARCH_MX3=y + +# +# MX3 Options +# +# CONFIG_MACH_MX31ADS is not set +# CONFIG_MACH_PCM037 is not set +# CONFIG_MACH_MX31LITE is not set +CONFIG_MACH_MX31MOBOARD=y +# CONFIG_MXC_IRQ_PRIOR is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_V6=y +# CONFIG_CPU_32v6K is not set +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +# CONFIG_MTD_CFI_I2 is not set +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/mx31pdk_defconfig b/arch/arm/configs/mx31pdk_defconfig new file mode 100644 index 000000000000..95ffc0db95a0 --- /dev/null +++ b/arch/arm/configs/mx31pdk_defconfig @@ -0,0 +1,773 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-rc2 +# Sun Oct 26 15:55:29 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_COMPAT_BRK is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +CONFIG_ARCH_MXC=y +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Freescale MXC Implementations +# +# CONFIG_ARCH_MX2 is not set +CONFIG_ARCH_MX3=y + +# +# MX3 Options +# +# CONFIG_MACH_MX31ADS is not set +# CONFIG_MACH_PCM037 is not set +# CONFIG_MACH_MX31LITE is not set +CONFIG_MACH_MX31_3DS=y +# CONFIG_MXC_IRQ_PRIOR is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_V6=y +# CONFIG_CPU_32v6K is not set +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_UNEVICTABLE_LRU is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +CONFIG_IPV6_SIT=y +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_WM8400 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_HFSPLUS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_PCBC is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/neocore926_defconfig b/arch/arm/configs/neocore926_defconfig new file mode 100644 index 000000000000..325f1e105f69 --- /dev/null +++ b/arch/arm/configs/neocore926_defconfig @@ -0,0 +1,1302 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc1 +# Tue Jul 29 10:46:54 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_COMPAT_BRK is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +CONFIG_ARCH_AT91SAM9263=y +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91SAM9263 Board Type +# +# CONFIG_MACH_AT91SAM9263EK is not set +# CONFIG_MACH_USB_A9263 is not set +CONFIG_MACH_NEOCORE926=y + +# +# AT91 Board Options +# +CONFIG_MTD_AT91_DATAFLASH_CARD=y + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +CONFIG_NFTL=y +CONFIG_NFTL_RW=y +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_BLOCK2MTD=y + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +CONFIG_MTD_NAND_ECC_SMC=y +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +CONFIG_MTD_NAND_ATMEL_ECC_HW=y +# CONFIG_MTD_NAND_ATMEL_ECC_SOFT is not set +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +CONFIG_ATMEL_PWM=y +CONFIG_ATMEL_TCLIB=y +CONFIG_ATMEL_TCB_CLKSRC=y +CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +# CONFIG_BLK_DEV_SD is not set +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MACB=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_PDC is not set +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ATMEL=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_ATMEL=y +# CONFIG_FB_VIRTUAL is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_ATMEL_LCDC=y +# CONFIG_BACKLIGHT_ATMEL_PWM is not set +# CONFIG_BACKLIGHT_CORGI is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_GADGET is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MMC_SPI is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_FS_WBUF_VERIFY=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 0884f2370c3a..61d0fc5b2417 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -728,9 +728,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=m -CONFIG_RTC_INTF_PROC=m -CONFIG_RTC_INTF_DEV=m +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y # # RTC drivers diff --git a/arch/arm/configs/omap3_pandora_defconfig b/arch/arm/configs/omap3_pandora_defconfig new file mode 100644 index 000000000000..09543f4de5bc --- /dev/null +++ b/arch/arm/configs/omap3_pandora_defconfig @@ -0,0 +1,1409 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-rc7 +# Fri Dec 5 11:54:09 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP3_BEAGLE is not set +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OVERO is not set +CONFIG_MACH_OMAP3_PANDORA=y + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE=" debug " +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=800 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_ISP1301_OMAP is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_COMPAT is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BRIGHT is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DELL is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +CONFIG_USB_MUSB_HOST=y +# CONFIG_USB_MUSB_PERIPHERAL is not set +# CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +CONFIG_USB_GADGET_OMAP=y +CONFIG_USB_OMAP=y +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/omap_ldp_defconfig b/arch/arm/configs/omap_ldp_defconfig index 948a212fb1cc..b77d054169ee 100644 --- a/arch/arm/configs/omap_ldp_defconfig +++ b/arch/arm/configs/omap_ldp_defconfig @@ -316,7 +316,82 @@ CONFIG_BINFMT_MISC=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_NET is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -332,6 +407,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y # CONFIG_MTD is not set # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y @@ -390,6 +467,54 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_DH is not set # CONFIG_ATA is not set # CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +CONFIG_SMC911X=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set # # Input device support @@ -816,6 +941,27 @@ CONFIG_TMPFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig index 14826f0dabde..59e4463c2da2 100644 --- a/arch/arm/configs/picotux200_defconfig +++ b/arch/arm/configs/picotux200_defconfig @@ -1069,9 +1069,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=m -CONFIG_RTC_INTF_PROC=m -CONFIG_RTC_INTF_DEV=m +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig index 0c09b23167ec..cd29824d791c 100644 --- a/arch/arm/configs/realview-smp_defconfig +++ b/arch/arm/configs/realview-smp_defconfig @@ -1,84 +1,111 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc3 -# Wed Oct 25 14:12:00 2006 +# Linux kernel version: 2.6.28-rc2 +# Mon Nov 10 14:41:47 2008 # CONFIG_ARM=y -# CONFIG_GENERIC_TIME is not set +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set -# CONFIG_CPUSETS is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set -CONFIG_INITRAMFS_SOURCE="" +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y -# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_SLAB=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y CONFIG_STOP_MACHINE=y - -# -# Block layer -# CONFIG_BLOCK=y +# CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -92,6 +119,8 @@ CONFIG_DEFAULT_DEADLINE=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # System Type @@ -103,19 +132,26 @@ CONFIG_ARCH_REALVIEW=y # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -123,13 +159,29 @@ CONFIG_ARCH_REALVIEW=y # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set + +# +# Boot options +# + +# +# Power management +# # # RealView platform type # CONFIG_MACH_REALVIEW_EB=y -CONFIG_REALVIEW_MPCORE=y +# CONFIG_REALVIEW_EB_A9MP is not set +CONFIG_REALVIEW_EB_ARM11MP=y +# CONFIG_REALVIEW_EB_ARM11MP_REVB is not set +CONFIG_MACH_REALVIEW_PB11MP=y +# CONFIG_MACH_REALVIEW_PB1176 is not set +# CONFIG_MACH_REALVIEW_PBA8 is not set +CONFIG_REALVIEW_HIGH_PHYS_OFFSET=y # # Processor Type @@ -138,12 +190,15 @@ CONFIG_CPU_32=y # CONFIG_CPU_ARM926T is not set CONFIG_CPU_V6=y CONFIG_CPU_32v6K=y +# CONFIG_CPU_V7 is not set CONFIG_CPU_32v6=y CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_V6=y CONFIG_CPU_CACHE_VIPT=y CONFIG_CPU_COPY_V6=y CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y CONFIG_CPU_CP15=y CONFIG_CPU_CP15_MMU=y @@ -153,9 +208,10 @@ CONFIG_CPU_CP15_MMU=y CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_HAS_TLS_REG=y +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_L2X0=y CONFIG_ARM_GIC=y CONFIG_ICST307=y @@ -163,32 +219,44 @@ CONFIG_ICST307=y # Bus support # CONFIG_ARM_AMBA=y - -# -# PCCARD (PCMCIA/CardBus) support -# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_SMP=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_NR_CPUS=4 CONFIG_HOTPLUG_CPU=y CONFIG_LOCAL_TIMERS=y # CONFIG_PREEMPT is not set CONFIG_HZ=100 -# CONFIG_AEABI is not set -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -198,6 +266,12 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M" # CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -206,8 +280,7 @@ CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=tt # # At least one emulation must be selected # -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_NWFPE is not set # CONFIG_FPE_FASTFPE is not set CONFIG_VFP=y @@ -215,28 +288,29 @@ CONFIG_VFP=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set # # Power management options # # CONFIG_PM is not set -# CONFIG_APM is not set - -# -# Networking -# +CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -255,36 +329,25 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -294,10 +357,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set # @@ -305,9 +364,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_IEEE80211 is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -316,38 +380,37 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers # CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set # # RAM/ROM/Flash chip drivers @@ -373,7 +436,6 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access @@ -397,115 +459,73 @@ CONFIG_MTD_ARM_INTEGRATOR=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# # CONFIG_MTD_NAND is not set - -# -# OneNAND Flash Device Drivers -# # CONFIG_MTD_ONENAND is not set # -# Parallel port support +# UBI - Unsorted block images # +# CONFIG_MTD_UBI is not set # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set # CONFIG_SCSI_NETLINK is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Network device support -# CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# PHY device support -# +# CONFIG_VETH is not set # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_AX88796 is not set CONFIG_SMC91X=y # CONFIG_DM9000 is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# +CONFIG_SMC911X=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set # @@ -513,6 +533,7 @@ CONFIG_SMC91X=y # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -522,7 +543,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -538,9 +558,16 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -558,9 +585,11 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -579,97 +608,91 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set -# CONFIG_DTLK is not set # CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# # CONFIG_TCG_TPM is not set - -# -# I2C support -# # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Misc devices -# -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set # -# LED devices +# Sonics Silicon Backplane # -# CONFIG_NEW_LEDS is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# LED drivers +# Multifunction device drivers # +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_WM8400 is not set # -# LED Triggers +# Multimedia devices # # -# Multimedia devices +# Multimedia core support # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set # -# Digital Video Broadcasting Devices +# Multimedia drivers # -# CONFIG_DVB is not set +# CONFIG_DAB is not set # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# CONFIG_FB_ARMCLCD=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -677,28 +700,17 @@ CONFIG_FB_ARMCLCD=y # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -712,100 +724,65 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -CONFIG_SND_AC97_CODEC=m -CONFIG_SND_AC97_BUS=m -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# ALSA ARM devices -# -CONFIG_SND_ARMAACI=m - -# -# Open Sound System -# +CONFIG_SND_VMASTER=y +CONFIG_SND_AC97_CODEC=y +# CONFIG_SND_DRIVERS is not set +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=y +# CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# +CONFIG_AC97_BUS=y +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set -CONFIG_MMC_BLOCK=y -CONFIG_MMC_ARMMMCI=y -# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_UNSAFE_RESUME is not set # -# Real Time Clock +# MMC/SD/SDIO Card Drivers # -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set # -# RTC interfaces +# MMC/SD/SDIO Host Controller Drivers # -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # -# RTC drivers +# Voltage and Current regulators # -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_M48T86 is not set -CONFIG_RTC_DRV_PL031=y -# CONFIG_RTC_DRV_TEST is not set -# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set # # File systems # -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y -# CONFIG_INOTIFY_USER is not set +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -831,11 +808,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -848,29 +825,28 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set # CONFIG_JFFS2_FS is not set CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -878,17 +854,12 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -929,64 +900,177 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set +# CONFIG_DLM is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RWSEMS=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set CONFIG_FRAME_POINTER=y -# CONFIG_UNWIND_INFO is not set -CONFIG_FORCED_INLINING=y -# CONFIG_HEADERS_CHECK is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set # # Security options # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set # -# Cryptographic options +# Random Number Generation # -# CONFIG_CRYPTO is not set +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index 907e54344dad..7e253f58ed18 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -1,105 +1,204 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc2 -# Thu Sep 29 14:50:10 2005 +# Linux kernel version: 2.6.28-rc2 +# Mon Nov 10 14:39:48 2008 # CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -CONFIG_UID16=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # -# CONFIG_EXPERIMENTAL is not set -CONFIG_CLEAN_COMPILE=y +CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set -CONFIG_INITRAMFS_SOURCE="" +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # System Type # +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +CONFIG_ARCH_REALVIEW=y +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -CONFIG_ARCH_REALVIEW=y -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_MSM is not set + +# +# Boot options +# + +# +# Power management +# # # RealView platform type # CONFIG_MACH_REALVIEW_EB=y +# CONFIG_REALVIEW_EB_A9MP is not set +CONFIG_REALVIEW_EB_ARM11MP=y +# CONFIG_REALVIEW_EB_ARM11MP_REVB is not set +CONFIG_MACH_REALVIEW_PB11MP=y +CONFIG_MACH_REALVIEW_PB1176=y +# CONFIG_MACH_REALVIEW_PBA8 is not set # # Processor Type # CONFIG_CPU_32=y -CONFIG_CPU_ARM926T=y -# CONFIG_CPU_V6 is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_TLB_V4WBI=y +# CONFIG_CPU_ARM926T is not set +CONFIG_CPU_V6=y +# CONFIG_CPU_32v6K is not set +# CONFIG_CPU_V7 is not set +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y # # Processor Features @@ -107,8 +206,9 @@ CONFIG_CPU_TLB_V4WBI=y CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_L2X0=y CONFIG_ARM_GIC=y CONFIG_ICST307=y @@ -116,20 +216,41 @@ CONFIG_ICST307=y # Bus support # CONFIG_ARM_AMBA=y -CONFIG_ISA_DMA_API=y - -# -# PCCARD (PCMCIA/CardBus) support -# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_SMP is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -139,6 +260,12 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M" # CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -147,26 +274,24 @@ CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=tt # # At least one emulation must be selected # -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_VFP is not set +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y # # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set # # Power management options # # CONFIG_PM is not set - -# -# Networking -# +CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # @@ -175,6 +300,11 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -186,34 +316,56 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_IEEE80211 is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -222,30 +374,37 @@ CONFIG_TCP_CONG_BIC=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set - -# -# Memory Technology Devices (MTD) -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers # CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set # # RAM/ROM/Flash chip drivers @@ -266,7 +425,6 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set @@ -279,7 +437,6 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set CONFIG_MTD_ARM_INTEGRATOR=y -# CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PLATRAM is not set # @@ -288,7 +445,7 @@ CONFIG_MTD_ARM_INTEGRATOR=y # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set # # Disk-On-Chip Device Drivers @@ -296,121 +453,81 @@ CONFIG_MTD_ARM_INTEGRATOR=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# # CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set # -# Parallel port support +# UBI - Unsorted block images # +# CONFIG_MTD_UBI is not set # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_RAM_COUNT=16 # CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_IOSCHED_CFQ is not set # CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Network device support -# CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# PHY device support -# +# CONFIG_VETH is not set # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_AX88796 is not set CONFIG_SMC91X=y # CONFIG_DM9000 is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# +CONFIG_SMC911X=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -420,7 +537,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -433,11 +549,19 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -455,8 +579,11 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -475,73 +602,91 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set # CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# I2C support -# +# CONFIG_TCG_TPM is not set # CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set # -# Hardware Monitoring support +# Sonics Silicon Backplane # -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Misc devices +# Multifunction device drivers # +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_WM8400 is not set # -# Multimedia Capabilities Port drivers +# Multimedia devices # # -# Multimedia devices +# Multimedia core support # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set # -# Digital Video Broadcasting Devices +# Multimedia drivers # -# CONFIG_DVB is not set +# CONFIG_DAB is not set # # Graphics support # +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# CONFIG_FB_ARMCLCD=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -549,27 +694,17 @@ CONFIG_FB_ARMCLCD=y # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -577,59 +712,71 @@ CONFIG_SND_PCM=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# ALSA ARM devices -# -# CONFIG_SND_ARMAACI is not set - -# -# Open Sound System -# +CONFIG_SND_VMASTER=y +CONFIG_SND_AC97_CODEC=y +# CONFIG_SND_DRIVERS is not set +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=y +# CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set # -# USB support +# MMC/SD/SDIO Card Drivers # -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set # -# USB Gadget Support +# MMC/SD/SDIO Host Controller Drivers # -# CONFIG_USB_GADGET is not set +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # -# MMC/SD Card support +# Voltage and Current regulators # -# CONFIG_MMC is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set # # File systems # # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -654,51 +801,59 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems # +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set -# CONFIG_JFFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFSD is not set +# CONFIG_NFS_V4 is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -739,26 +894,71 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_LL is not set # @@ -766,21 +966,106 @@ CONFIG_DEBUG_ERRORS=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set # -# Cryptographic options +# Compression # -# CONFIG_CRYPTO is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set # -# Hardware crypto devices +# Random Number Generation # +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig new file mode 100644 index 000000000000..cf3c1b5d7048 --- /dev/null +++ b/arch/arm/configs/s3c6400_defconfig @@ -0,0 +1,845 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-rc3 +# Mon Nov 3 10:10:30 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +CONFIG_NO_IOPORT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_LSF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +CONFIG_ARCH_S3C64XX=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +CONFIG_PLAT_S3C64XX=y +CONFIG_CPU_S3C6400_INIT=y +CONFIG_CPU_S3C6400_CLOCK=y +CONFIG_S3C64XX_SETUP_I2C0=y +CONFIG_S3C64XX_SETUP_I2C1=y +CONFIG_PLAT_S3C=y + +# +# Boot options +# +CONFIG_S3C_BOOT_ERROR_RESET=y + +# +# Power management +# +CONFIG_S3C_LOWLEVEL_UART_PORT=0 +CONFIG_S3C_GPIO_SPACE=0 +CONFIG_S3C_GPIO_TRACK=y +CONFIG_S3C_GPIO_PULL_UPDOWN=y +CONFIG_S3C_GPIO_CFG_S3C24XX=y +CONFIG_S3C_GPIO_CFG_S3C64XX=y +CONFIG_S3C_DEV_HSMMC=y +CONFIG_S3C_DEV_HSMMC1=y +CONFIG_S3C_DEV_I2C1=y +CONFIG_CPU_S3C6410=y +CONFIG_S3C6410_SETUP_SDHCI=y +CONFIG_MACH_SMDK6410=y +CONFIG_SMDK6410_SD_CH0=y +# CONFIG_SMDK6410_SD_CH1 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_V6=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_ARM_VIC=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/bin/bash initrd=0x51000000,4M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SAMSUNG=y +CONFIG_SERIAL_SAMSUNG_UARTS=4 +# CONFIG_SERIAL_SAMSUNG_DEBUG is not set +CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_S3C6400=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_S3C2410=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +CONFIG_AT24=y +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +# CONFIG_HID_COMPAT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +# CONFIG_USB_GADGET is not set +CONFIG_MMC=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_S3C=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_DEBUG_S3C_PORT=y +CONFIG_DEBUG_S3C_UART=0 + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/w90p910_defconfig b/arch/arm/configs/w90p910_defconfig new file mode 100644 index 000000000000..56bda7c6d670 --- /dev/null +++ b/arch/arm/configs/w90p910_defconfig @@ -0,0 +1,626 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc8-git8 +# Sat Nov 15 10:05:00 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +# CONFIG_GENERIC_GPIO is not set +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +CONFIG_USER_NS=y +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set +CONFIG_ARCH_W90X900=y + +# +# Boot options +# + +# +# Power management +# +CONFIG_CPU_W90P910=y + +# +# W90P910 Machines +# +CONFIG_MACH_W90P910EVB=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_TICK_ONESHOT is not set +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 initrd=0xa00000,4000000 mem=64M" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_W90X900=y +# CONFIG_SERIAL_W90X900_PORT1 is not set +# CONFIG_SERIAL_W90X900_PORT2 is not set +# CONFIG_SERIAL_W90X900_PORT3 is not set +# CONFIG_SERIAL_W90X900_PORT4 is not set +CONFIG_SERIAL_W90X900_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index de6c59f814a1..6cbd8fdc9f1f 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -10,11 +10,11 @@ #ifndef _ASMARM_CACHEFLUSH_H #define _ASMARM_CACHEFLUSH_H -#include <linux/sched.h> #include <linux/mm.h> #include <asm/glue.h> #include <asm/shmparam.h> +#include <asm/cachetype.h> #define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) @@ -296,16 +296,6 @@ static inline void outer_flush_range(unsigned long start, unsigned long end) #endif /* - * flush_cache_vmap() is used when creating mappings (eg, via vmap, - * vmalloc, ioremap etc) in kernel space for pages. Since the - * direct-mappings of these pages may contain cached data, we need - * to do a full cache flush to ensure that writebacks don't corrupt - * data placed into these pages via the new mappings. - */ -#define flush_cache_vmap(start, end) flush_cache_all() -#define flush_cache_vunmap(start, end) flush_cache_all() - -/* * Copy user data from/to a page which is mapped into a different * processes address space. Really, we want to allow our "user * space" model to handle this. @@ -444,4 +434,29 @@ static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt, dmac_inv_range(start, start + size); } +/* + * flush_cache_vmap() is used when creating mappings (eg, via vmap, + * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT + * caches, since the direct-mappings of these pages may contain cached + * data, we need to do a full cache flush to ensure that writebacks + * don't corrupt data placed into these pages via the new mappings. + */ +static inline void flush_cache_vmap(unsigned long start, unsigned long end) +{ + if (!cache_is_vipt_nonaliasing()) + flush_cache_all(); + else + /* + * set_pte_at() called from vmap_pte_range() does not + * have a DSB after cleaning the cache line. + */ + dsb(); +} + +static inline void flush_cache_vunmap(unsigned long start, unsigned long end) +{ + if (!cache_is_vipt_nonaliasing()) + flush_cache_all(); +} + #endif diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h new file mode 100644 index 000000000000..b6ec7c627b39 --- /dev/null +++ b/arch/arm/include/asm/clkdev.h @@ -0,0 +1,30 @@ +/* + * arch/arm/include/asm/clkdev.h + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ +#ifndef __ASM_CLKDEV_H +#define __ASM_CLKDEV_H + +struct clk; + +struct clk_lookup { + struct list_head node; + const char *dev_id; + const char *con_id; + struct clk *clk; +}; + +struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, + const char *dev_fmt, ...); + +void clkdev_add(struct clk_lookup *cl); +void clkdev_drop(struct clk_lookup *cl); + +#endif diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 4ed149cbb32a..22cb14ec3438 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -69,7 +69,9 @@ extern void dma_cache_maint(const void *kaddr, size_t size, int rw); */ static inline int dma_supported(struct device *dev, u64 mask) { - return dev->dma_mask && *dev->dma_mask != 0; + if (mask < ISA_DMA_THRESHOLD) + return 0; + return 1; } static inline int dma_set_mask(struct device *dev, u64 dma_mask) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index 75154b193117..df5638f3643a 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -1,12 +1,7 @@ #ifndef __ASM_ARM_DMA_H #define __ASM_ARM_DMA_H -typedef unsigned int dmach_t; - -#include <linux/spinlock.h> -#include <asm/system.h> -#include <asm/scatterlist.h> -#include <mach/dma.h> +#include <asm/memory.h> /* * This is the maximum virtual address which can be DMA'd from. @@ -15,6 +10,19 @@ typedef unsigned int dmach_t; #define MAX_DMA_ADDRESS 0xffffffff #endif +#ifdef CONFIG_ISA_DMA_API +/* + * This is used to support drivers written for the x86 ISA DMA API. + * It should not be re-used except for that purpose. + */ +#include <linux/spinlock.h> +#include <asm/system.h> +#include <asm/scatterlist.h> + +typedef unsigned int dmach_t; + +#include <mach/isa-dma.h> + /* * DMA modes */ @@ -140,4 +148,6 @@ extern int isa_dma_bridge_buggy; #define isa_dma_bridge_buggy (0) #endif -#endif /* _ARM_DMA_H */ +#endif /* CONFIG_ISA_DMA_API */ + +#endif /* __ASM_ARM_DMA_H */ diff --git a/arch/arm/include/asm/hardware/iomd.h b/arch/arm/include/asm/hardware/iomd.h index 9c5afbd71a69..f9ee69e4f53e 100644 --- a/arch/arm/include/asm/hardware/iomd.h +++ b/arch/arm/include/asm/hardware/iomd.h @@ -32,19 +32,11 @@ #define IOMD_KARTRX (0x004) #define IOMD_KCTRL (0x008) -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_IOLINES (0x00C) -#endif - #define IOMD_IRQSTATA (0x010) #define IOMD_IRQREQA (0x014) #define IOMD_IRQCLRA (0x014) #define IOMD_IRQMASKA (0x018) -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_SUSMODE (0x01C) -#endif - #define IOMD_IRQSTATB (0x020) #define IOMD_IRQREQB (0x024) #define IOMD_IRQMASKB (0x028) @@ -53,10 +45,6 @@ #define IOMD_FIQREQ (0x034) #define IOMD_FIQMASK (0x038) -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_CLKCTL (0x03C) -#endif - #define IOMD_T0CNTL (0x040) #define IOMD_T0LTCHL (0x040) #define IOMD_T0CNTH (0x044) @@ -71,18 +59,6 @@ #define IOMD_T1GO (0x058) #define IOMD_T1LATCH (0x05c) -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_IRQSTATC (0x060) -#define IOMD_IRQREQC (0x064) -#define IOMD_IRQMASKC (0x068) - -#define IOMD_VIDMUX (0x06c) - -#define IOMD_IRQSTATD (0x070) -#define IOMD_IRQREQD (0x074) -#define IOMD_IRQMASKD (0x078) -#endif - #define IOMD_ROMCR0 (0x080) #define IOMD_ROMCR1 (0x084) #ifdef CONFIG_ARCH_RPC @@ -100,11 +76,6 @@ #define IOMD_MOUSEY (0x0A4) #endif -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_MSEDAT (0x0A8) -#define IOMD_MSECTL (0x0Ac) -#endif - #ifdef CONFIG_ARCH_RPC #define IOMD_DMATCR (0x0C0) #endif @@ -113,18 +84,6 @@ #ifdef CONFIG_ARCH_RPC #define IOMD_DMAEXT (0x0CC) #endif -#ifdef CONFIG_ARCH_CLPS7500 -#define IOMD_ASTCR (0x0CC) -#define IOMD_DRAMCR (0x0D0) -#define IOMD_SELFREF (0x0D4) -#define IOMD_ATODICR (0x0E0) -#define IOMD_ATODSR (0x0E4) -#define IOMD_ATODCC (0x0E8) -#define IOMD_ATODCNT1 (0x0EC) -#define IOMD_ATODCNT2 (0x0F0) -#define IOMD_ATODCNT3 (0x0F4) -#define IOMD_ATODCNT4 (0x0F8) -#endif #ifdef CONFIG_ARCH_RPC #define DMA_EXT_IO0 1 diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index 263f2c362a30..f87328d4a180 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h @@ -29,15 +29,17 @@ #define VIC_INT_SOFT 0x18 #define VIC_INT_SOFT_CLEAR 0x1c #define VIC_PROTECT 0x20 -#define VIC_VECT_ADDR 0x30 -#define VIC_DEF_VECT_ADDR 0x34 +#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ +#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ #define VIC_ITCR 0x300 /* VIC test control register */ #define VIC_VECT_CNTL_ENABLE (1 << 5) +#define VIC_PL192_VECT_ADDR 0xF00 + #ifndef __ASSEMBLY__ void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources); #endif diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h index 81f4c899a555..bda489f9f017 100644 --- a/arch/arm/include/asm/hwcap.h +++ b/arch/arm/include/asm/hwcap.h @@ -16,6 +16,7 @@ #define HWCAP_IWMMXT 512 #define HWCAP_CRUNCH 1024 #define HWCAP_THUMBEE 2048 +#define HWCAP_NEON 4096 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) /* diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index a8094451be57..d2a59cfc30ce 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -80,6 +80,14 @@ extern void __iounmap(volatile void __iomem *addr); extern void __readwrite_bug(const char *fn); /* + * A typesafe __io() helper + */ +static inline void __iomem *__typesafe_io(unsigned long addr) +{ + return (void __iomem *)addr; +} + +/* * Now, pick up the machine-defined IO definitions */ #include <mach/io.h> diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index a0009aa5d157..328f14a8b790 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -7,10 +7,6 @@ #define irq_canonicalize(i) (i) #endif -#ifndef NR_IRQS -#define NR_IRQS 128 -#endif - /* * Use this value to indicate lack of interrupt * capability diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 77764301844b..0202a7c20e62 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -112,10 +112,8 @@ * private definitions which should NOT be used outside memory.h * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. */ -#ifndef __virt_to_phys #define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) -#endif /* * Convert a physical address to a Page Frame Number and back @@ -180,6 +178,11 @@ static inline void *phys_to_virt(unsigned long x) * memory. Use of these is *deprecated* (and that doesn't mean * use the __ prefixed forms instead.) See dma-mapping.h. */ +#ifndef __virt_to_bus +#define __virt_to_bus __virt_to_phys +#define __bus_to_virt __phys_to_virt +#endif + static inline __deprecated unsigned long virt_to_bus(void *x) { return __virt_to_bus((unsigned long)x); diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index 0559f37c2a27..263fed05ea33 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -14,6 +14,7 @@ #define __ASM_ARM_MMU_CONTEXT_H #include <linux/compiler.h> +#include <linux/sched.h> #include <asm/cacheflush.h> #include <asm/cachetype.h> #include <asm/proc-fns.h> diff --git a/arch/arm/include/asm/mtd-xip.h b/arch/arm/include/asm/mtd-xip.h index d8fbe2d9b8b9..d79d66d2cf71 100644 --- a/arch/arm/include/asm/mtd-xip.h +++ b/arch/arm/include/asm/mtd-xip.h @@ -15,7 +15,6 @@ #ifndef __ARM_MTD_XIP_H__ #define __ARM_MTD_XIP_H__ -#include <mach/hardware.h> #include <mach/mtd-xip.h> /* fill instruction prefetch */ diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index bed1c0a00368..f341c9dbd662 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -108,32 +108,38 @@ #error Unknown user operations model #endif +struct page; + struct cpu_user_fns { - void (*cpu_clear_user_page)(void *p, unsigned long user); - void (*cpu_copy_user_page)(void *to, const void *from, - unsigned long user); + void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr); + void (*cpu_copy_user_highpage)(struct page *to, struct page *from, + unsigned long vaddr); }; #ifdef MULTI_USER extern struct cpu_user_fns cpu_user; -#define __cpu_clear_user_page cpu_user.cpu_clear_user_page -#define __cpu_copy_user_page cpu_user.cpu_copy_user_page +#define __cpu_clear_user_highpage cpu_user.cpu_clear_user_highpage +#define __cpu_copy_user_highpage cpu_user.cpu_copy_user_highpage #else -#define __cpu_clear_user_page __glue(_USER,_clear_user_page) -#define __cpu_copy_user_page __glue(_USER,_copy_user_page) +#define __cpu_clear_user_highpage __glue(_USER,_clear_user_highpage) +#define __cpu_copy_user_highpage __glue(_USER,_copy_user_highpage) -extern void __cpu_clear_user_page(void *p, unsigned long user); -extern void __cpu_copy_user_page(void *to, const void *from, - unsigned long user); +extern void __cpu_clear_user_highpage(struct page *page, unsigned long vaddr); +extern void __cpu_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr); #endif -#define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) -#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) +#define clear_user_highpage(page,vaddr) \ + __cpu_clear_user_highpage(page, vaddr) + +#define __HAVE_ARCH_COPY_USER_HIGHPAGE +#define copy_user_highpage(to,from,vaddr,vma) \ + __cpu_copy_user_highpage(to, from, vaddr) -#define clear_page(page) memzero((void *)(page), PAGE_SIZE) +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) extern void copy_page(void *to, const void *from); #undef STRICT_MM_TYPECHECKS diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 6ff33790f47b..1845892260e7 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -64,7 +64,7 @@ struct thread_struct { ({ \ unsigned long *stack = (unsigned long *)sp; \ set_fs(USER_DS); \ - memzero(regs->uregs, sizeof(regs->uregs)); \ + memset(regs->uregs, 0, sizeof(regs->uregs)); \ if (current->personality & ADDR_LIMIT_32BIT) \ regs->ARM_cpsr = USR_MODE; \ else \ diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index a65413ba121d..f2cd18a0932b 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -209,9 +209,11 @@ struct meminfo { struct membank bank[NR_BANKS]; }; +extern struct meminfo meminfo; + #define for_each_nodebank(iter,mi,no) \ - for (iter = 0; iter < mi->nr_banks; iter++) \ - if (mi->bank[iter].node == no) + for (iter = 0; iter < (mi)->nr_banks; iter++) \ + if ((mi)->bank[iter].node == no) #define bank_pfn_start(bank) __phys_to_pfn((bank)->start) #define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size) diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 727b5c042e52..fad70da5911d 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -114,7 +114,7 @@ extern void local_timer_interrupt(void); /* * Stop a local timer interrupt. */ -extern void local_timer_stop(unsigned int cpu); +extern void local_timer_stop(void); /* * Platform provides this to acknowledge a local timer IRQ @@ -123,7 +123,7 @@ extern int local_timer_ack(void); #else -static inline void local_timer_stop(unsigned int cpu) +static inline void local_timer_stop(void) { } @@ -132,7 +132,7 @@ static inline void local_timer_stop(unsigned int cpu) /* * Setup a local timer interrupt for a CPU. */ -extern void local_timer_setup(unsigned int cpu); +extern void local_timer_setup(void); /* * show local interrupt info diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h index e50c4a39b699..cf4f3aad0fc1 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h @@ -21,7 +21,6 @@ extern void * memmove(void *, const void *, __kernel_size_t); #define __HAVE_ARCH_MEMCHR extern void * memchr(const void *, int, __kernel_size_t); -#define __HAVE_ARCH_MEMZERO #define __HAVE_ARCH_MEMSET extern void * memset(void *, int, __kernel_size_t); @@ -39,12 +38,4 @@ extern void __memzero(void *ptr, __kernel_size_t n); (__p); \ }) -#define memzero(p,n) \ - ({ \ - void *__p = (p); size_t __n = n; \ - if ((__n) != 0) \ - __memzero((__p),(__n)); \ - (__p); \ - }) - #endif diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 568020b34e3e..811be55f338e 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -3,8 +3,6 @@ #ifdef __KERNEL__ -#include <asm/memory.h> - #define CPU_ARCH_UNKNOWN 0 #define CPU_ARCH_ARMv3 1 #define CPU_ARCH_ARMv4 2 diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index e98ec60b3400..7897464e0c24 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -11,7 +11,8 @@ /* * User space memory access functions */ -#include <linux/sched.h> +#include <linux/string.h> +#include <linux/thread_info.h> #include <asm/errno.h> #include <asm/memory.h> #include <asm/domain.h> @@ -400,7 +401,7 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u if (access_ok(VERIFY_READ, from, n)) n = __copy_from_user(to, from, n); else /* security hole - plug it */ - memzero(to, n); + memset(to, 0, n); return n; } diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 23af3c972c9a..531e1860e546 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ #include <linux/module.h> +#include <linux/sched.h> #include <linux/string.h> #include <linux/cryptohash.h> #include <linux/delay.h> diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 6c90479e8974..c63842766229 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -95,7 +95,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } -/* run from kstop_machine */ +/* run from ftrace_init with irqs disabled */ int __init ftrace_dyn_arch_init(void *data) { ftrace_mcount_set(data); diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index bde52df1c668..991952c644d1 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -18,7 +18,7 @@ __switch_data: .long __mmap_switched .long __data_loc @ r4 - .long __data_start @ r5 + .long _data @ r5 .long __bss_start @ r6 .long _end @ r7 .long processor_id @ r4 diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index b8d965dcd6fd..dab48f27263f 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -21,6 +21,7 @@ #include <linux/string.h> #include <asm/pgtable.h> +#include <asm/sections.h> #ifdef CONFIG_XIP_KERNEL /* @@ -29,9 +30,8 @@ * MODULES_VADDR is redefined here and not in asm/memory.h to avoid * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. */ -extern void _etext; #undef MODULES_VADDR -#define MODULES_VADDR (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK) +#define MODULES_VADDR (((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK) #endif #ifdef CONFIG_MMU diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1f1eecca7f55..7049815d66d5 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -29,6 +29,7 @@ #include <asm/cputype.h> #include <asm/elf.h> #include <asm/procinfo.h> +#include <asm/sections.h> #include <asm/setup.h> #include <asm/mach-types.h> #include <asm/cacheflush.h> @@ -59,9 +60,8 @@ static int __init fpe_setup(char *line) __setup("fpe=", fpe_setup); #endif -extern void paging_init(struct meminfo *, struct machine_desc *desc); +extern void paging_init(struct machine_desc *desc); extern void reboot_setup(char *str); -extern void _text, _etext, __data_start, _edata, _end; unsigned int processor_id; EXPORT_SYMBOL(processor_id); @@ -112,7 +112,6 @@ static struct stack stacks[NR_CPUS]; char elf_platform[ELF_PLATFORM_SIZE]; EXPORT_SYMBOL(elf_platform); -static struct meminfo meminfo __initdata = { 0, }; static const char *cpu_name; static const char *machine_name; static char __initdata command_line[COMMAND_LINE_SIZE]; @@ -367,21 +366,34 @@ static struct machine_desc * __init setup_machine(unsigned int nr) return list; } -static void __init arm_add_memory(unsigned long start, unsigned long size) +static int __init arm_add_memory(unsigned long start, unsigned long size) { - struct membank *bank; + struct membank *bank = &meminfo.bank[meminfo.nr_banks]; + + if (meminfo.nr_banks >= NR_BANKS) { + printk(KERN_CRIT "NR_BANKS too low, " + "ignoring memory at %#lx\n", start); + return -EINVAL; + } /* * Ensure that start/size are aligned to a page boundary. * Size is appropriately rounded down, start is rounded up. */ size -= start & ~PAGE_MASK; - - bank = &meminfo.bank[meminfo.nr_banks++]; - bank->start = PAGE_ALIGN(start); bank->size = size & PAGE_MASK; bank->node = PHYS_TO_NID(start); + + /* + * Check whether this memory region has non-zero size or + * invalid node number. + */ + if (bank->size == 0 || bank->node >= MAX_NUMNODES) + return -EINVAL; + + meminfo.nr_banks++; + return 0; } /* @@ -472,10 +484,10 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) struct resource *res; int i; - kernel_code.start = virt_to_phys(&_text); - kernel_code.end = virt_to_phys(&_etext - 1); - kernel_data.start = virt_to_phys(&__data_start); - kernel_data.end = virt_to_phys(&_end - 1); + kernel_code.start = virt_to_phys(_text); + kernel_code.end = virt_to_phys(_etext - 1); + kernel_data.start = virt_to_phys(_data); + kernel_data.end = virt_to_phys(_end - 1); for (i = 0; i < mi->nr_banks; i++) { if (mi->bank[i].size == 0) @@ -539,14 +551,7 @@ __tagtable(ATAG_CORE, parse_tag_core); static int __init parse_tag_mem32(const struct tag *tag) { - if (meminfo.nr_banks >= NR_BANKS) { - printk(KERN_WARNING - "Ignoring memory bank 0x%08x size %dKB\n", - tag->u.mem.start, tag->u.mem.size / 1024); - return -EINVAL; - } - arm_add_memory(tag->u.mem.start, tag->u.mem.size); - return 0; + return arm_add_memory(tag->u.mem.start, tag->u.mem.size); } __tagtable(ATAG_MEM, parse_tag_mem32); @@ -710,15 +715,15 @@ void __init setup_arch(char **cmdline_p) parse_tags(tags); } - init_mm.start_code = (unsigned long) &_text; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) &_end; + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; memcpy(boot_command_line, from, COMMAND_LINE_SIZE); boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(cmdline_p, from); - paging_init(&meminfo, mdesc); + paging_init(mdesc); request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_SMP @@ -772,6 +777,8 @@ static const char *hwcap_str[] = { "java", "iwmmxt", "crunch", + "thumbee", + "neon", NULL }; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e42a749a56dd..019237d21622 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -181,7 +181,7 @@ int __cpuexit __cpu_disable(void) /* * Stop the local timer for this CPU. */ - local_timer_stop(cpu); + local_timer_stop(); /* * Flush user cache and TLB mappings, and then remove this CPU @@ -284,7 +284,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) /* * Setup local timer for this CPU. */ - local_timer_setup(cpu); + local_timer_setup(); calibrate_delay(); diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c index df3f6b7ebcea..9cb7aaca159f 100644 --- a/arch/arm/kernel/thumbee.c +++ b/arch/arm/kernel/thumbee.c @@ -25,7 +25,7 @@ /* * Access to the ThumbEE Handler Base register */ -static inline unsigned long teehbr_read() +static inline unsigned long teehbr_read(void) { unsigned long v; asm("mrc p14, 6, %0, c1, c0, 0\n" : "=r" (v)); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4898bdcfe7dd..00216071eaf7 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -119,7 +119,7 @@ SECTIONS #endif .data : AT(__data_loc) { - __data_start = .; /* address in memory */ + _data = .; /* address in memory */ /* * first, the init task union, aligned diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 30351cd4560d..866f84a586ff 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -38,7 +38,6 @@ else endif lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o -lib-$(CONFIG_ARCH_CLPS7500) += io-acorn.o lib-$(CONFIG_ARCH_L7200) += io-acorn.o lib-$(CONFIG_ARCH_SHARK) += io-shark.o diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 761eefa76243..650d5923ab83 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -25,7 +25,7 @@ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) /* * The pointer is now aligned and the length is adjusted. Try doing the - * memzero again. + * memset again. */ ENTRY(memset) diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile index a8e462f58bc9..20ec83896c37 100644 --- a/arch/arm/mach-aaec2000/Makefile +++ b/arch/arm/mach-aaec2000/Makefile @@ -3,7 +3,7 @@ # # Common support (must be linked before board specific support) -obj-y += core.o clock.o +obj-y += core.o # Specific board support obj-$(CONFIG_MACH_AAED2000) += aaed2000.o diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c deleted file mode 100644 index e10ee158d720..000000000000 --- a/arch/arm/mach-aaec2000/clock.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * linux/arch/arm/mach-aaec2000/clock.c - * - * Copyright (C) 2005 Nicolas Bellido Y Ortega - * - * Based on linux/arch/arm/mach-integrator/clock.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/string.h> -#include <linux/clk.h> -#include <linux/mutex.h> - -#include "clock.h" - -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - return rate; -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return 0; -} -EXPORT_SYMBOL(clk_set_rate); - -int clk_register(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init(void) -{ - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-aaec2000/clock.h b/arch/arm/mach-aaec2000/clock.h deleted file mode 100644 index d4bb74ff613f..000000000000 --- a/arch/arm/mach-aaec2000/clock.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * linux/arch/arm/mach-aaec2000/clock.h - * - * Copyright (C) 2005 Nicolas Bellido Y Ortega - * - * Based on linux/arch/arm/mach-integrator/clock.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -struct module; - -struct clk { - struct list_head node; - unsigned long rate; - struct module *owner; - const char *name; - void *data; -}; - -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c index dfb26bc23d1a..50e13965dfed 100644 --- a/arch/arm/mach-aaec2000/core.c +++ b/arch/arm/mach-aaec2000/core.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/timex.h> #include <linux/signal.h> +#include <linux/clk.h> #include <mach/hardware.h> #include <asm/irq.h> @@ -30,7 +31,6 @@ #include <asm/mach/map.h> #include "core.h" -#include "clock.h" /* * Common I/O mapping: @@ -229,9 +229,28 @@ static struct amba_device *amba_devs[] __initdata = { &clcd_device, }; -static struct clk aaec2000_clcd_clk = { - .name = "CLCDCLK", -}; +void clk_disable(struct clk *clk) +{ +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +int clk_enable(struct clk *clk) +{ + return 0; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + return dev && strcmp(dev_name(dev), "mb:16") == 0 ? NULL : ERR_PTR(-ENOENT); +} + +void clk_put(struct clk *clk) +{ +} void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *clcd) { @@ -265,8 +284,6 @@ static int __init aaec2000_init(void) { int i; - clk_register(&aaec2000_clcd_clk); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; amba_device_register(d, &iomem_resource); diff --git a/arch/arm/mach-aaec2000/include/mach/dma.h b/arch/arm/mach-aaec2000/include/mach/dma.h deleted file mode 100644 index 2da846c72fe7..000000000000 --- a/arch/arm/mach-aaec2000/include/mach/dma.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * arch/arm/mach-aaec2000/include/mach/dma.h - * - * Copyright (c) 2005 Nicolas Bellido Y Ortega - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ diff --git a/arch/arm/mach-aaec2000/include/mach/io.h b/arch/arm/mach-aaec2000/include/mach/io.h index c87c24de1110..ab4fe5d20eaf 100644 --- a/arch/arm/mach-aaec2000/include/mach/io.h +++ b/arch/arm/mach-aaec2000/include/mach/io.h @@ -6,15 +6,13 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff /* * We don't actually have real ISA nor PCI buses, but there is so many * drivers out there that might just work if we fake them... */ -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-aaec2000/include/mach/memory.h b/arch/arm/mach-aaec2000/include/mach/memory.h index 56ae900a482e..c00822543d9f 100644 --- a/arch/arm/mach-aaec2000/include/mach/memory.h +++ b/arch/arm/mach-aaec2000/include/mach/memory.h @@ -14,9 +14,6 @@ #define PHYS_OFFSET UL(0xf0000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - /* * The nodes are the followings: * diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 5aafb2e2ca7a..323b47f2b52f 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -7,36 +7,43 @@ choice config ARCH_AT91RM9200 bool "AT91RM9200" + select CPU_ARM920T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91SAM9260 bool "AT91SAM9260 or AT91SAM9XE" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91SAM9261 bool "AT91SAM9261" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91SAM9263 bool "AT91SAM9263" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91SAM9RL bool "AT91SAM9RL" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91SAM9G20 bool "AT91SAM9G20" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91CAP9 bool "AT91CAP9" + select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -235,6 +242,12 @@ config MACH_USB_A9263 Select this if you are using a Calao Systems USB-A9263. <http://www.calao-systems.com> +config MACH_NEOCORE926 + bool "Adeneo NEOCORE926" + depends on ARCH_AT91SAM9263 + help + Select this if you are using the Adeneo Neocore 926 board. + endif # ---------------------------------------------------------- @@ -302,7 +315,7 @@ comment "AT91 Board Options" config MTD_AT91_DATAFLASH_CARD bool "Enable DataFlash Card support" - depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_ECBAT91 || MACH_SAM9_L9260 || MACH_AT91CAP9ADK) + depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_ECBAT91 || MACH_SAM9_L9260 || MACH_AT91CAP9ADK || MACH_NEOCORE926) help Enable support for the DataFlash card. diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index cca612d97ca2..c69ff237fd14 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -11,12 +11,12 @@ obj-$(CONFIG_AT91_PMC_UNIT) += clock.o # CPU-specific support obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o -obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o -obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o -obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o -obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o -obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o -obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o # AT91RM9200 board-specific support @@ -47,6 +47,7 @@ obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o # AT91SAM9263 board-specific support obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o obj-$(CONFIG_MACH_USB_A9263) += board-usb-a9263.o +obj-$(CONFIG_MACH_NEOCORE926) += board-neocore926.o # AT91SAM9RL board-specific support obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index 0fc0adaebd58..0a38c69fdbc4 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -17,6 +17,8 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> + +#include <mach/cpu.h> #include <mach/at91cap9.h> #include <mach/at91_pmc.h> #include <mach/at91_rstc.h> @@ -317,6 +319,12 @@ void __init at91cap9_initialize(unsigned long main_clock) /* Register GPIO subsystem */ at91_gpio_init(at91cap9_gpio, 4); + + /* Remember the silicon revision */ + if (cpu_is_at91cap9_revB()) + system_rev = 0xB; + else if (cpu_is_at91cap9_revC()) + system_rev = 0xC; } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index 5ebd4273d353..9eca2209cde6 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -13,6 +13,7 @@ */ #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/mach/irq.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> @@ -21,6 +22,7 @@ #include <video/atmel_lcdc.h> #include <mach/board.h> +#include <mach/cpu.h> #include <mach/gpio.h> #include <mach/at91cap9.h> #include <mach/at91cap9_matrix.h> @@ -69,6 +71,9 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) if (!data) return; + if (cpu_is_at91cap9_revB()) + set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH); + /* Enable VBus control for UHP ports */ for (i = 0; i < data->ports; i++) { if (data->vbus_pin[i]) @@ -151,8 +156,13 @@ static struct platform_device at91_usba_udc_device = { void __init at91_add_device_usba(struct usba_platform_data *data) { - at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS | - AT91_MATRIX_UDPHS_BYPASS_LOCK); + if (cpu_is_at91cap9_revB()) { + set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH); + at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS | + AT91_MATRIX_UDPHS_BYPASS_LOCK); + } + else + at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS); /* * Invalid pins are 0 on AT91, but the usba driver is shared @@ -406,28 +416,13 @@ static struct platform_device at91cap9_nand_device = { void __init at91_add_device_nand(struct atmel_nand_data *data) { - unsigned long csa, mode; + unsigned long csa; if (!data) return; csa = at91_sys_read(AT91_MATRIX_EBICSA); - at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA | AT91_MATRIX_EBI_VDDIOMSEL_3_3V); - - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(1) - | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(1)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(6) - | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(6)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(8) | AT91_SMC_NRDCYCLE_(8)); - - if (data->bus_width_16) - mode = AT91_SMC_DBW_16; - else - mode = AT91_SMC_DBW_8; - at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); /* enable pin */ if (data->enable_pin) @@ -865,6 +860,9 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) if (!data) return; + if (cpu_is_at91cap9_revB()) + set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH); + at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */ at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */ at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDDEN */ diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index a72e798a2a40..d140eae53ded 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -141,6 +141,15 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) /* Use "raw" primitives so we behave correctly on RT kernels. */ raw_local_irq_save(flags); + /* + * According to Thomas Gleixner irqs are already disabled here. Simply + * removing raw_local_irq_save above (and the matching + * raw_local_irq_restore) was not accepted. See + * http://thread.gmane.org/gmane.linux.ports.arm.kernel/41174 + * So for now (2008-11-20) just warn once if irqs were not disabled ... + */ + WARN_ON_ONCE(!raw_irqs_disabled_flags(flags)); + /* The alarm IRQ uses absolute time (now+delta), not the relative * time (delta) in our calling convention. Like all clockevents * using such "match" hardware, we have a race to defend against. diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 7774d17dde74..fdde1ea21b07 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -313,7 +313,7 @@ static struct platform_device at91sam9260_nand_device = { void __init at91_add_device_nand(struct atmel_nand_data *data) { - unsigned long csa, mode; + unsigned long csa; if (!data) return; @@ -321,42 +321,6 @@ void __init at91_add_device_nand(struct atmel_nand_data *data) csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); - if (cpu_is_at91sam9260()) { - /* Timing for sam9260 */ - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) - | AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) - | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); - - if (data->bus_width_16) - mode = AT91_SMC_DBW_16; - else - mode = AT91_SMC_DBW_8; - at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); - } - - if (cpu_is_at91sam9g20()) { - /* Timing for sam9g20 */ - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) - | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(4) - | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(4)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); - - if (data->bus_width_16) - mode = AT91_SMC_DBW_16; - else - mode = AT91_SMC_DBW_8; - at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(3)); - } - /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 6b89172310c7..17289756f80f 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -223,7 +223,7 @@ static struct platform_device atmel_nand_device = { void __init at91_add_device_nand(struct atmel_nand_data *data) { - unsigned long csa, mode; + unsigned long csa; if (!data) return; @@ -231,21 +231,6 @@ void __init at91_add_device_nand(struct atmel_nand_data *data) csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) - | AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) - | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); - - if (data->bus_width_16) - mode = AT91_SMC_DBW_16; - else - mode = AT91_SMC_DBW_8; - at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); - /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 8b884083f76d..b753cb879d8e 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -382,7 +382,7 @@ static struct platform_device at91sam9263_nand_device = { void __init at91_add_device_nand(struct atmel_nand_data *data) { - unsigned long csa, mode; + unsigned long csa; if (!data) return; @@ -390,21 +390,6 @@ void __init at91_add_device_nand(struct atmel_nand_data *data) csa = at91_sys_read(AT91_MATRIX_EBI0CSA); at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA); - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) - | AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) - | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); - - if (data->bus_width_16) - mode = AT91_SMC_DBW_16; - else - mode = AT91_SMC_DBW_8; - at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); - /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 87deb1e1b529..145324f4ec56 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -232,17 +232,6 @@ void __init at91_add_device_nand(struct atmel_nand_data *data) csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) - | AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0)); - - at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) - | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); - - at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); - - at91_sys_write(AT91_SMC_MODE(3), AT91_SMC_DBW_8 | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); - /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index cdddca54b938..d3ba29c5d8c8 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -39,7 +39,9 @@ #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include "sam9_smc.h" #include "generic.h" @@ -151,6 +153,32 @@ static struct atmel_nand_data __initdata cam60_nand_data = { .partition_info = nand_partitions, }; +static struct sam9_smc_config __initdata cam60_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init cam60_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &cam60_nand_smc_config); + + at91_add_device_nand(&cam60_nand_data); +} + static void __init cam60_board_init(void) { @@ -165,7 +193,7 @@ static void __init cam60_board_init(void) at91_set_gpio_output(AT91_PIN_PB18, 1); at91_add_device_usbh(&cam60_usbh_data); /* NAND */ - at91_add_device_nand(&cam60_nand_data); + cam60_add_device_nand(); } MACHINE_START(CAM60, "KwikByte CAM60") diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index 201b89392dcc..83a1a0fef47b 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -36,17 +36,16 @@ #include <mach/hardware.h> #include <asm/setup.h> #include <asm/mach-types.h> -#include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/mach/irq.h> #include <mach/board.h> #include <mach/gpio.h> #include <mach/at91cap9_matrix.h> #include <mach/at91sam9_smc.h> +#include "sam9_smc.h" #include "generic.h" @@ -195,6 +194,43 @@ static struct atmel_nand_data __initdata cap9adk_nand_data = { #endif }; +static struct sam9_smc_config __initdata cap9adk_nand_smc_config = { + .ncs_read_setup = 1, + .nrd_setup = 2, + .ncs_write_setup = 1, + .nwe_setup = 2, + + .ncs_read_pulse = 6, + .nrd_pulse = 4, + .ncs_write_pulse = 6, + .nwe_pulse = 4, + + .read_cycle = 8, + .write_cycle = 8, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 1, +}; + +static void __init cap9adk_add_device_nand(void) +{ + unsigned long csa; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V); + + /* setup bus-width (8 or 16) */ + if (cap9adk_nand_data.bus_width_16) + cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &cap9adk_nand_smc_config); + + at91_add_device_nand(&cap9adk_nand_data); +} + /* * NOR flash @@ -234,6 +270,24 @@ static struct platform_device cap9adk_nor_flash = { .num_resources = ARRAY_SIZE(nor_flash_resources), }; +static struct sam9_smc_config __initdata cap9adk_nor_smc_config = { + .ncs_read_setup = 2, + .nrd_setup = 4, + .ncs_write_setup = 2, + .nwe_setup = 4, + + .ncs_read_pulse = 10, + .nrd_pulse = 8, + .ncs_write_pulse = 10, + .nwe_pulse = 8, + + .read_cycle = 16, + .write_cycle = 16, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16, + .tdf_cycles = 1, +}; + static __init void cap9adk_add_device_nor(void) { unsigned long csa; @@ -241,18 +295,8 @@ static __init void cap9adk_add_device_nor(void) csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V); - /* set the bus interface characteristics */ - at91_sys_write(AT91_SMC_SETUP(0), AT91_SMC_NWESETUP_(4) | AT91_SMC_NCS_WRSETUP_(2) - | AT91_SMC_NRDSETUP_(4) | AT91_SMC_NCS_RDSETUP_(2)); - - at91_sys_write(AT91_SMC_PULSE(0), AT91_SMC_NWEPULSE_(8) | AT91_SMC_NCS_WRPULSE_(10) - | AT91_SMC_NRDPULSE_(8) | AT91_SMC_NCS_RDPULSE_(10)); - - at91_sys_write(AT91_SMC_CYCLE(0), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16)); - - at91_sys_write(AT91_SMC_MODE(0), AT91_SMC_READMODE | AT91_SMC_WRITEMODE - | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE - | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1)); + /* configure chip-select 0 (NOR) */ + sam9_smc_configure(0, &cap9adk_nor_smc_config); platform_device_register(&cap9adk_nor_flash); } @@ -330,10 +374,8 @@ static void __init cap9adk_board_init(void) /* Serial */ at91_add_device_serial(); /* USB Host */ - set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH); at91_add_device_usbh(&cap9adk_usbh_data); /* USB HS */ - set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH); at91_add_device_usba(&cap9adk_usba_udc_data); /* SPI */ at91_add_device_spi(cap9adk_spi_devices, ARRAY_SIZE(cap9adk_spi_devices)); @@ -344,13 +386,12 @@ static void __init cap9adk_board_init(void) /* Ethernet */ at91_add_device_eth(&cap9adk_macb_data); /* NAND */ - at91_add_device_nand(&cap9adk_nand_data); + cap9adk_add_device_nand(); /* NOR Flash */ cap9adk_add_device_nor(); /* I2C */ at91_add_device_i2c(NULL, 0); /* LCD Controller */ - set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH); at91_add_device_lcdc(&cap9adk_lcdc_data); /* AC97 */ at91_add_device_ac97(&cap9adk_ac97_data); diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c new file mode 100644 index 000000000000..9ba7ba2cc3b1 --- /dev/null +++ b/arch/arm/mach-at91/board-neocore926.c @@ -0,0 +1,397 @@ +/* + * linux/arch/arm/mach-at91/board-neocore926.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2007 Atmel Corporation + * Copyright (C) 2008 ADENEO. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> +#include <linux/fb.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> + +#include <video/atmel_lcdc.h> + +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> +#include <asm/sizes.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9_smc.h> + +#include "sam9_smc.h" +#include "generic.h" + + +static void __init neocore926_map_io(void) +{ + /* Initialize processor: 20 MHz crystal */ + at91sam9263_initialize(20000000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init neocore926_init_irq(void) +{ + at91sam9263_init_interrupts(NULL); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata neocore926_usbh_data = { + .ports = 2, + .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata neocore926_udc_data = { + .vbus_pin = AT91_PIN_PA25, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * ADS7846 Touchscreen + */ +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) +static int ads7843_pendown_state(void) +{ + return !at91_get_gpio_value(AT91_PIN_PA15); /* Touchscreen PENIRQ */ +} + +static struct ads7846_platform_data ads_info = { + .model = 7843, + .x_min = 150, + .x_max = 3830, + .y_min = 190, + .y_max = 3830, + .vref_delay_usecs = 100, + .x_plate_ohms = 450, + .y_plate_ohms = 250, + .pressure_max = 15000, + .debounce_max = 1, + .debounce_rep = 0, + .debounce_tol = (~0), + .get_pendown_state = ads7843_pendown_state, +}; + +static void __init neocore926_add_device_ts(void) +{ + at91_set_B_periph(AT91_PIN_PA15, 1); /* External IRQ1, with pullup */ + at91_set_gpio_input(AT91_PIN_PC13, 1); /* Touchscreen BUSY signal */ +} +#else +static void __init neocore926_add_device_ts(void) {} +#endif + +/* + * SPI devices. + */ +static struct spi_board_info neocore926_spi_devices[] = { +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#endif +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + { + .modalias = "ads7846", + .chip_select = 1, + .max_speed_hz = 125000 * 16, + .bus_num = 0, + .platform_data = &ads_info, + .irq = AT91SAM9263_ID_IRQ1, + }, +#endif +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata neocore926_mmc_data = { + .wire4 = 1, + .det_pin = AT91_PIN_PE18, + .wp_pin = AT91_PIN_PE19, +}; + + +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata neocore926_macb_data = { + .phy_irq_pin = AT91_PIN_PE31, + .is_rmii = 1, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata neocore926_nand_partition[] = { + { + .name = "Linux Kernel", /* "Partition 1", */ + .offset = 0, + .size = SZ_8M, + }, + { + .name = "Filesystem", /* "Partition 2", */ + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_32M, + }, + { + .name = "Free", /* "Partition 3", */ + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(neocore926_nand_partition); + return neocore926_nand_partition; +} + +static struct atmel_nand_data __initdata neocore926_nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PB19, + .rdy_pin_active_low = 1, + .enable_pin = AT91_PIN_PD15, + .partition_info = nand_partitions, +}; + +static struct sam9_smc_config __initdata neocore926_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 6, + .write_cycle = 6, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init neocore926_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &neocore926_nand_smc_config); + + at91_add_device_nand(&neocore926_nand_data); +} + + +/* + * LCD Controller + */ +#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) +static struct fb_videomode at91_tft_vga_modes[] = { + { + .name = "TX09D50VM1CCA @ 60", + .refresh = 60, + .xres = 240, .yres = 320, + .pixclock = KHZ2PICOS(5000), + + .left_margin = 1, .right_margin = 33, + .upper_margin = 1, .lower_margin = 0, + .hsync_len = 5, .vsync_len = 1, + + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs at91fb_default_monspecs = { + .manufacturer = "HIT", + .monitor = "TX09D70VM1CCA", + + .modedb = at91_tft_vga_modes, + .modedb_len = ARRAY_SIZE(at91_tft_vga_modes), + .hfmin = 15000, + .hfmax = 64000, + .vfmin = 50, + .vfmax = 150, +}; + +#define AT91SAM9263_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \ + | ATMEL_LCDC_DISTYPE_TFT \ + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) + +static void at91_lcdc_power_control(int on) +{ + at91_set_gpio_value(AT91_PIN_PA30, on); +} + +/* Driver datas */ +static struct atmel_lcdfb_info __initdata neocore926_lcdc_data = { + .lcdcon_is_backlight = true, + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN, + .default_lcdcon2 = AT91SAM9263_DEFAULT_LCDCON2, + .default_monspecs = &at91fb_default_monspecs, + .atmel_lcdfb_power_control = at91_lcdc_power_control, + .guard_time = 1, + .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB555, +}; + +#else +static struct atmel_lcdfb_info __initdata neocore926_lcdc_data; +#endif + + +/* + * GPIO Buttons + */ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button neocore926_buttons[] = { + { /* BP1, "leftclic" */ + .code = BTN_LEFT, + .gpio = AT91_PIN_PC5, + .active_low = 1, + .desc = "left_click", + .wakeup = 1, + }, + { /* BP2, "rightclic" */ + .code = BTN_RIGHT, + .gpio = AT91_PIN_PC4, + .active_low = 1, + .desc = "right_click", + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data neocore926_button_data = { + .buttons = neocore926_buttons, + .nbuttons = ARRAY_SIZE(neocore926_buttons), +}; + +static struct platform_device neocore926_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &neocore926_button_data, + } +}; + +static void __init neocore926_add_device_buttons(void) +{ + at91_set_GPIO_periph(AT91_PIN_PC5, 0); /* left button */ + at91_set_deglitch(AT91_PIN_PC5, 1); + at91_set_GPIO_periph(AT91_PIN_PC4, 0); /* right button */ + at91_set_deglitch(AT91_PIN_PC4, 1); + + platform_device_register(&neocore926_button_device); +} +#else +static void __init neocore926_add_device_buttons(void) {} +#endif + + +/* + * AC97 + */ +static struct atmel_ac97_data neocore926_ac97_data = { + .reset_pin = AT91_PIN_PA13, +}; + + +static void __init neocore926_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + + /* USB Host */ + at91_add_device_usbh(&neocore926_usbh_data); + + /* USB Device */ + at91_add_device_udc(&neocore926_udc_data); + + /* SPI */ + at91_set_gpio_output(AT91_PIN_PE20, 1); /* select spi0 clock */ + at91_add_device_spi(neocore926_spi_devices, ARRAY_SIZE(neocore926_spi_devices)); + + /* Touchscreen */ + neocore926_add_device_ts(); + + /* MMC */ + at91_add_device_mmc(1, &neocore926_mmc_data); + + /* Ethernet */ + at91_add_device_eth(&neocore926_macb_data); + + /* NAND */ + neocore926_add_device_nand(); + + /* I2C */ + at91_add_device_i2c(NULL, 0); + + /* LCD Controller */ + at91_add_device_lcdc(&neocore926_lcdc_data); + + /* Push Buttons */ + neocore926_add_device_buttons(); + + /* AC97 */ + at91_add_device_ac97(&neocore926_ac97_data); +} + +MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926") + /* Maintainer: ADENEO */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = neocore926_map_io, + .init_irq = neocore926_init_irq, + .init_machine = neocore926_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index cfb4571a2e27..4cff9a7e61d2 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -41,8 +41,10 @@ #include <mach/hardware.h> #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> #include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -147,13 +149,34 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * MCI (SD/MMC) */ @@ -227,7 +250,7 @@ static void __init ek_board_init(void) /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* I2C */ at91_add_device_i2c(NULL, 0); /* Ethernet */ diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 99bb4cc23a09..b48346977534 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -38,7 +38,9 @@ #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include "sam9_smc.h" #include "generic.h" @@ -148,13 +150,34 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * MCI (SD/MMC) @@ -178,7 +201,7 @@ static void __init ek_board_init(void) /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* MMC */ diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index b49eb6e4918a..93a0f8b100eb 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -42,7 +42,10 @@ #include <mach/hardware.h> #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -195,6 +198,38 @@ static struct atmel_nand_data __initdata ek_nand_data = { #endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* setup bus-width (8 or 16) */ + if (ek_nand_data.bus_width_16) + ek_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * MCI (SD/MMC) @@ -303,7 +338,7 @@ static void __init ek_board_init(void) /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* MMC */ diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 4977409d4fc6..d5266da55311 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -47,7 +47,9 @@ #include <mach/board.h> #include <mach/gpio.h> #include <mach/at91sam9_smc.h> +#include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -76,7 +78,7 @@ static void __init ek_init_irq(void) * DM9000 ethernet device */ #if defined(CONFIG_DM9000) -static struct resource at91sam9261_dm9000_resource[] = { +static struct resource dm9000_resource[] = { [0] = { .start = AT91_CHIPSELECT_2, .end = AT91_CHIPSELECT_2 + 3, @@ -98,27 +100,42 @@ static struct dm9000_plat_data dm9000_platdata = { .flags = DM9000_PLATF_16BITONLY, }; -static struct platform_device at91sam9261_dm9000_device = { +static struct platform_device dm9000_device = { .name = "dm9000", .id = 0, - .num_resources = ARRAY_SIZE(at91sam9261_dm9000_resource), - .resource = at91sam9261_dm9000_resource, + .num_resources = ARRAY_SIZE(dm9000_resource), + .resource = dm9000_resource, .dev = { .platform_data = &dm9000_platdata, } }; +/* + * SMC timings for the DM9000. + * Note: These timings were calculated for MASTER_CLOCK = 100000000 according to the DM9000 timings. + */ +static struct sam9_smc_config __initdata dm9000_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 8, + .nrd_pulse = 4, + .ncs_write_pulse = 8, + .nwe_pulse = 4, + + .read_cycle = 16, + .write_cycle = 16, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16, + .tdf_cycles = 1, +}; + static void __init ek_add_device_dm9000(void) { - /* - * Configure Chip-Select 2 on SMC for the DM9000. - * Note: These timings were calculated for MASTER_CLOCK = 100000000 - * according to the DM9000 timings. - */ - at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0)); - at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8)); - at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16)); - at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1)); + /* Configure chip-select 2 (DM9000) */ + sam9_smc_configure(2, &dm9000_smc_config); /* Configure Reset signal as output */ at91_set_gpio_output(AT91_PIN_PC10, 0); @@ -126,7 +143,7 @@ static void __init ek_add_device_dm9000(void) /* Configure Interrupt pin as input, no pull-up */ at91_set_gpio_input(AT91_PIN_PC11, 0); - platform_device_register(&at91sam9261_dm9000_device); + platform_device_register(&dm9000_device); } #else static void __init ek_add_device_dm9000(void) {} @@ -197,6 +214,39 @@ static struct atmel_nand_data __initdata ek_nand_data = { #endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* setup bus-width (8 or 16) */ + if (ek_nand_data.bus_width_16) + ek_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + + /* * ADS7846 Touchscreen */ @@ -525,7 +575,7 @@ static void __init ek_board_init(void) /* I2C */ at91_add_device_i2c(NULL, 0); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* DM9000 ethernet */ ek_add_device_dm9000(); diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 8354015c6a23..57d52528f224 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -46,7 +46,9 @@ #include <mach/board.h> #include <mach/gpio.h> #include <mach/at91sam9_smc.h> +#include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -203,6 +205,38 @@ static struct atmel_nand_data __initdata ek_nand_data = { #endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* setup bus-width (8 or 16) */ + if (ek_nand_data.bus_width_16) + ek_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * I2C devices @@ -385,7 +419,7 @@ static void __init ek_board_init(void) /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* I2C */ at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* LCD Controller */ diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index b588ead14d68..81439fe6fb3d 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -37,7 +37,9 @@ #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include "sam9_smc.h" #include "generic.h" @@ -156,6 +158,38 @@ static struct atmel_nand_data __initdata ek_nand_data = { #endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 3, +}; + +static void __init ek_add_device_nand(void) +{ + /* setup bus-width (8 or 16) */ + if (ek_nand_data.bus_width_16) + ek_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * MCI (SD/MMC) @@ -195,7 +229,7 @@ static void __init ek_board_init(void) /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* MMC */ diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 270851864308..9b937ee4815a 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -29,8 +29,9 @@ #include <mach/hardware.h> #include <mach/board.h> #include <mach/gpio.h> -#include <mach/at91sam9_smc.h> +#include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -103,9 +104,34 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PD17, .enable_pin = AT91_PIN_PB6, .partition_info = nand_partitions, - .bus_width_16 = 0, }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * SPI devices @@ -188,7 +214,7 @@ static void __init ek_board_init(void) /* I2C */ at91_add_device_i2c(NULL, 0); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); /* MMC */ diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c index 7c350357333a..d13304c0bc45 100644 --- a/arch/arm/mach-at91/board-usb-a9260.c +++ b/arch/arm/mach-at91/board-usb-a9260.c @@ -41,8 +41,10 @@ #include <mach/hardware.h> #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> #include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -121,13 +123,34 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + /* * GPIO Buttons */ @@ -189,7 +212,7 @@ static void __init ek_board_init(void) /* USB Device */ at91_add_device_udc(&ek_udc_data); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* I2C */ at91_add_device_i2c(NULL, 0); /* Ethernet */ diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c index 391b566c4571..d96405b7d578 100644 --- a/arch/arm/mach-at91/board-usb-a9263.c +++ b/arch/arm/mach-at91/board-usb-a9263.c @@ -40,8 +40,10 @@ #include <mach/hardware.h> #include <mach/board.h> #include <mach/gpio.h> +#include <mach/at91sam9_smc.h> #include <mach/at91_shdwc.h> +#include "sam9_smc.h" #include "generic.h" @@ -134,13 +136,35 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif }; +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init ek_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + + /* * GPIO Buttons */ @@ -206,7 +230,7 @@ static void __init ek_board_init(void) /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* NAND */ - at91_add_device_nand(&ek_nand_data); + ek_add_device_nand(); /* I2C */ at91_add_device_i2c(NULL, 0); /* Push Buttons */ diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 2e3f2894b704..9561e33b8a9a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -23,6 +23,7 @@ #define AT91_PMC_PCK (1 << 0) /* Processor Clock */ #define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */ #define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */ +#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock [AT91CAP9 revC only] */ #define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */ #define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */ #define AT91CAP9_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91CAP9 only] */ @@ -102,10 +103,16 @@ #define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ #define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ #define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [AT91CAP9 only] */ +#define AT91_PMC_OSCSEL (1 << 7) /* Slow Clock Oscillator [AT91CAP9 revC only] */ #define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ #define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ #define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ #define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ #define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */ +#define AT91_PMC_PROT (AT91_PMC + 0xe4) /* Protect Register [AT91CAP9 revC only] */ +#define AT91_PMC_PROTKEY 0x504d4301 /* Activation Code */ + +#define AT91_PMC_VER (AT91_PMC + 0xfc) /* PMC Module Version [AT91CAP9 only] */ + #endif diff --git a/arch/arm/mach-at91/include/mach/at91cap9.h b/arch/arm/mach-at91/include/mach/at91cap9.h index 4a4b64135a92..d8c1ededaa75 100644 --- a/arch/arm/mach-at91/include/mach/at91cap9.h +++ b/arch/arm/mach-at91/include/mach/at91cap9.h @@ -101,7 +101,9 @@ #define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) #define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) #define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) -#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) +#define AT91_GPBR (cpu_is_at91cap9_revB() ? \ + (0xfffffd50 - AT91_BASE_SYS) : \ + (0xfffffd60 - AT91_BASE_SYS)) #define AT91_USART0 AT91CAP9_BASE_US0 #define AT91_USART1 AT91CAP9_BASE_US1 diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index dbfd9f73f80b..c554c3e4d553 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -49,6 +49,17 @@ static inline unsigned long at91_arch_identify(void) return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH); } +#ifdef CONFIG_ARCH_AT91CAP9 +#include <mach/at91_pmc.h> + +#define ARCH_REVISION_CAP9_B 0x399 +#define ARCH_REVISION_CAP9_C 0x601 + +static inline unsigned long at91cap9_rev_identify(void) +{ + return (at91_sys_read(AT91_PMC_VER)); +} +#endif #ifdef CONFIG_ARCH_AT91RM9200 #define cpu_is_at91rm9200() (at91_cpu_identify() == ARCH_ID_AT91RM9200) @@ -90,8 +101,12 @@ static inline unsigned long at91_arch_identify(void) #ifdef CONFIG_ARCH_AT91CAP9 #define cpu_is_at91cap9() (at91_cpu_identify() == ARCH_ID_AT91CAP9) +#define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B) +#define cpu_is_at91cap9_revC() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_C) #else #define cpu_is_at91cap9() (0) +#define cpu_is_at91cap9_revB() (0) +#define cpu_is_at91cap9_revC() (0) #endif /* diff --git a/arch/arm/mach-at91/include/mach/dma.h b/arch/arm/mach-at91/include/mach/dma.h deleted file mode 100644 index e4f90c177616..000000000000 --- a/arch/arm/mach-at91/include/mach/dma.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * arch/arm/mach-at91/include/mach/dma.h - * - * Copyright (C) 2003 SAN People - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h index 1611bd03f528..0b0cccc46e68 100644 --- a/arch/arm/mach-at91/include/mach/io.h +++ b/arch/arm/mach-at91/include/mach/io.h @@ -23,8 +23,8 @@ #define IO_SPACE_LIMIT 0xFFFFFFFF -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-at91/include/mach/memory.h b/arch/arm/mach-at91/include/mach/memory.h index 9dd1b8c79b08..14f4ef4b6a9e 100644 --- a/arch/arm/mach-at91/include/mach/memory.h +++ b/arch/arm/mach-at91/include/mach/memory.h @@ -25,15 +25,4 @@ #define PHYS_OFFSET (AT91_SDRAM_BASE) - -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c new file mode 100644 index 000000000000..5eab6aa621d0 --- /dev/null +++ b/arch/arm/mach-at91/sam9_smc.c @@ -0,0 +1,47 @@ +/* + * linux/arch/arm/mach-at91/sam9_smc.c + * + * Copyright (C) 2008 Andrew Victor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/io.h> + +#include <mach/at91sam9_smc.h> + +#include "sam9_smc.h" + +void __init sam9_smc_configure(int cs, struct sam9_smc_config* config) +{ + /* Setup register */ + at91_sys_write(AT91_SMC_SETUP(cs), + AT91_SMC_NWESETUP_(config->nwe_setup) + | AT91_SMC_NCS_WRSETUP_(config->ncs_write_setup) + | AT91_SMC_NRDSETUP_(config->nrd_setup) + | AT91_SMC_NCS_RDSETUP_(config->ncs_read_setup) + ); + + /* Pulse register */ + at91_sys_write(AT91_SMC_PULSE(cs), + AT91_SMC_NWEPULSE_(config->nwe_pulse) + | AT91_SMC_NCS_WRPULSE_(config->ncs_write_pulse) + | AT91_SMC_NRDPULSE_(config->nrd_pulse) + | AT91_SMC_NCS_RDPULSE_(config->ncs_read_pulse) + ); + + /* Cycle register */ + at91_sys_write(AT91_SMC_CYCLE(cs), + AT91_SMC_NWECYCLE_(config->write_cycle) + | AT91_SMC_NRDCYCLE_(config->read_cycle) + ); + + /* Mode register */ + at91_sys_write(AT91_SMC_MODE(cs), + config->mode + | AT91_SMC_TDF_(config->tdf_cycles) + ); +} diff --git a/arch/arm/mach-at91/sam9_smc.h b/arch/arm/mach-at91/sam9_smc.h new file mode 100644 index 000000000000..bf72cfb3455b --- /dev/null +++ b/arch/arm/mach-at91/sam9_smc.h @@ -0,0 +1,33 @@ +/* + * linux/arch/arm/mach-at91/sam9_smc. + * + * Copyright (C) 2008 Andrew Victor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +struct sam9_smc_config { + /* Setup register */ + u8 ncs_read_setup; + u8 nrd_setup; + u8 ncs_write_setup; + u8 nwe_setup; + + /* Pulse register */ + u8 ncs_read_pulse; + u8 nrd_pulse; + u8 ncs_write_pulse; + u8 nwe_pulse; + + /* Cycle register */ + u16 read_cycle; + u16 write_cycle; + + /* Mode register */ + u32 mode; + u8 tdf_cycles:4; +}; + +extern void __init sam9_smc_configure(int cs, struct sam9_smc_config* config); diff --git a/arch/arm/mach-clps711x/include/mach/dma.h b/arch/arm/mach-clps711x/include/mach/dma.h deleted file mode 100644 index 0d620e869536..000000000000 --- a/arch/arm/mach-clps711x/include/mach/dma.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * arch/arm/mach-clps711x/include/mach/dma.h - * - * Copyright (C) 1997,1998 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/arch/arm/mach-clps711x/include/mach/io.h b/arch/arm/mach-clps711x/include/mach/io.h index 4c8440087679..2e0b3ced8f07 100644 --- a/arch/arm/mach-clps711x/include/mach/io.h +++ b/arch/arm/mach-clps711x/include/mach/io.h @@ -20,12 +20,10 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) /* * We don't support ins[lb]/outs[lb]. Make them fault. diff --git a/arch/arm/mach-clps711x/include/mach/memory.h b/arch/arm/mach-clps711x/include/mach/memory.h index 98ec30c97bbe..e522b20bcbc2 100644 --- a/arch/arm/mach-clps711x/include/mach/memory.h +++ b/arch/arm/mach-clps711x/include/mach/memory.h @@ -26,25 +26,7 @@ */ #define PHYS_OFFSET UL(0xc0000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ - -#if defined(CONFIG_ARCH_CDB89712) - -#define __virt_to_bus(x) (x) -#define __bus_to_virt(x) (x) - -#elif defined (CONFIG_ARCH_AUTCPU12) - -#define __virt_to_bus(x) (x) -#define __bus_to_virt(x) (x) - -#else +#if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12) #define __virt_to_bus(x) ((x) - PAGE_OFFSET) #define __bus_to_virt(x) ((x) + PAGE_OFFSET) diff --git a/arch/arm/mach-clps7500/Makefile b/arch/arm/mach-clps7500/Makefile deleted file mode 100644 index 4bd8ebd70e7b..000000000000 --- a/arch/arm/mach-clps7500/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := core.o -obj-m := -obj-n := -obj- := - diff --git a/arch/arm/mach-clps7500/Makefile.boot b/arch/arm/mach-clps7500/Makefile.boot deleted file mode 100644 index fe16506c1540..000000000000 --- a/arch/arm/mach-clps7500/Makefile.boot +++ /dev/null @@ -1,2 +0,0 @@ - zreladdr-y := 0x10008000 - diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c deleted file mode 100644 index 7e247c04d41c..000000000000 --- a/arch/arm/mach-clps7500/core.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * linux/arch/arm/mach-clps7500/core.c - * - * Copyright (C) 1998 Russell King - * Copyright (C) 1999 Nexus Electronics Ltd - * - * Extra MM routines for CL7500 architecture - */ -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/list.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/serial_8250.h> -#include <linux/io.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> -#include <asm/mach/time.h> - -#include <mach/hardware.h> -#include <asm/hardware/iomd.h> -#include <asm/irq.h> -#include <asm/mach-types.h> - -unsigned int vram_size; - -static void cl7500_ack_irq_a(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << irq; - val = iomd_readb(IOMD_IRQMASKA); - iomd_writeb(val & ~mask, IOMD_IRQMASKA); - iomd_writeb(mask, IOMD_IRQCLRA); -} - -static void cl7500_mask_irq_a(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << irq; - val = iomd_readb(IOMD_IRQMASKA); - iomd_writeb(val & ~mask, IOMD_IRQMASKA); -} - -static void cl7500_unmask_irq_a(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << irq; - val = iomd_readb(IOMD_IRQMASKA); - iomd_writeb(val | mask, IOMD_IRQMASKA); -} - -static struct irq_chip clps7500_a_chip = { - .ack = cl7500_ack_irq_a, - .mask = cl7500_mask_irq_a, - .unmask = cl7500_unmask_irq_a, -}; - -static void cl7500_mask_irq_b(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKB); - iomd_writeb(val & ~mask, IOMD_IRQMASKB); -} - -static void cl7500_unmask_irq_b(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKB); - iomd_writeb(val | mask, IOMD_IRQMASKB); -} - -static struct irq_chip clps7500_b_chip = { - .ack = cl7500_mask_irq_b, - .mask = cl7500_mask_irq_b, - .unmask = cl7500_unmask_irq_b, -}; - -static void cl7500_mask_irq_c(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKC); - iomd_writeb(val & ~mask, IOMD_IRQMASKC); -} - -static void cl7500_unmask_irq_c(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKC); - iomd_writeb(val | mask, IOMD_IRQMASKC); -} - -static struct irq_chip clps7500_c_chip = { - .ack = cl7500_mask_irq_c, - .mask = cl7500_mask_irq_c, - .unmask = cl7500_unmask_irq_c, -}; - -static void cl7500_mask_irq_d(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKD); - iomd_writeb(val & ~mask, IOMD_IRQMASKD); -} - -static void cl7500_unmask_irq_d(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_IRQMASKD); - iomd_writeb(val | mask, IOMD_IRQMASKD); -} - -static struct irq_chip clps7500_d_chip = { - .ack = cl7500_mask_irq_d, - .mask = cl7500_mask_irq_d, - .unmask = cl7500_unmask_irq_d, -}; - -static void cl7500_mask_irq_dma(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_DMAMASK); - iomd_writeb(val & ~mask, IOMD_DMAMASK); -} - -static void cl7500_unmask_irq_dma(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_DMAMASK); - iomd_writeb(val | mask, IOMD_DMAMASK); -} - -static struct irq_chip clps7500_dma_chip = { - .ack = cl7500_mask_irq_dma, - .mask = cl7500_mask_irq_dma, - .unmask = cl7500_unmask_irq_dma, -}; - -static void cl7500_mask_irq_fiq(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_FIQMASK); - iomd_writeb(val & ~mask, IOMD_FIQMASK); -} - -static void cl7500_unmask_irq_fiq(unsigned int irq) -{ - unsigned int val, mask; - - mask = 1 << (irq & 7); - val = iomd_readb(IOMD_FIQMASK); - iomd_writeb(val | mask, IOMD_FIQMASK); -} - -static struct irq_chip clps7500_fiq_chip = { - .ack = cl7500_mask_irq_fiq, - .mask = cl7500_mask_irq_fiq, - .unmask = cl7500_unmask_irq_fiq, -}; - -static void cl7500_no_action(unsigned int irq) -{ -} - -static struct irq_chip clps7500_no_chip = { - .ack = cl7500_no_action, - .mask = cl7500_no_action, - .unmask = cl7500_no_action, -}; - -static struct irqaction irq_isa = { - .handler = no_action, - .mask = CPU_MASK_NONE, - .name = "isa", -}; - -static void __init clps7500_init_irq(void) -{ - unsigned int irq, flags; - - iomd_writeb(0, IOMD_IRQMASKA); - iomd_writeb(0, IOMD_IRQMASKB); - iomd_writeb(0, IOMD_FIQMASK); - iomd_writeb(0, IOMD_DMAMASK); - - for (irq = 0; irq < NR_IRQS; irq++) { - flags = IRQF_VALID; - - if (irq <= 6 || (irq >= 9 && irq <= 15) || - (irq >= 48 && irq <= 55)) - flags |= IRQF_PROBE; - - switch (irq) { - case 0 ... 7: - set_irq_chip(irq, &clps7500_a_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 8 ... 15: - set_irq_chip(irq, &clps7500_b_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 16 ... 22: - set_irq_chip(irq, &clps7500_dma_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 24 ... 31: - set_irq_chip(irq, &clps7500_c_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 40 ... 47: - set_irq_chip(irq, &clps7500_d_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 48 ... 55: - set_irq_chip(irq, &clps7500_no_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - - case 64 ... 72: - set_irq_chip(irq, &clps7500_fiq_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, flags); - break; - } - } - - setup_irq(IRQ_ISA, &irq_isa); -} - -static struct map_desc cl7500_io_desc[] __initdata = { - { /* IO space */ - .virtual = (unsigned long)IO_BASE, - .pfn = __phys_to_pfn(IO_START), - .length = IO_SIZE, - .type = MT_DEVICE - }, { /* ISA space */ - .virtual = ISA_BASE, - .pfn = __phys_to_pfn(ISA_START), - .length = ISA_SIZE, - .type = MT_DEVICE - }, { /* Flash */ - .virtual = CLPS7500_FLASH_BASE, - .pfn = __phys_to_pfn(CLPS7500_FLASH_START), - .length = CLPS7500_FLASH_SIZE, - .type = MT_DEVICE - }, { /* LED */ - .virtual = LED_BASE, - .pfn = __phys_to_pfn(LED_START), - .length = LED_SIZE, - .type = MT_DEVICE - } -}; - -static void __init clps7500_map_io(void) -{ - iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc)); -} - -extern void ioctime_init(void); -extern unsigned long ioc_timer_gettimeoffset(void); - -static irqreturn_t -clps7500_timer_interrupt(int irq, void *dev_id) -{ - timer_tick(); - - /* Why not using do_leds interface?? */ - { - /* Twinkle the lights. */ - static int count, state = 0xff00; - if (count-- == 0) { - state ^= 0x100; - count = 25; - *((volatile unsigned int *)LED_ADDRESS) = state; - } - } - - return IRQ_HANDLED; -} - -static struct irqaction clps7500_timer_irq = { - .name = "CLPS7500 Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = clps7500_timer_interrupt, -}; - -/* - * Set up timer interrupt. - */ -static void __init clps7500_timer_init(void) -{ - ioctime_init(); - setup_irq(IRQ_TIMER, &clps7500_timer_irq); -} - -static struct sys_timer clps7500_timer = { - .init = clps7500_timer_init, - .offset = ioc_timer_gettimeoffset, -}; - -static struct plat_serial8250_port serial_platform_data[] = { - { - .mapbase = 0x03010fe0, - .irq = 10, - .uartclk = 1843200, - .regshift = 2, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST, - }, - { - .mapbase = 0x03010be0, - .irq = 0, - .uartclk = 1843200, - .regshift = 2, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST, - }, - { - .iobase = ISASLOT_IO + 0x2e8, - .irq = 41, - .uartclk = 1843200, - .regshift = 0, - .iotype = UPIO_PORT, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - }, - { - .iobase = ISASLOT_IO + 0x3e8, - .irq = 40, - .uartclk = 1843200, - .regshift = 0, - .iotype = UPIO_PORT, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - }, - { }, -}; - -static struct platform_device serial_device = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = serial_platform_data, - }, -}; - -static void __init clps7500_init(void) -{ - platform_device_register(&serial_device); -} - -MACHINE_START(CLPS7500, "CL-PS7500") - /* Maintainer: Philip Blundell */ - .phys_io = 0x03000000, - .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, - .map_io = clps7500_map_io, - .init_irq = clps7500_init_irq, - .init_machine = clps7500_init, - .timer = &clps7500_timer, -MACHINE_END - diff --git a/arch/arm/mach-clps7500/include/mach/acornfb.h b/arch/arm/mach-clps7500/include/mach/acornfb.h deleted file mode 100644 index aea6330c9745..000000000000 --- a/arch/arm/mach-clps7500/include/mach/acornfb.h +++ /dev/null @@ -1,33 +0,0 @@ -#define acornfb_valid_pixrate(var) (var->pixclock >= 39325 && var->pixclock <= 40119) - -static inline void -acornfb_vidc20_find_rates(struct vidc_timing *vidc, - struct fb_var_screeninfo *var) -{ - u_int bandwidth; - - vidc->control |= VIDC20_CTRL_PIX_CK; - - /* Calculate bandwidth */ - bandwidth = var->pixclock * 8 / var->bits_per_pixel; - - /* Encode bandwidth as VIDC20 setting */ - if (bandwidth > 16667*2) - vidc->control |= VIDC20_CTRL_FIFO_16; - else if (bandwidth > 13333*2) - vidc->control |= VIDC20_CTRL_FIFO_20; - else if (bandwidth > 11111*2) - vidc->control |= VIDC20_CTRL_FIFO_24; - else - vidc->control |= VIDC20_CTRL_FIFO_28; - - vidc->pll_ctl = 0x2020; -} - -#ifdef CONFIG_CHRONTEL_7003 -#define acornfb_default_control() VIDC20_CTRL_PIX_HCLK -#else -#define acornfb_default_control() VIDC20_CTRL_PIX_VCLK -#endif - -#define acornfb_default_econtrol() VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3) | VIDC20_ECTL_ECK diff --git a/arch/arm/mach-clps7500/include/mach/debug-macro.S b/arch/arm/mach-clps7500/include/mach/debug-macro.S deleted file mode 100644 index af4104e7e84a..000000000000 --- a/arch/arm/mach-clps7500/include/mach/debug-macro.S +++ /dev/null @@ -1,21 +0,0 @@ -/* arch/arm/mach-clps7500/include/mach/debug-macro.S - * - * Debugging macro include header - * - * Copyright (C) 1994-1999 Russell King - * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * -*/ - - .macro addruart,rx - mov \rx, #0xe0000000 - orr \rx, \rx, #0x00010000 - orr \rx, \rx, #0x00000be0 - .endm - -#define UART_SHIFT 2 -#include <asm/hardware/debug-8250.S> diff --git a/arch/arm/mach-clps7500/include/mach/dma.h b/arch/arm/mach-clps7500/include/mach/dma.h deleted file mode 100644 index 63fcde505498..000000000000 --- a/arch/arm/mach-clps7500/include/mach/dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/dma.h - * - * Copyright (C) 1999 Nexus Electronics Ltd. - */ - -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -/* DMA is not yet implemented! It should be the same as acorn, copy over.. */ - -/* - * This is the maximum DMA address that can be DMAd to. - * There should not be more than (0xd0000000 - 0xc0000000) - * bytes of RAM. - */ -#define MAX_DMA_ADDRESS 0xd0000000 - -#define DMA_S0 0 - -#endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-clps7500/include/mach/entry-macro.S b/arch/arm/mach-clps7500/include/mach/entry-macro.S deleted file mode 100644 index 4e7e54144093..000000000000 --- a/arch/arm/mach-clps7500/include/mach/entry-macro.S +++ /dev/null @@ -1,16 +0,0 @@ -#include <mach/hardware.h> -#include <asm/hardware/entry-macro-iomd.S> - - .equ ioc_base_high, IOC_BASE & 0xff000000 - .equ ioc_base_low, IOC_BASE & 0x00ff0000 - - .macro get_irqnr_preamble, base, tmp - mov \base, #ioc_base_high @ point at IOC - .if ioc_base_low - orr \base, \base, #ioc_base_low - .endif - .endm - - .macro arch_ret_to_user, tmp1, tmp2 - .endm - diff --git a/arch/arm/mach-clps7500/include/mach/hardware.h b/arch/arm/mach-clps7500/include/mach/hardware.h deleted file mode 100644 index a6ad1d44badf..000000000000 --- a/arch/arm/mach-clps7500/include/mach/hardware.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/hardware.h - * - * Copyright (C) 1996-1999 Russell King. - * Copyright (C) 1999 Nexus Electronics Ltd. - * - * This file contains the hardware definitions of the - * CL7500 evaluation board. - */ -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include <mach/memory.h> -#include <asm/hardware/iomd.h> - -#ifdef __ASSEMBLY__ -#define IOMEM(x) x -#else -#define IOMEM(x) ((void __iomem *)(x)) -#endif - -/* - * What hardware must be present - */ -#define HAS_IOMD -#define HAS_VIDC20 - -/* Hardware addresses of major areas. - * *_START is the physical address - * *_SIZE is the size of the region - * *_BASE is the virtual address - */ - -#define IO_START 0x03000000 /* I/O */ -#define IO_SIZE 0x01000000 -#define IO_BASE IOMEM(0xe0000000) - -#define ISA_START 0x0c000000 /* ISA */ -#define ISA_SIZE 0x00010000 -#define ISA_BASE 0xe1000000 - -#define CLPS7500_FLASH_START 0x01000000 /* XXX */ -#define CLPS7500_FLASH_SIZE 0x01000000 -#define CLPS7500_FLASH_BASE 0xe2000000 - -#define LED_START 0x0302B000 -#define LED_SIZE 0x00001000 -#define LED_BASE 0xe3000000 -#define LED_ADDRESS (LED_BASE + 0xa00) - -/* Let's define SCREEN_START for CL7500, even though it's a lie. */ -#define SCREEN_START 0x02000000 /* VRAM */ -#define SCREEN_END 0xdfc00000 -#define SCREEN_BASE 0xdf800000 - -#define VIDC_BASE (void __iomem *)0xe0400000 -#define IOMD_BASE IOMEM(0xe0200000) -#define IOC_BASE IOMEM(0xe0200000) -#define FLOPPYDMA_BASE IOMEM(0xe002a000) -#define PCIO_BASE IOMEM(0xe0010000) - -#define vidc_writel(val) __raw_writel(val, VIDC_BASE) - -/* in/out bias for the ISA slot region */ -#define ISASLOT_IO 0x80400000 - -#endif diff --git a/arch/arm/mach-clps7500/include/mach/io.h b/arch/arm/mach-clps7500/include/mach/io.h deleted file mode 100644 index 2ff2860889ed..000000000000 --- a/arch/arm/mach-clps7500/include/mach/io.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/io.h - * from arch/arm/mach-rpc/include/mach/io.h - * - * Copyright (C) 1997 Russell King - * - * Modifications: - * 06-Dec-1997 RMK Created. - */ -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -#include <mach/hardware.h> - -#define IO_SPACE_LIMIT 0xffffffff - -/* - * GCC is totally crap at loading/storing data. We try to persuade it - * to do the right thing by using these whereever possible instead of - * the above. - */ -#define __arch_base_getb(b,o) \ - ({ \ - unsigned int v, r = (b); \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2]" \ - : "=r" (v) \ - : "r" (r), "Ir" (o)); \ - v; \ - }) - -#define __arch_base_getl(b,o) \ - ({ \ - unsigned int v, r = (b); \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (v) \ - : "r" (r), "Ir" (o)); \ - v; \ - }) - -#define __arch_base_putb(v,b,o) \ - ({ \ - unsigned int r = (b); \ - __asm__ __volatile__( \ - "strb %0, [%1, %2]" \ - : \ - : "r" (v), "r" (r), "Ir" (o)); \ - }) - -#define __arch_base_putl(v,b,o) \ - ({ \ - unsigned int r = (b); \ - __asm__ __volatile__( \ - "str %0, [%1, %2]" \ - : \ - : "r" (v), "r" (r), "Ir" (o)); \ - }) - -/* - * We use two different types of addressing - PC style addresses, and ARM - * addresses. PC style accesses the PC hardware with the normal PC IO - * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ - * and are translated to the start of IO. Note that all addresses are - * shifted left! - */ -#define __PORT_PCIO(x) (!((x) & 0x80000000)) - -/* - * Dynamic IO functions - let the compiler - * optimize the expressions - */ -static inline void __outb (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "strb %1, [%0, %2, lsl #2] @ outb" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -static inline void __outw (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2] @ outw" - : "=&r" (temp) - : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -static inline void __outl (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2] @ outl" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ -static inline unsigned sz __in##fnsuffix (unsigned int port) \ -{ \ - unsigned long temp, value; \ - __asm__ __volatile__( \ - "tst %2, #0x80000000\n\t" \ - "mov %0, %4\n\t" \ - "addeq %0, %0, %3\n\t" \ - "ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \ - : "=&r" (temp), "=r" (value) \ - : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ - : "cc"); \ - return (unsigned sz)value; \ -} - -static inline unsigned int __ioaddr (unsigned int port) \ -{ \ - if (__PORT_PCIO(port)) \ - return (unsigned int)(PCIO_BASE + (port << 2)); \ - else \ - return (unsigned int)(IO_BASE + (port << 2)); \ -} - -#define DECLARE_IO(sz,fnsuffix,instr) \ - DECLARE_DYN_IN(sz,fnsuffix,instr) - -DECLARE_IO(char,b,"b") -DECLARE_IO(short,w,"") -DECLARE_IO(int,l,"") - -#undef DECLARE_IO -#undef DECLARE_DYN_IN - -/* - * Constant address IO functions - * - * These have to be macros for the 'J' constraint to work - - * +/-4096 immediate operand. - */ -#define __outbc(value,port) \ -({ \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "strb %0, [%1, %2] @ outbc" \ - : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "strb %0, [%1, %2] @ outbc" \ - : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inbc(port) \ -({ \ - unsigned char result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2] @ inbc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2] @ inbc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define __outwc(value,port) \ -({ \ - unsigned long v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outwc" \ - : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outwc" \ - : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inwc(port) \ -({ \ - unsigned short result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inwc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inwc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result & 0xffff; \ -}) - -#define __outlc(value,port) \ -({ \ - unsigned long v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outlc" \ - : : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outlc" \ - : : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inlc(port) \ -({ \ - unsigned long result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inlc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inlc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define __ioaddrc(port) \ - (__PORT_PCIO((port)) ? PCIO_BASE + ((port) << 2) : IO_BASE + ((port) << 2)) - -#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p)) -#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p)) -#define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p)) -#define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p)) -#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p)) -#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p)) -#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p)) -/* the following macro is deprecated */ -#define ioaddr(port) __ioaddr((port)) - -#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l) -#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l) - -#define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l) -#define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l) - -/* - * 1:1 mapping for ioremapped regions. - */ -#define __mem_pci(x) (x) - -#endif diff --git a/arch/arm/mach-clps7500/include/mach/irq.h b/arch/arm/mach-clps7500/include/mach/irq.h deleted file mode 100644 index d02fcf28ee05..000000000000 --- a/arch/arm/mach-clps7500/include/mach/irq.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/irq.h - * - * Copyright (C) 1996 Russell King - * Copyright (C) 1999, 2001 Nexus Electronics Ltd. - * - * Changelog: - * 10-10-1996 RMK Brought up to date with arch-sa110eval - * 22-08-1998 RMK Restructured IRQ routines - * 11-08-1999 PJB Created ARM7500 version, derived from RiscPC code - */ - -#include <linux/io.h> -#include <asm/hardware/iomd.h> - -static inline int fixup_irq(unsigned int irq) -{ - if (irq == IRQ_ISA) { - int isabits = *((volatile unsigned int *)0xe002b700); - if (isabits == 0) { - printk("Spurious ISA IRQ!\n"); - return irq; - } - irq = IRQ_ISA_BASE; - while (!(isabits & 1)) { - irq++; - isabits >>= 1; - } - } - - return irq; -} diff --git a/arch/arm/mach-clps7500/include/mach/irqs.h b/arch/arm/mach-clps7500/include/mach/irqs.h deleted file mode 100644 index bee66b487f59..000000000000 --- a/arch/arm/mach-clps7500/include/mach/irqs.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/irqs.h - * - * Copyright (C) 1999 Nexus Electronics Ltd - */ - -#define IRQ_INT2 0 -#define IRQ_INT1 2 -#define IRQ_VSYNCPULSE 3 -#define IRQ_POWERON 4 -#define IRQ_TIMER0 5 -#define IRQ_TIMER1 6 -#define IRQ_FORCE 7 -#define IRQ_INT8 8 -#define IRQ_ISA 9 -#define IRQ_INT6 10 -#define IRQ_INT5 11 -#define IRQ_INT4 12 -#define IRQ_INT3 13 -#define IRQ_KEYBOARDTX 14 -#define IRQ_KEYBOARDRX 15 - -#define IRQ_DMA0 16 -#define IRQ_DMA1 17 -#define IRQ_DMA2 18 -#define IRQ_DMA3 19 -#define IRQ_DMAS0 20 -#define IRQ_DMAS1 21 - -#define IRQ_IOP0 24 -#define IRQ_IOP1 25 -#define IRQ_IOP2 26 -#define IRQ_IOP3 27 -#define IRQ_IOP4 28 -#define IRQ_IOP5 29 -#define IRQ_IOP6 30 -#define IRQ_IOP7 31 - -#define IRQ_MOUSERX 40 -#define IRQ_MOUSETX 41 -#define IRQ_ADC 42 -#define IRQ_EVENT1 43 -#define IRQ_EVENT2 44 - -#define IRQ_ISA_BASE 48 -#define IRQ_ISA_3 48 -#define IRQ_ISA_4 49 -#define IRQ_ISA_5 50 -#define IRQ_ISA_7 51 -#define IRQ_ISA_9 52 -#define IRQ_ISA_10 53 -#define IRQ_ISA_11 54 -#define IRQ_ISA_14 55 - -#define FIQ_INT9 0 -#define FIQ_INT5 1 -#define FIQ_INT6 4 -#define FIQ_INT8 6 -#define FIQ_FORCE 7 - -/* - * This is the offset of the FIQ "IRQ" numbers - */ -#define FIQ_START 64 - -#define IRQ_TIMER IRQ_TIMER0 diff --git a/arch/arm/mach-clps7500/include/mach/memory.h b/arch/arm/mach-clps7500/include/mach/memory.h deleted file mode 100644 index 87b32db470c8..000000000000 --- a/arch/arm/mach-clps7500/include/mach/memory.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/memory.h - * - * Copyright (c) 1996,1997,1998 Russell King. - * - * Changelog: - * 20-Oct-1996 RMK Created - * 31-Dec-1997 RMK Fixed definitions to reduce warnings - * 11-Jan-1998 RMK Uninlined to reduce hits on cache - * 08-Feb-1998 RMK Added __virt_to_bus and __bus_to_virt - * 21-Mar-1999 RMK Renamed to memory.h - * RMK Added TASK_SIZE and PAGE_OFFSET - */ -#ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H - -/* - * Physical DRAM offset. - */ -#define PHYS_OFFSET UL(0x10000000) - -/* - * These are exactly the same on the RiscPC as the - * physical memory view. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -/* - * Cache flushing area - ROM - */ -#define FLUSH_BASE_PHYS 0x00000000 -#define FLUSH_BASE 0xdf000000 - -/* - * Sparsemem support. Each section is a maximum of 64MB. The sections - * are offset by 128MB and can cover 128MB, so that gives us a maximum - * of 29 physmem bits. - */ -#define MAX_PHYSMEM_BITS 29 -#define SECTION_SIZE_BITS 26 - -#endif diff --git a/arch/arm/mach-clps7500/include/mach/system.h b/arch/arm/mach-clps7500/include/mach/system.h deleted file mode 100644 index 6d325fbe8b08..000000000000 --- a/arch/arm/mach-clps7500/include/mach/system.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/system.h - * - * Copyright (c) 1999 Nexus Electronics Ltd. - */ -#ifndef __ASM_ARCH_SYSTEM_H -#define __ASM_ARCH_SYSTEM_H - -#include <linux/io.h> -#include <asm/hardware/iomd.h> - -static inline void arch_idle(void) -{ - iomd_writeb(0, IOMD_SUSMODE); -} - -#define arch_reset(mode) \ - do { \ - iomd_writeb(0, IOMD_ROMCR0); \ - cpu_reset(0); \ - } while (0) - -#endif diff --git a/arch/arm/mach-clps7500/include/mach/timex.h b/arch/arm/mach-clps7500/include/mach/timex.h deleted file mode 100644 index dfaa9b425757..000000000000 --- a/arch/arm/mach-clps7500/include/mach/timex.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/timex.h - * - * CL7500 architecture timex specifications - * - * Copyright (C) 1999 Nexus Electronics Ltd - */ - -/* - * On the ARM7500, the clock ticks at 2MHz. - */ -#define CLOCK_TICK_RATE 2000000 - diff --git a/arch/arm/mach-clps7500/include/mach/uncompress.h b/arch/arm/mach-clps7500/include/mach/uncompress.h deleted file mode 100644 index d7d0af4b49fc..000000000000 --- a/arch/arm/mach-clps7500/include/mach/uncompress.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/uncompress.h - * - * Copyright (C) 1999, 2000 Nexus Electronics Ltd. - */ -#define BASE 0x03010000 -#define SERBASE (BASE + (0x2f8 << 2)) - -static inline void putc(char c) -{ - while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20)) - barrier(); - - *((volatile unsigned int *)(SERBASE)) = c; -} - -static inline void flush(void) -{ -} - -static __inline__ void arch_decomp_setup(void) -{ - int baud = 3686400 / (9600 * 32); - - *((volatile unsigned int *)(SERBASE + 0xC)) = 0x80; - *((volatile unsigned int *)(SERBASE + 0x0)) = baud & 0xff; - *((volatile unsigned int *)(SERBASE + 0x4)) = (baud & 0xff00) >> 8; - *((volatile unsigned int *)(SERBASE + 0xC)) = 3; /* 8 bits */ - *((volatile unsigned int *)(SERBASE + 0x10)) = 3; /* DTR, RTS */ -} - -/* - * nothing to do - */ -#define arch_decomp_wdog() diff --git a/arch/arm/mach-clps7500/include/mach/vmalloc.h b/arch/arm/mach-clps7500/include/mach/vmalloc.h deleted file mode 100644 index 8fc5406d1b6d..000000000000 --- a/arch/arm/mach-clps7500/include/mach/vmalloc.h +++ /dev/null @@ -1,4 +0,0 @@ -/* - * arch/arm/mach-clps7500/include/mach/vmalloc.h - */ -#define VMALLOC_END (PAGE_OFFSET + 0x1c000000) diff --git a/arch/arm/mach-davinci/include/mach/dma.h b/arch/arm/mach-davinci/include/mach/dma.h deleted file mode 100644 index 8e2f2d0ba667..000000000000 --- a/arch/arm/mach-davinci/include/mach/dma.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * DaVinci DMA definitions - * - * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#define MAX_DMA_ADDRESS 0xffffffff - -#endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index b78ee9140496..a48795fd2417 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h @@ -29,8 +29,7 @@ * We don't actually have real ISA nor PCI buses, but there is so many * drivers out there that might just work if we fake them... */ -#define PCIO_BASE 0 -#define __io(a) ((void __iomem *)(PCIO_BASE + (a))) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #define __mem_isa(a) (a) diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h index dd1625c23cf4..86c25c7f3ce3 100644 --- a/arch/arm/mach-davinci/include/mach/memory.h +++ b/arch/arm/mach-davinci/include/mach/memory.h @@ -52,13 +52,8 @@ __arch_adjust_zones(int node, unsigned long *size, unsigned long *holes) if ((meminfo.bank[0].size >> 20) > 128) __arch_adjust_zones(node, zone_size, holes) #define ISA_DMA_THRESHOLD (PHYS_OFFSET + (128<<20) - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + (128<<20)) #endif -/* - * Bus address is physical address - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-davinci/include/mach/vmalloc.h b/arch/arm/mach-davinci/include/mach/vmalloc.h index b98bd9e92fd6..ad51625b6609 100644 --- a/arch/arm/mach-davinci/include/mach/vmalloc.h +++ b/arch/arm/mach-davinci/include/mach/vmalloc.h @@ -8,7 +8,6 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <asm/memory.h> #include <mach/io.h> /* Allow vmalloc range until the IO virtual range minus a 2M "hole" */ diff --git a/arch/arm/mach-ebsa110/include/mach/dma.h b/arch/arm/mach-ebsa110/include/mach/dma.h deleted file mode 100644 index 780a04c8bbe9..000000000000 --- a/arch/arm/mach-ebsa110/include/mach/dma.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * arch/arm/mach-ebsa110/include/mach/dma.h - * - * Copyright (C) 1997,1998 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * EBSA110 DMA definitions - */ diff --git a/arch/arm/mach-ebsa110/include/mach/memory.h b/arch/arm/mach-ebsa110/include/mach/memory.h index eea4b75b657b..0ca66d080c69 100644 --- a/arch/arm/mach-ebsa110/include/mach/memory.h +++ b/arch/arm/mach-ebsa110/include/mach/memory.h @@ -22,13 +22,6 @@ #define PHYS_OFFSET UL(0x00000000) /* - * We keep this 1:1 so that we don't interfere - * with the PCMCIA memory regions - */ -#define __virt_to_bus(x) (x) -#define __bus_to_virt(x) (x) - -/* * Cache flushing area - SRAM */ #define FLUSH_BASE_PHYS 0x40000000 diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index 5a1b8c05c958..56bddcef6905 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -33,6 +33,12 @@ config MACH_EDB9307 Say 'Y' here if you want your kernel to support the Cirrus Logic EDB9307 Evaluation Board. +config MACH_EDB9307A + bool "Support Cirrus Logic EDB9307A" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9307A Evaluation Board. + config MACH_EDB9312 bool "Support Cirrus Logic EDB9312" help diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index c1252ca9648e..944e42d51646 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o obj-$(CONFIG_MACH_EDB9302) += edb9302.o obj-$(CONFIG_MACH_EDB9302A) += edb9302a.o obj-$(CONFIG_MACH_EDB9307) += edb9307.o +obj-$(CONFIG_MACH_EDB9307A) += edb9307a.o obj-$(CONFIG_MACH_EDB9312) += edb9312.o obj-$(CONFIG_MACH_EDB9315) += edb9315.o obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index 561db73ec1ae..3fbd9b0fbe24 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data adssphere_flash_data = { }; static struct resource adssphere_flash_resource = { - .start = 0x60000000, - .end = 0x61ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }; @@ -59,7 +60,7 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 8c9f2491dccc..96049283a10a 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -16,11 +16,12 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/io.h> + +#include <asm/clkdev.h> #include <asm/div64.h> #include <mach/hardware.h> struct clk { - char *name; unsigned long rate; int users; u32 enable_reg; @@ -28,53 +29,33 @@ struct clk { }; static struct clk clk_uart = { - .name = "UARTCLK", .rate = 14745600, }; -static struct clk clk_pll1 = { - .name = "pll1", -}; -static struct clk clk_f = { - .name = "fclk", -}; -static struct clk clk_h = { - .name = "hclk", -}; -static struct clk clk_p = { - .name = "pclk", -}; -static struct clk clk_pll2 = { - .name = "pll2", -}; +static struct clk clk_pll1; +static struct clk clk_f; +static struct clk clk_h; +static struct clk clk_p; +static struct clk clk_pll2; static struct clk clk_usb_host = { - .name = "usb_host", .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL, .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN, }; - -static struct clk *clocks[] = { - &clk_uart, - &clk_pll1, - &clk_f, - &clk_h, - &clk_p, - &clk_pll2, - &clk_usb_host, +#define INIT_CK(dev,con,ck) \ + { .dev_id = dev, .con_id = con, .clk = ck } + +static struct clk_lookup clocks[] = { + INIT_CK("apb:uart1", NULL, &clk_uart), + INIT_CK("apb:uart2", NULL, &clk_uart), + INIT_CK("apb:uart3", NULL, &clk_uart), + INIT_CK(NULL, "pll1", &clk_pll1), + INIT_CK(NULL, "fclk", &clk_f), + INIT_CK(NULL, "hclk", &clk_h), + INIT_CK(NULL, "pclk", &clk_p), + INIT_CK(NULL, "pll2", &clk_pll2), + INIT_CK(NULL, "usb_host", &clk_usb_host), }; -struct clk *clk_get(struct device *dev, const char *id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(clocks); i++) { - if (!strcmp(clocks[i]->name, id)) - return clocks[i]; - } - - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get); int clk_enable(struct clk *clk) { @@ -106,12 +87,6 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - - static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; @@ -138,6 +113,7 @@ static unsigned long calc_pll_rate(u32 config_word) static int __init ep93xx_clock_init(void) { u32 value; + int i; value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); if (!(value & 0x00800000)) { /* PLL1 bypassed? */ @@ -165,6 +141,8 @@ static int __init ep93xx_clock_init(void) clk_f.rate / 1000000, clk_h.rate / 1000000, clk_p.rate / 1000000); + for (i = 0; i < ARRAY_SIZE(clocks); i++) + clkdev_add(&clocks[i]); return 0; } arch_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 48345fb34613..4781f323703b 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -34,6 +34,8 @@ #include <linux/amba/bus.h> #include <linux/amba/serial.h> #include <linux/io.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> #include <asm/types.h> #include <asm/setup.h> @@ -153,12 +155,14 @@ static unsigned char gpio_int_unmasked[3]; static unsigned char gpio_int_enabled[3]; static unsigned char gpio_int_type1[3]; static unsigned char gpio_int_type2[3]; +static unsigned char gpio_int_debouce[3]; /* Port ordering is: A B F */ static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 }; +static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 }; void ep93xx_gpio_update_int_params(unsigned port) { @@ -181,6 +185,22 @@ void ep93xx_gpio_int_mask(unsigned line) gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); } +void ep93xx_gpio_int_debounce(unsigned int irq, int enable) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + int port_mask = 1 << (line & 7); + + if (enable) + gpio_int_debouce[port] |= port_mask; + else + gpio_int_debouce[port] &= ~port_mask; + + __raw_writeb(gpio_int_debouce[port], + EP93XX_GPIO_REG(int_debounce_register_offset[port])); +} +EXPORT_SYMBOL(ep93xx_gpio_int_debounce); + /************************************************************************* * EP93xx IRQ handling *************************************************************************/ @@ -497,6 +517,26 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) platform_device_register(&ep93xx_eth_device); } +static struct i2c_gpio_platform_data ep93xx_i2c_data = { + .sda_pin = EP93XX_GPIO_LINE_EEDAT, + .sda_is_open_drain = 0, + .scl_pin = EP93XX_GPIO_LINE_EECLK, + .scl_is_open_drain = 0, + .udelay = 2, +}; + +static struct platform_device ep93xx_i2c_device = { + .name = "i2c-gpio", + .id = 0, + .dev.platform_data = &ep93xx_i2c_data, +}; + +void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) +{ + i2c_register_board_info(0, devices, num); + platform_device_register(&ep93xx_i2c_device); +} + extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c index e4add5bdccfd..8bf8d7c78f1a 100644 --- a/arch/arm/mach-ep93xx/edb9302.c +++ b/arch/arm/mach-ep93xx/edb9302.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data edb9302_flash_data = { }; static struct resource edb9302_flash_resource = { - .start = 0x60000000, - .end = 0x60ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; @@ -59,7 +60,7 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") /* Maintainer: George Kashperko <george@chas.com.ua> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/edb9302a.c b/arch/arm/mach-ep93xx/edb9302a.c index 02c4405afed7..a352c57c7b46 100644 --- a/arch/arm/mach-ep93xx/edb9302a.c +++ b/arch/arm/mach-ep93xx/edb9302a.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data edb9302a_flash_data = { }; static struct resource edb9302a_flash_resource = { - .start = 0x60000000, - .end = 0x60ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; @@ -44,7 +45,7 @@ static struct platform_device edb9302a_flash = { }; static struct ep93xx_eth_data edb9302a_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init edb9302a_init_machine(void) @@ -59,7 +60,7 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0xc0000100, + .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/edb9307.c b/arch/arm/mach-ep93xx/edb9307.c index 040edbd2ea05..5ab22f63a4eb 100644 --- a/arch/arm/mach-ep93xx/edb9307.c +++ b/arch/arm/mach-ep93xx/edb9307.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data edb9307_flash_data = { }; static struct resource edb9307_flash_resource = { - .start = 0x60000000, - .end = 0x61ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }; @@ -44,7 +45,7 @@ static struct platform_device edb9307_flash = { }; static struct ep93xx_eth_data edb9307_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init edb9307_init_machine(void) @@ -59,7 +60,7 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/edb9307a.c b/arch/arm/mach-ep93xx/edb9307a.c new file mode 100644 index 000000000000..5b5c22b681be --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9307a.c @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-ep93xx/edb9307a.c + * Cirrus Logic EDB9307A support. + * + * Copyright (C) 2008 H Hartley Sweeten <hsweeten@visionengravers.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/i2c.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9307a_flash_data = { + .width = 2, +}; + +static struct resource edb9307a_flash_resource = { + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9307a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9307a_flash_data, + }, + .num_resources = 1, + .resource = &edb9307a_flash_resource, +}; + +static struct ep93xx_eth_data edb9307a_eth_data = { + .phy_id = 1, +}; + +static void __init edb9307a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9307a_flash); + + ep93xx_register_eth(&edb9307a_eth_data, 1); +} + +MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") + /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9307a_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9312.c b/arch/arm/mach-ep93xx/edb9312.c index 6853e302bc3a..d7179f66d804 100644 --- a/arch/arm/mach-ep93xx/edb9312.c +++ b/arch/arm/mach-ep93xx/edb9312.c @@ -20,6 +20,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -29,8 +30,8 @@ static struct physmap_flash_data edb9312_flash_data = { }; static struct resource edb9312_flash_resource = { - .start = 0x60000000, - .end = 0x61ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }; @@ -45,7 +46,7 @@ static struct platform_device edb9312_flash = { }; static struct ep93xx_eth_data edb9312_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init edb9312_init_machine(void) @@ -60,7 +61,7 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/edb9315.c b/arch/arm/mach-ep93xx/edb9315.c index 9469b350d253..025af6eaca10 100644 --- a/arch/arm/mach-ep93xx/edb9315.c +++ b/arch/arm/mach-ep93xx/edb9315.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data edb9315_flash_data = { }; static struct resource edb9315_flash_resource = { - .start = 0x60000000, - .end = 0x61ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }; @@ -44,7 +45,7 @@ static struct platform_device edb9315_flash = { }; static struct ep93xx_eth_data edb9315_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init edb9315_init_machine(void) @@ -59,7 +60,7 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c index 584457ce7c80..4c9cc8a39f5c 100644 --- a/arch/arm/mach-ep93xx/edb9315a.c +++ b/arch/arm/mach-ep93xx/edb9315a.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data edb9315a_flash_data = { }; static struct resource edb9315a_flash_resource = { - .start = 0x60000000, - .end = 0x60ffffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; @@ -44,7 +45,7 @@ static struct platform_device edb9315a_flash = { }; static struct ep93xx_eth_data edb9315a_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init edb9315a_init_machine(void) @@ -59,7 +60,7 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0xc0000100, + .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index 035b24e31b64..3bad500b71b6 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -19,6 +19,7 @@ #include <linux/mtd/physmap.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -28,8 +29,8 @@ static struct physmap_flash_data gesbc9312_flash_data = { }; static struct resource gesbc9312_flash_resource = { - .start = 0x60000000, - .end = 0x607fffff, + .start = EP93XX_CS6_PHYS_BASE, + .end = EP93XX_CS6_PHYS_BASE + SZ_8M - 1, .flags = IORESOURCE_MEM, }; @@ -59,7 +60,7 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-ep93xx/include/mach/clkdev.h b/arch/arm/mach-ep93xx/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h deleted file mode 100644 index d0fa9656e92f..000000000000 --- a/arch/arm/mach-ep93xx/include/mach/dma.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * arch/arm/mach-ep93xx/include/mach/dma.h - */ diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h index f7020414c5df..0a1498ae899a 100644 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ b/arch/arm/mach-ep93xx/include/mach/gpio.h @@ -99,6 +99,8 @@ /* maximum value for irq capable line identifiers */ #define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) +extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable); + /* new generic GPIO API - see Documentation/gpio.txt */ #include <asm-generic/gpio.h> diff --git a/arch/arm/mach-ep93xx/include/mach/io.h b/arch/arm/mach-ep93xx/include/mach/io.h index 1ab9a90ad339..fd5f081cc8b7 100644 --- a/arch/arm/mach-ep93xx/include/mach/io.h +++ b/arch/arm/mach-ep93xx/include/mach/io.h @@ -4,5 +4,5 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(p) ((void __iomem *)(p)) -#define __mem_pci(p) (p) +#define __io(p) __typesafe_io(p) +#define __mem_pci(p) (p) diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h index f1b633590752..5c80c3c8158d 100644 --- a/arch/arm/mach-ep93xx/include/mach/memory.h +++ b/arch/arm/mach-ep93xx/include/mach/memory.h @@ -7,8 +7,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __bus_to_virt(x) __phys_to_virt(x) -#define __virt_to_bus(x) __virt_to_phys(x) - - #endif diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index db2489d3bda7..88f7e88f152f 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -14,6 +14,7 @@ void ep93xx_map_io(void); void ep93xx_init_irq(void); void ep93xx_init_time(unsigned long); void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); +void ep93xx_register_i2c(struct i2c_board_info *devices, int num); void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index c2197236b632..15d6815d78c4 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/io.h> +#include <linux/i2c.h> #include <linux/mtd/physmap.h> #include <mach/hardware.h> @@ -25,7 +26,7 @@ #include <asm/mach-types.h> static struct ep93xx_eth_data micro9_eth_data = { - .phy_id = 0x1f, + .phy_id = 0x1f, }; static void __init micro9_init(void) @@ -38,46 +39,46 @@ static void __init micro9_init(void) */ #ifdef CONFIG_MACH_MICRO9H static struct physmap_flash_data micro9h_flash_data = { - .width = 4, + .width = 4, }; static struct resource micro9h_flash_resource = { - .start = 0x10000000, - .end = 0x13ffffff, - .flags = IORESOURCE_MEM, + .start = EP93XX_CS1_PHYS_BASE, + .end = EP93XX_CS1_PHYS_BASE + SZ_64M - 1, + .flags = IORESOURCE_MEM, }; static struct platform_device micro9h_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = µ9h_flash_data, - }, - .num_resources = 1, - .resource = µ9h_flash_resource, + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = µ9h_flash_data, + }, + .num_resources = 1, + .resource = µ9h_flash_resource, }; static void __init micro9h_init(void) { - platform_device_register(µ9h_flash); + platform_device_register(µ9h_flash); } static void __init micro9h_init_machine(void) { - ep93xx_init_devices(); - micro9_init(); - micro9h_init(); + ep93xx_init_devices(); + micro9_init(); + micro9h_init(); } MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ - .phys_io = EP93XX_APB_PHYS_BASE, - .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .timer = &ep93xx_timer, - .init_machine = micro9h_init_machine, + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9h_init_machine, MACHINE_END #endif @@ -87,19 +88,19 @@ MACHINE_END #ifdef CONFIG_MACH_MICRO9M static void __init micro9m_init_machine(void) { - ep93xx_init_devices(); - micro9_init(); + ep93xx_init_devices(); + micro9_init(); } MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ - .phys_io = EP93XX_APB_PHYS_BASE, - .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .timer = &ep93xx_timer, - .init_machine = micro9m_init_machine, + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9m_init_machine, MACHINE_END #endif @@ -109,19 +110,19 @@ MACHINE_END #ifdef CONFIG_MACH_MICRO9L static void __init micro9l_init_machine(void) { - ep93xx_init_devices(); - micro9_init(); + ep93xx_init_devices(); + micro9_init(); } MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ - .phys_io = EP93XX_APB_PHYS_BASE, - .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .timer = &ep93xx_timer, - .init_machine = micro9l_init_machine, + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9l_init_machine, MACHINE_END #endif diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index b4aa4c054276..7ee024d34829 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -20,6 +20,7 @@ #include <linux/platform_device.h> #include <linux/m48t86.h> #include <linux/io.h> +#include <linux/i2c.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -117,7 +118,7 @@ static struct physmap_flash_data ts72xx_flash_data = { static struct resource ts72xx_flash_resource = { .start = TS72XX_NOR_PHYS_BASE, - .end = TS72XX_NOR_PHYS_BASE + 0x00ffffff, + .end = TS72XX_NOR_PHYS_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; @@ -144,21 +145,21 @@ static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr) } static struct m48t86_ops ts72xx_rtc_ops = { - .readbyte = ts72xx_rtc_readbyte, - .writebyte = ts72xx_rtc_writebyte, + .readbyte = ts72xx_rtc_readbyte, + .writebyte = ts72xx_rtc_writebyte, }; static struct platform_device ts72xx_rtc_device = { - .name = "rtc-m48t86", - .id = -1, - .dev = { - .platform_data = &ts72xx_rtc_ops, + .name = "rtc-m48t86", + .id = -1, + .dev = { + .platform_data = &ts72xx_rtc_ops, }, - .num_resources = 0, + .num_resources = 0, }; static struct ep93xx_eth_data ts72xx_eth_data = { - .phy_id = 1, + .phy_id = 1, }; static void __init ts72xx_init_machine(void) @@ -175,7 +176,7 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ts72xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 6a5b437ab86f..1b996b26d2e0 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/screen_info.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/hardware/dec21285.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index 818014e09f4a..36ff06d4df15 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -14,6 +14,7 @@ #include <linux/list.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/pgtable.h> #include <asm/page.h> diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index b2a21189dd81..da35bc5c5ccc 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -7,6 +7,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/spinlock.h> #include <asm/irq.h> diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index d4c1e526f59c..133086019e3e 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -17,6 +17,7 @@ #include <linux/ioport.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/irq.h> #include <asm/system.h> diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c index b653e9cfa3f7..4f3506346969 100644 --- a/arch/arm/mach-footbridge/dma.c +++ b/arch/arm/mach-footbridge/dma.c @@ -12,6 +12,7 @@ */ #include <linux/init.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/dma.h> #include <asm/scatterlist.h> diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index b1d3bf20a41e..30040fd588cc 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -4,6 +4,7 @@ * EBSA285 machine fixup */ #include <linux/init.h> +#include <linux/spinlock.h> #include <asm/hardware/dec21285.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h index ffaea90486f9..51dd902043ad 100644 --- a/arch/arm/mach-footbridge/include/mach/hardware.h +++ b/arch/arm/mach-footbridge/include/mach/hardware.h @@ -12,8 +12,6 @@ #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H -#include <mach/memory.h> - /* Virtual Physical Size * 0xff800000 0x40000000 1MB X-Bus * 0xff000000 0x7c000000 1MB PCI I/O space @@ -28,9 +26,6 @@ #define XBUS_SIZE 0x00100000 #define XBUS_BASE 0xff800000 -#define PCIO_SIZE 0x00100000 -#define PCIO_BASE 0xff000000 - #define ARMCSR_SIZE 0x00100000 #define ARMCSR_BASE 0xfe000000 @@ -91,10 +86,11 @@ #define CPLD_FLASH_WR_ENABLE 1 #ifndef __ASSEMBLY__ -extern void gpio_modify_op(int mask, int set); -extern void gpio_modify_io(int mask, int in); -extern int gpio_read(void); -extern void cpld_modify(int mask, int set); +extern spinlock_t nw_gpio_lock; +extern void nw_gpio_modify_op(unsigned int mask, unsigned int set); +extern void nw_gpio_modify_io(unsigned int mask, unsigned int in); +extern unsigned int nw_gpio_read(void); +extern void nw_cpld_modify(unsigned int mask, unsigned int set); #endif #define pcibios_assign_all_busses() 1 diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h index a7b066239996..101a4fe90bde 100644 --- a/arch/arm/mach-footbridge/include/mach/io.h +++ b/arch/arm/mach-footbridge/include/mach/io.h @@ -14,7 +14,8 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> +#define PCIO_SIZE 0x00100000 +#define PCIO_BASE 0xff000000 #define IO_SPACE_LIMIT 0xffff diff --git a/arch/arm/mach-footbridge/include/mach/dma.h b/arch/arm/mach-footbridge/include/mach/isa-dma.h index 62afd213effb..5bd4a0d338a8 100644 --- a/arch/arm/mach-footbridge/include/mach/dma.h +++ b/arch/arm/mach-footbridge/include/mach/isa-dma.h @@ -1,5 +1,5 @@ /* - * arch/arm/mach-footbridge/include/mach/dma.h + * arch/arm/mach-footbridge/include/mach/isa-dma.h * * Architecture DMA routines * diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h index 6ae2f1a07ab9..cb16e59d87b6 100644 --- a/arch/arm/mach-footbridge/include/mach/memory.h +++ b/arch/arm/mach-footbridge/include/mach/memory.h @@ -30,9 +30,18 @@ extern unsigned long __virt_to_bus(unsigned long); extern unsigned long __bus_to_virt(unsigned long); #endif +#define __virt_to_bus __virt_to_bus +#define __bus_to_virt __bus_to_virt #elif defined(CONFIG_FOOTBRIDGE_HOST) +/* + * The footbridge is programmed to expose the system RAM at the corresponding + * address. So, if PAGE_OFFSET is 0xc0000000, RAM appears at 0xe0000000. + * If 0x80000000, then its exposed at 0xa0000000 on the bus. etc. + * The only requirement is that the RAM isn't placed at bus address 0 which + * would clash with VGA cards. + */ #define __virt_to_bus(x) ((x) - 0xe0000000) #define __bus_to_virt(x) ((x) + 0xe0000000) diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index 54fec9ae28b9..9ee80a211d3c 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -19,6 +19,7 @@ #include <linux/list.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/mach/irq.h> diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index 00b0ddcac283..ac7ffa6fc413 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <asm/hardware/dec21285.h> #include <asm/leds.h> @@ -67,13 +68,14 @@ static inline void wb977_ww(int reg, int val) /* * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE */ -DEFINE_SPINLOCK(gpio_lock); +DEFINE_SPINLOCK(nw_gpio_lock); +EXPORT_SYMBOL(nw_gpio_lock); static unsigned int current_gpio_op; static unsigned int current_gpio_io; static unsigned int current_cpld; -void gpio_modify_op(int mask, int set) +void nw_gpio_modify_op(unsigned int mask, unsigned int set) { unsigned int new_gpio, changed; @@ -86,6 +88,7 @@ void gpio_modify_op(int mask, int set) if (changed & 0xff00) outb(new_gpio >> 8, GP2_IO_BASE); } +EXPORT_SYMBOL(nw_gpio_modify_op); static inline void __gpio_modify_io(int mask, int in) { @@ -118,7 +121,7 @@ static inline void __gpio_modify_io(int mask, int in) } } -void gpio_modify_io(int mask, int in) +void nw_gpio_modify_io(unsigned int mask, unsigned int in) { /* Open up the SuperIO chip */ wb977_open(); @@ -128,11 +131,13 @@ void gpio_modify_io(int mask, int in) /* Close up the EFER gate */ wb977_close(); } +EXPORT_SYMBOL(nw_gpio_modify_io); -int gpio_read(void) +unsigned int nw_gpio_read(void) { return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8; } +EXPORT_SYMBOL(nw_gpio_read); /* * Initialise the Winbond W83977F global registers @@ -322,9 +327,9 @@ static inline void wb977_init_gpio(void) /* * Set Group1/Group2 outputs */ - spin_lock_irqsave(&gpio_lock, flags); - gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } /* @@ -359,34 +364,35 @@ static void __init wb977_init(void) wb977_close(); } -void cpld_modify(int mask, int set) +void nw_cpld_modify(unsigned int mask, unsigned int set) { int msk; current_cpld = (current_cpld & ~mask) | set; - gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0); - gpio_modify_op(GPIO_IOLOAD, 0); + nw_gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0); + nw_gpio_modify_op(GPIO_IOLOAD, 0); for (msk = 8; msk; msk >>= 1) { int bit = current_cpld & msk; - gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0); - gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK); + nw_gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0); + nw_gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK); } - gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0); - gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK); - gpio_modify_op(GPIO_IOLOAD, 0); + nw_gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0); + nw_gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK); + nw_gpio_modify_op(GPIO_IOLOAD, 0); } +EXPORT_SYMBOL(nw_cpld_modify); static void __init cpld_init(void) { unsigned long flags; - spin_lock_irqsave(&gpio_lock, flags); - cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } static unsigned char rwa_unlock[] __initdata = @@ -596,12 +602,6 @@ static void __init rwa010_init(void) rwa010_soundblaster_reset(); } -EXPORT_SYMBOL(gpio_lock); -EXPORT_SYMBOL(gpio_modify_op); -EXPORT_SYMBOL(gpio_modify_io); -EXPORT_SYMBOL(cpld_modify); -EXPORT_SYMBOL(gpio_read); - /* * Initialise any other hardware after we've got the PCI bus * initialised. We may need the PCI bus to talk to this other @@ -616,9 +616,9 @@ static int __init nw_hw_init(void) cpld_init(); rwa010_init(); - spin_lock_irqsave(&gpio_lock, flags); - gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } return 0; } diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c index d91a4f4a32dc..00269fe0be8a 100644 --- a/arch/arm/mach-footbridge/netwinder-leds.c +++ b/arch/arm/mach-footbridge/netwinder-leds.c @@ -32,7 +32,6 @@ static char led_state; static char hw_led_state; static DEFINE_SPINLOCK(leds_lock); -extern spinlock_t gpio_lock; static void netwinder_leds_event(led_event_t evt) { @@ -121,9 +120,9 @@ static void netwinder_leds_event(led_event_t evt) spin_unlock_irqrestore(&leds_lock, flags); if (led_state & LED_STATE_ENABLED) { - spin_lock_irqsave(&gpio_lock, flags); - gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } } diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c index c4f843fc099d..e2c9f0690b16 100644 --- a/arch/arm/mach-footbridge/personal.c +++ b/arch/arm/mach-footbridge/personal.c @@ -4,6 +4,7 @@ * Personal server (Skiff) machine fixup */ #include <linux/init.h> +#include <linux/spinlock.h> #include <asm/hardware/dec21285.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-h720x/include/mach/io.h b/arch/arm/mach-h720x/include/mach/io.h index 1dab74ce88c6..2c8659c21a93 100644 --- a/arch/arm/mach-h720x/include/mach/io.h +++ b/arch/arm/mach-h720x/include/mach/io.h @@ -14,11 +14,9 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-h720x/include/mach/dma.h b/arch/arm/mach-h720x/include/mach/isa-dma.h index 0a9d86ee84fe..3eafb3f163c0 100644 --- a/arch/arm/mach-h720x/include/mach/dma.h +++ b/arch/arm/mach-h720x/include/mach/isa-dma.h @@ -1,5 +1,5 @@ /* - * arch/arm/mach-h720x/include/mach/dma.h + * arch/arm/mach-h720x/include/mach/isa-dma.h * * Architecture DMA routes * @@ -8,13 +8,6 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H -/* - * This is the maximum DMA address that can be DMAd to. - * There should not be more than (0xd0000000 - 0xc0000000) - * bytes of RAM. - */ -#define MAX_DMA_ADDRESS 0xd0000000 - #if defined (CONFIG_CPU_H7201) #define MAX_DMA_CHANNELS 3 #elif defined (CONFIG_CPU_H7202) diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h index cb26f49cc4e1..ef4c1e26f18e 100644 --- a/arch/arm/mach-h720x/include/mach/memory.h +++ b/arch/arm/mach-h720x/include/mach/memory.h @@ -7,23 +7,13 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -/* - * Page offset: - * ( 0xc0000000UL ) - */ #define PHYS_OFFSET UL(0x40000000) - /* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - * - * There is something to do here later !, Mar 2000, Jungjun Kim + * This is the maximum DMA address that can be DMAd to. + * There should not be more than (0xd0000000 - 0xc0000000) + * bytes of RAM. */ - -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) +#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_256M - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_256M) #endif diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c index c10810c936b3..1536583eece0 100644 --- a/arch/arm/mach-imx/dma.c +++ b/arch/arm/mach-imx/dma.c @@ -28,10 +28,11 @@ #include <linux/interrupt.h> #include <linux/errno.h> +#include <asm/scatterlist.h> #include <asm/system.h> #include <asm/irq.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/imx-dma.h> struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; @@ -138,7 +139,7 @@ imx_dma_setup_sg_base(imx_dmach_t dma_ch, int imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode) + unsigned int dmamode) { struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; @@ -223,7 +224,7 @@ imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address, int imx_dma_setup_sg(imx_dmach_t dma_ch, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, - unsigned int dev_addr, dmamode_t dmamode) + unsigned int dev_addr, unsigned int dmamode) { int res; struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; diff --git a/arch/arm/mach-imx/include/mach/imx-dma.h b/arch/arm/mach-imx/include/mach/imx-dma.h index 44d89c35539a..bbe54df7f0de 100644 --- a/arch/arm/mach-imx/include/mach/imx-dma.h +++ b/arch/arm/mach-imx/include/mach/imx-dma.h @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <asm/dma.h> +#include <mach/dma.h> #ifndef __ASM_ARCH_IMX_DMA_H #define __ASM_ARCH_IMX_DMA_H @@ -48,7 +48,7 @@ struct imx_dma_channel { void (*irq_handler) (int, void *); void (*err_handler) (int, void *, int errcode); void *data; - dmamode_t dma_mode; + unsigned int dma_mode; struct scatterlist *sg; unsigned int sgbc; unsigned int sgcount; @@ -66,14 +66,18 @@ extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; /* The type to distinguish channel numbers parameter from ordinal int type */ typedef int imx_dmach_t; +#define DMA_MODE_READ 0 +#define DMA_MODE_WRITE 1 +#define DMA_MODE_MASK 1 + int imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address, - unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode); + unsigned int dma_length, unsigned int dev_addr, unsigned int dmamode); int imx_dma_setup_sg(imx_dmach_t dma_ch, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, - unsigned int dev_addr, dmamode_t dmamode); + unsigned int dev_addr, unsigned int dmamode); int imx_dma_setup_handlers(imx_dmach_t dma_ch, diff --git a/arch/arm/mach-imx/include/mach/imxfb.h b/arch/arm/mach-imx/include/mach/imxfb.h index 3ed9ec8b9f00..870d0d939616 100644 --- a/arch/arm/mach-imx/include/mach/imxfb.h +++ b/arch/arm/mach-imx/include/mach/imxfb.h @@ -1,7 +1,52 @@ /* * This structure describes the machine which we are running on. */ -struct imxfb_mach_info { + +#define PCR_TFT (1 << 31) +#define PCR_COLOR (1 << 30) +#define PCR_PBSIZ_1 (0 << 28) +#define PCR_PBSIZ_2 (1 << 28) +#define PCR_PBSIZ_4 (2 << 28) +#define PCR_PBSIZ_8 (3 << 28) +#define PCR_BPIX_1 (0 << 25) +#define PCR_BPIX_2 (1 << 25) +#define PCR_BPIX_4 (2 << 25) +#define PCR_BPIX_8 (3 << 25) +#define PCR_BPIX_12 (4 << 25) +#define PCR_BPIX_16 (4 << 25) +#define PCR_PIXPOL (1 << 24) +#define PCR_FLMPOL (1 << 23) +#define PCR_LPPOL (1 << 22) +#define PCR_CLKPOL (1 << 21) +#define PCR_OEPOL (1 << 20) +#define PCR_SCLKIDLE (1 << 19) +#define PCR_END_SEL (1 << 18) +#define PCR_END_BYTE_SWAP (1 << 17) +#define PCR_REV_VS (1 << 16) +#define PCR_ACD_SEL (1 << 15) +#define PCR_ACD(x) (((x) & 0x7f) << 8) +#define PCR_SCLK_SEL (1 << 7) +#define PCR_SHARP (1 << 6) +#define PCR_PCD(x) ((x) & 0x3f) + +#define PWMR_CLS(x) (((x) & 0x1ff) << 16) +#define PWMR_LDMSK (1 << 15) +#define PWMR_SCR1 (1 << 10) +#define PWMR_SCR0 (1 << 9) +#define PWMR_CC_EN (1 << 8) +#define PWMR_PW(x) ((x) & 0xff) + +#define LSCR1_PS_RISE_DELAY(x) (((x) & 0x7f) << 26) +#define LSCR1_CLS_RISE_DELAY(x) (((x) & 0x3f) << 16) +#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8) +#define LSCR1_GRAY2(x) (((x) & 0xf) << 4) +#define LSCR1_GRAY1(x) (((x) & 0xf)) + +#define DMACR_BURST (1 << 31) +#define DMACR_HM(x) (((x) & 0xf) << 16) +#define DMACR_TM(x) ((x) & 0xf) + +struct imx_fb_platform_data { u_long pixclock; u_short xres; @@ -34,4 +79,5 @@ struct imxfb_mach_info { void (*lcd_power)(int); void (*backlight_power)(int); }; -void set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info); + +void set_imx_fb_info(struct imx_fb_platform_data *); diff --git a/arch/arm/mach-imx/include/mach/io.h b/arch/arm/mach-imx/include/mach/io.h index c50c5fa6fb81..9e197ae4590f 100644 --- a/arch/arm/mach-imx/include/mach/io.h +++ b/arch/arm/mach-imx/include/mach/io.h @@ -20,11 +20,9 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-imx/include/mach/memory.h b/arch/arm/mach-imx/include/mach/memory.h index 5c453063c0ed..a93df7cba694 100644 --- a/arch/arm/mach-imx/include/mach/memory.h +++ b/arch/arm/mach-imx/include/mach/memory.h @@ -23,14 +23,4 @@ #define PHYS_OFFSET UL(0x08000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) (x - PAGE_OFFSET + PHYS_OFFSET) -#define __bus_to_virt(x) (x - PHYS_OFFSET + PAGE_OFFSET) - #endif diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index 8d761fdd2ecd..989ecf5f5c46 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -10,42 +10,12 @@ */ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/list.h> #include <linux/errno.h> -#include <linux/err.h> -#include <linux/string.h> #include <linux/clk.h> #include <linux/mutex.h> -#include <asm/hardware/icst525.h> - -#include "clock.h" - -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); +#include <asm/clkdev.h> +#include <mach/clkdev.h> int clk_enable(struct clk *clk) { @@ -67,7 +37,6 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst525_vco vco; - vco = icst525_khz_to_vco(clk->params, rate / 1000); return icst525_khz(clk->params, vco) * 1000; } @@ -76,56 +45,15 @@ EXPORT_SYMBOL(clk_round_rate); int clk_set_rate(struct clk *clk, unsigned long rate) { int ret = -EIO; + if (clk->setvco) { struct icst525_vco vco; vco = icst525_khz_to_vco(clk->params, rate / 1000); clk->rate = icst525_khz(clk->params, vco) * 1000; - - printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", - clk->name, vco.s, vco.r, vco.v); - clk->setvco(clk, vco); ret = 0; } - return 0; + return ret; } EXPORT_SYMBOL(clk_set_rate); - -/* - * These are fixed clocks. - */ -static struct clk kmi_clk = { - .name = "KMIREFCLK", - .rate = 24000000, -}; - -static struct clk uart_clk = { - .name = "UARTCLK", - .rate = 14745600, -}; - -int clk_register(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init(void) -{ - clk_register(&kmi_clk); - clk_register(&uart_clk); - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-integrator/clock.h b/arch/arm/mach-integrator/clock.h index 09e6328ceba9..e69de29bb2d1 100644 --- a/arch/arm/mach-integrator/clock.h +++ b/arch/arm/mach-integrator/clock.h @@ -1,25 +0,0 @@ -/* - * linux/arch/arm/mach-integrator/clock.h - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -struct module; -struct icst525_params; - -struct clk { - struct list_head node; - unsigned long rate; - struct module *owner; - const char *name; - const struct icst525_params *params; - void *data; - void (*setvco)(struct clk *, struct icst525_vco vco); -}; - -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 595b7392ee4e..c89c949b4d45 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -21,6 +21,8 @@ #include <linux/amba/serial.h> #include <linux/io.h> +#include <asm/clkdev.h> +#include <mach/clkdev.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/hardware/arm_timer.h> @@ -108,10 +110,43 @@ static struct amba_device *amba_devs[] __initdata = { &kmi1_device, }; +/* + * These are fixed clocks. + */ +static struct clk clk24mhz = { + .rate = 24000000, +}; + +static struct clk uartclk = { + .rate = 14745600, +}; + +static struct clk_lookup lookups[] __initdata = { + { /* UART0 */ + .dev_id = "mb:16", + .clk = &uartclk, + }, { /* UART1 */ + .dev_id = "mb:17", + .clk = &uartclk, + }, { /* KMI0 */ + .dev_id = "mb:18", + .clk = &clk24mhz, + }, { /* KMI1 */ + .dev_id = "mb:19", + .clk = &clk24mhz, + }, { /* MMCI - IntegratorCP */ + .dev_id = "mb:1c", + .clk = &uartclk, + } +}; + static int __init integrator_init(void) { int i; + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; amba_device_register(d, &iomem_resource); diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 172299a78302..0058c937719e 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -22,13 +22,13 @@ #include <linux/amba/clcd.h> #include <linux/io.h> +#include <asm/clkdev.h> +#include <mach/clkdev.h> #include <asm/hardware/icst525.h> #include <mach/lm.h> #include <mach/impd1.h> #include <asm/sizes.h> -#include "clock.h" - static int module_id; module_param_named(lmid, module_id, int, 0444); @@ -37,6 +37,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position"); struct impd1_module { void __iomem *base; struct clk vcos[2]; + struct clk_lookup *clks[3]; }; static const struct icst525_params impd1_vco_params = { @@ -339,9 +340,8 @@ static struct impd1_device impd1_devs[] = { } }; -static const char *impd1_vconames[2] = { - "CLCDCLK", - "AUXVCO2", +static struct clk fixed_14745600 = { + .rate = 14745600, }; static int impd1_probe(struct lm_device *dev) @@ -374,14 +374,20 @@ static int impd1_probe(struct lm_device *dev) for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { impd1->vcos[i].owner = THIS_MODULE, - impd1->vcos[i].name = impd1_vconames[i], impd1->vcos[i].params = &impd1_vco_params, impd1->vcos[i].data = impd1, impd1->vcos[i].setvco = impd1_setvco; - - clk_register(&impd1->vcos[i]); } + impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000", + dev->id); + impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100", + dev->id); + impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200", + dev->id); + for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) + clkdev_add(impd1->clks[i]); + for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { struct impd1_device *idev = impd1_devs + i; struct amba_device *d; @@ -434,8 +440,8 @@ static void impd1_remove(struct lm_device *dev) device_for_each_child(&dev->dev, NULL, impd1_remove_one); - for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) - clk_unregister(&impd1->vcos[i]); + for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) + clkdev_drop(impd1->clks[i]); lm_set_drvdata(dev, NULL); diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h new file mode 100644 index 000000000000..9293e410832a --- /dev/null +++ b/arch/arm/mach-integrator/include/mach/clkdev.h @@ -0,0 +1,25 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#include <linux/module.h> +#include <asm/hardware/icst525.h> + +struct clk { + unsigned long rate; + struct module *owner; + const struct icst525_params *params; + void *data; + void (*setvco)(struct clk *, struct icst525_vco vco); +}; + +static inline int __clk_get(struct clk *clk) +{ + return try_module_get(clk->owner); +} + +static inline void __clk_put(struct clk *clk) +{ + module_put(clk->owner); +} + +#endif diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h index be7e63c21d25..2b2e7a110724 100644 --- a/arch/arm/mach-integrator/include/mach/memory.h +++ b/arch/arm/mach-integrator/include/mach/memory.h @@ -24,16 +24,9 @@ * Physical DRAM offset. */ #define PHYS_OFFSET UL(0x00000000) -#define BUS_OFFSET UL(0x80000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) (x - PAGE_OFFSET + BUS_OFFSET) -#define __bus_to_virt(x) (x - BUS_OFFSET + PAGE_OFFSET) +#define BUS_OFFSET UL(0x80000000) +#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET) +#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET) #endif diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 88026ccd5ac9..427c2d8dc123 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -21,6 +21,8 @@ #include <linux/amba/clcd.h> #include <linux/io.h> +#include <asm/clkdev.h> +#include <mach/clkdev.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/setup.h> @@ -38,7 +40,6 @@ #include <asm/mach/time.h> #include "common.h" -#include "clock.h" #define INTCP_PA_MMC_BASE 0x1c000000 #define INTCP_PA_AACI_BASE 0x1d000000 @@ -289,15 +290,16 @@ static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco) writel(0, CM_LOCK); } -static struct clk cp_clcd_clk = { - .name = "CLCDCLK", +static struct clk cp_auxclk = { .params = &cp_auxvco_params, .setvco = cp_auxvco_set, }; -static struct clk cp_mmci_clk = { - .name = "MCLK", - .rate = 14745600, +static struct clk_lookup cp_lookups[] = { + { /* CLCD */ + .dev_id = "mb:c0", + .clk = &cp_auxclk, + }, }; /* @@ -554,8 +556,8 @@ static void __init intcp_init(void) { int i; - clk_register(&cp_clcd_clk); - clk_register(&cp_mmci_clk); + for (i = 0; i < ARRAY_SIZE(cp_lookups); i++) + clkdev_add(&cp_lookups[i]); platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); diff --git a/arch/arm/mach-iop13xx/include/mach/dma.h b/arch/arm/mach-iop13xx/include/mach/dma.h deleted file mode 100644 index d79846fbb394..000000000000 --- a/arch/arm/mach-iop13xx/include/mach/dma.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef _IOP13XX_DMA_H -#define _IOP13XX_DMA_H -#endif diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index b82602d529bf..e012bf13c955 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h @@ -16,18 +16,6 @@ #define IOP13XX_PMMR_P_START (IOP13XX_PMMR_PHYS_MEM_BASE) #define IOP13XX_PMMR_P_END (IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_SIZE) -/* - * Virtual view <-> PCI DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ - -/* RAM has 1:1 mapping on the PCIe/x Busses */ -#define __virt_to_bus(x) (__virt_to_phys(x)) -#define __bus_to_virt(x) (__phys_to_virt(x)) - static inline dma_addr_t __virt_to_lbus(unsigned long x) { return x + IOP13XX_PMMR_PHYS_MEM_BASE - IOP13XX_PMMR_VIRT_MEM_BASE; @@ -55,7 +43,7 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) if (is_lbus_device(dev) && __is_lbus_dma(__dma)) \ __virt = __lbus_to_virt(__dma); \ else \ - __virt = __bus_to_virt(__dma); \ + __virt = __phys_to_virt(__dma); \ (void *)__virt; \ }) @@ -66,7 +54,7 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) if (is_lbus_device(dev) && __is_lbus_virt(__virt)) \ __dma = __virt_to_lbus(__virt); \ else \ - __dma = __virt_to_bus(__virt); \ + __dma = __virt_to_phys(__virt); \ __dma; \ }) diff --git a/arch/arm/mach-iop13xx/include/mach/timex.h b/arch/arm/mach-iop13xx/include/mach/timex.h index 5b1f1c8a8270..45fb2745bb54 100644 --- a/arch/arm/mach-iop13xx/include/mach/timex.h +++ b/arch/arm/mach-iop13xx/include/mach/timex.h @@ -1,3 +1 @@ -#include <mach/hardware.h> - #define CLOCK_TICK_RATE (100 * HZ) diff --git a/arch/arm/mach-iop32x/include/mach/dma.h b/arch/arm/mach-iop32x/include/mach/dma.h deleted file mode 100644 index f8bd817f205d..000000000000 --- a/arch/arm/mach-iop32x/include/mach/dma.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * arch/arm/mach-iop32x/include/mach/dma.h - * - * Copyright (C) 2004 Intel Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ diff --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h index ce54705ba3d4..339e5854728b 100644 --- a/arch/arm/mach-iop32x/include/mach/io.h +++ b/arch/arm/mach-iop32x/include/mach/io.h @@ -11,7 +11,7 @@ #ifndef __IO_H #define __IO_H -#include <mach/hardware.h> +#include <asm/hardware/iop3xx.h> extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size, unsigned int mtype); diff --git a/arch/arm/mach-iop32x/include/mach/memory.h b/arch/arm/mach-iop32x/include/mach/memory.h index 42cd4bf3148c..c30f6450ad50 100644 --- a/arch/arm/mach-iop32x/include/mach/memory.h +++ b/arch/arm/mach-iop32x/include/mach/memory.h @@ -5,22 +5,9 @@ #ifndef __MEMORY_H #define __MEMORY_H -#include <mach/hardware.h> - /* * Physical DRAM offset. */ #define PHYS_OFFSET UL(0xa0000000) -/* - * Virtual view <-> PCI DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) (__virt_to_phys(x)) -#define __bus_to_virt(x) (__phys_to_virt(x)) - - #endif diff --git a/arch/arm/mach-iop32x/include/mach/system.h b/arch/arm/mach-iop32x/include/mach/system.h index 20f923e54f46..32d9e5b0a28d 100644 --- a/arch/arm/mach-iop32x/include/mach/system.h +++ b/arch/arm/mach-iop32x/include/mach/system.h @@ -7,8 +7,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - #include <asm/mach-types.h> +#include <asm/hardware/iop3xx.h> +#include <mach/n2100.h> static inline void arch_idle(void) { diff --git a/arch/arm/mach-iop32x/include/mach/timex.h b/arch/arm/mach-iop32x/include/mach/timex.h index a541afced3cb..7262ab81419d 100644 --- a/arch/arm/mach-iop32x/include/mach/timex.h +++ b/arch/arm/mach-iop32x/include/mach/timex.h @@ -3,7 +3,4 @@ * * IOP32x architecture timex specifications */ - -#include <mach/hardware.h> - #define CLOCK_TICK_RATE (100 * HZ) diff --git a/arch/arm/mach-iop33x/include/mach/dma.h b/arch/arm/mach-iop33x/include/mach/dma.h deleted file mode 100644 index d8b42232931d..000000000000 --- a/arch/arm/mach-iop33x/include/mach/dma.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * arch/arm/mach-iop33x/include/mach/dma.h - * - * Copyright (C) 2004 Intel Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h index 158874631217..e99a7ed6d050 100644 --- a/arch/arm/mach-iop33x/include/mach/io.h +++ b/arch/arm/mach-iop33x/include/mach/io.h @@ -11,7 +11,7 @@ #ifndef __IO_H #define __IO_H -#include <mach/hardware.h> +#include <asm/hardware/iop3xx.h> extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size, unsigned int mtype); diff --git a/arch/arm/mach-iop33x/include/mach/memory.h b/arch/arm/mach-iop33x/include/mach/memory.h index 2cef0bbb354f..a30a96aa6d2d 100644 --- a/arch/arm/mach-iop33x/include/mach/memory.h +++ b/arch/arm/mach-iop33x/include/mach/memory.h @@ -5,22 +5,9 @@ #ifndef __MEMORY_H #define __MEMORY_H -#include <mach/hardware.h> - /* * Physical DRAM offset. */ #define PHYS_OFFSET UL(0x00000000) -/* - * Virtual view <-> PCI DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) (__virt_to_phys(x)) -#define __bus_to_virt(x) (__phys_to_virt(x)) - - #endif diff --git a/arch/arm/mach-iop33x/include/mach/system.h b/arch/arm/mach-iop33x/include/mach/system.h index 7bf3bfb49446..0cb3ad862acd 100644 --- a/arch/arm/mach-iop33x/include/mach/system.h +++ b/arch/arm/mach-iop33x/include/mach/system.h @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <asm/hardware/iop3xx.h> static inline void arch_idle(void) { diff --git a/arch/arm/mach-iop33x/include/mach/timex.h b/arch/arm/mach-iop33x/include/mach/timex.h index c75760844d49..54c589091d6e 100644 --- a/arch/arm/mach-iop33x/include/mach/timex.h +++ b/arch/arm/mach-iop33x/include/mach/timex.h @@ -3,7 +3,4 @@ * * IOP3xx architecture timex specifications */ - -#include <mach/hardware.h> - #define CLOCK_TICK_RATE (100 * HZ) diff --git a/arch/arm/mach-ixp2000/include/mach/dma.h b/arch/arm/mach-ixp2000/include/mach/dma.h deleted file mode 100644 index 26063d60f622..000000000000 --- a/arch/arm/mach-ixp2000/include/mach/dma.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * arch/arm/mach-ixp2000/include/mach/dma.h - * - * Copyright (C) 2002 Intel Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h index 241529a7c52d..aee7eb8a71b2 100644 --- a/arch/arm/mach-ixp2000/include/mach/memory.h +++ b/arch/arm/mach-ixp2000/include/mach/memory.h @@ -15,13 +15,6 @@ #define PHYS_OFFSET UL(0x00000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ #include <mach/ixp2000-regs.h> #define __virt_to_bus(v) \ diff --git a/arch/arm/mach-ixp23xx/include/mach/dma.h b/arch/arm/mach-ixp23xx/include/mach/dma.h deleted file mode 100644 index 8886544b93f7..000000000000 --- a/arch/arm/mach-ixp23xx/include/mach/dma.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * arch/arm/mach-ixp23xx/include/mach/dma.h - */ diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h index 305ea1808c71..fd9ef8e519f7 100644 --- a/arch/arm/mach-ixp23xx/include/mach/io.h +++ b/arch/arm/mach-ixp23xx/include/mach/io.h @@ -20,8 +20,6 @@ #define __io(p) ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT)) #define __mem_pci(a) (a) -#include <linux/kernel.h> /* For BUG */ - static inline void __iomem * ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned int mtype) { diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h index 9d40115f7ebe..fdd138706c70 100644 --- a/arch/arm/mach-ixp23xx/include/mach/memory.h +++ b/arch/arm/mach-ixp23xx/include/mach/memory.h @@ -19,16 +19,6 @@ */ #define PHYS_OFFSET (0x00000000) - -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#ifndef __ASSEMBLY__ - #define __virt_to_bus(v) \ ({ unsigned int ret; \ ret = ((__virt_to_phys(v) - 0x00000000) + \ @@ -43,6 +33,3 @@ #define arch_is_coherent() 1 #endif - - -#endif diff --git a/arch/arm/mach-ixp4xx/include/mach/dma.h b/arch/arm/mach-ixp4xx/include/mach/dma.h deleted file mode 100644 index 00c5070c0201..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/dma.h - * - * Copyright (C) 2001-2004 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#include <linux/device.h> -#include <asm/page.h> -#include <asm/sizes.h> -#include <mach/hardware.h> - -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M) - -#endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h index 319948e31bec..ce63048d45eb 100644 --- a/arch/arm/mach-ixp4xx/include/mach/io.h +++ b/arch/arm/mach-ixp4xx/include/mach/io.h @@ -49,8 +49,6 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); #else -#include <linux/mm.h> - /* * In the case of using indirect PCI, we simply return the actual PCI * address and our read/write implementation use that to drive the @@ -241,7 +239,7 @@ __ixp4xx_readsl(const volatile void __iomem *bus_addr, u32 *vaddr, u32 count) #ifndef CONFIG_PCI -#define __io(v) v +#define __io(v) __typesafe_io(v) #else diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h index c4d2830ac987..98f5e5e20980 100644 --- a/arch/arm/mach-ixp4xx/include/mach/memory.h +++ b/arch/arm/mach-ixp4xx/include/mach/memory.h @@ -22,19 +22,8 @@ void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes); ixp4xx_adjust_zones(node, size, holes) #define ISA_DMA_THRESHOLD (SZ_64M - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M) #endif -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - * - * These are dummies for now. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 0bb1fbd84ccb..7b8ef97fb501 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -57,6 +57,7 @@ void __init kirkwood_map_io(void) ****************************************************************************/ static struct orion_ehci_data kirkwood_ehci_data = { .dram = &kirkwood_mbus_dram_info, + .phy_version = EHCI_PHY_NA, }; static u64 ehci_dmamask = 0xffffffffUL; @@ -153,6 +154,64 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) /***************************************************************************** + * GE01 + ****************************************************************************/ +struct mv643xx_eth_shared_platform_data kirkwood_ge01_shared_data = { + .dram = &kirkwood_mbus_dram_info, + .shared_smi = &kirkwood_ge00_shared, +}; + +static struct resource kirkwood_ge01_shared_resources[] = { + { + .name = "ge01 base", + .start = GE01_PHYS_BASE + 0x2000, + .end = GE01_PHYS_BASE + 0x3fff, + .flags = IORESOURCE_MEM, + }, { + .name = "ge01 err irq", + .start = IRQ_KIRKWOOD_GE01_ERR, + .end = IRQ_KIRKWOOD_GE01_ERR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kirkwood_ge01_shared = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 1, + .dev = { + .platform_data = &kirkwood_ge01_shared_data, + }, + .num_resources = ARRAY_SIZE(kirkwood_ge01_shared_resources), + .resource = kirkwood_ge01_shared_resources, +}; + +static struct resource kirkwood_ge01_resources[] = { + { + .name = "ge01 irq", + .start = IRQ_KIRKWOOD_GE01_SUM, + .end = IRQ_KIRKWOOD_GE01_SUM, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kirkwood_ge01 = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = 1, + .resource = kirkwood_ge01_resources, +}; + +void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) +{ + eth_data->shared = &kirkwood_ge01_shared; + kirkwood_ge01.dev.platform_data = eth_data; + + platform_device_register(&kirkwood_ge01_shared); + platform_device_register(&kirkwood_ge01); +} + + +/***************************************************************************** * Ethernet switch ****************************************************************************/ static struct resource kirkwood_switch_resources[] = { diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 5774632a67e3..fe367c18e722 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -30,6 +30,7 @@ void kirkwood_pcie_id(u32 *dev, u32 *rev); void kirkwood_ehci_init(void); void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data); +void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data); void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq); void kirkwood_pcie_init(void); void kirkwood_rtc_init(void); diff --git a/arch/arm/mach-kirkwood/include/mach/dma.h b/arch/arm/mach-kirkwood/include/mach/dma.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/arm/mach-kirkwood/include/mach/dma.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-kirkwood/include/mach/gpio.h b/arch/arm/mach-kirkwood/include/mach/gpio.h new file mode 100644 index 000000000000..81b335eb62ec --- /dev/null +++ b/arch/arm/mach-kirkwood/include/mach/gpio.h @@ -0,0 +1,38 @@ +/* + * arch/asm-arm/mach-kirkwood/include/mach/gpio.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include <mach/irqs.h> +#include <plat/gpio.h> +#include <asm-generic/gpio.h> /* cansleep wrappers */ + +#define GPIO_MAX 50 +#define GPIO_OFF(pin) (((pin) >> 5) ? 0x0140 : 0x0100) +#define GPIO_OUT(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x00) +#define GPIO_IO_CONF(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x04) +#define GPIO_BLINK_EN(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x08) +#define GPIO_IN_POL(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x0c) +#define GPIO_DATA_IN(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x10) +#define GPIO_EDGE_CAUSE(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x14) +#define GPIO_EDGE_MASK(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x18) +#define GPIO_LEVEL_MASK(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x1c) + +static inline int gpio_to_irq(int pin) +{ + return pin + IRQ_KIRKWOOD_GPIO_START; +} + +static inline int irq_to_gpio(int irq) +{ + return irq - IRQ_KIRKWOOD_GPIO_START; +} + + +#endif diff --git a/arch/arm/mach-kirkwood/include/mach/irqs.h b/arch/arm/mach-kirkwood/include/mach/irqs.h index ffab89f21c11..f00a0a45a67e 100644 --- a/arch/arm/mach-kirkwood/include/mach/irqs.h +++ b/arch/arm/mach-kirkwood/include/mach/irqs.h @@ -11,8 +11,6 @@ #ifndef __ASM_ARCH_IRQS_H #define __ASM_ARCH_IRQS_H -#include "kirkwood.h" /* need GPIO_MAX */ - /* * Low Interrupt Controller */ @@ -51,12 +49,13 @@ #define IRQ_KIRKWOOD_GPIO_HIGH_8_15 40 #define IRQ_KIRKWOOD_GPIO_HIGH_16_23 41 #define IRQ_KIRKWOOD_GE00_ERR 46 +#define IRQ_KIRKWOOD_GE01_ERR 47 /* * KIRKWOOD General Purpose Pins */ #define IRQ_KIRKWOOD_GPIO_START 64 -#define NR_GPIO_IRQS GPIO_MAX +#define NR_GPIO_IRQS 50 #define NR_IRQS (IRQ_KIRKWOOD_GPIO_START + NR_GPIO_IRQS) diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index eae42406fd86..ada480c0e197 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -117,7 +117,4 @@ #define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x80000) -#define GPIO_MAX 50 - - #endif diff --git a/arch/arm/mach-kirkwood/include/mach/memory.h b/arch/arm/mach-kirkwood/include/mach/memory.h index b5fb34bdccd5..45431e131465 100644 --- a/arch/arm/mach-kirkwood/include/mach/memory.h +++ b/arch/arm/mach-kirkwood/include/mach/memory.h @@ -7,8 +7,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - - #endif diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c index 5790643ffe07..efb86b700276 100644 --- a/arch/arm/mach-kirkwood/irq.c +++ b/arch/arm/mach-kirkwood/irq.c @@ -13,10 +13,45 @@ #include <linux/irq.h> #include <linux/io.h> #include <plat/irq.h> +#include <asm/gpio.h> #include "common.h" +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + BUG_ON(irq < IRQ_KIRKWOOD_GPIO_LOW_0_7); + BUG_ON(irq > IRQ_KIRKWOOD_GPIO_HIGH_16_23); + + orion_gpio_irq_handler((irq - IRQ_KIRKWOOD_GPIO_LOW_0_7) << 3); +} + void __init kirkwood_init_irq(void) { + int i; + orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); + + /* + * Mask and clear GPIO IRQ interrupts. + */ + writel(0, GPIO_LEVEL_MASK(0)); + writel(0, GPIO_EDGE_MASK(0)); + writel(0, GPIO_EDGE_CAUSE(0)); + writel(0, GPIO_LEVEL_MASK(32)); + writel(0, GPIO_EDGE_MASK(32)); + writel(0, GPIO_EDGE_CAUSE(32)); + + for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) { + set_irq_chip(i, &orion_gpio_irq_level_chip); + set_irq_handler(i, handle_level_irq); + irq_desc[i].status |= IRQ_LEVEL; + set_irq_flags(i, IRQF_VALID); + } + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler); + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23, gpio_irq_handler); } diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index 175054abd630..9a0e905d10cd 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -80,24 +80,38 @@ static struct dsa_platform_data rd88f6281_switch_data = { .port_names[1] = "lan2", .port_names[2] = "lan3", .port_names[3] = "lan4", - .port_names[4] = "wan", .port_names[5] = "cpu", }; +static struct mv643xx_eth_platform_data rd88f6281_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(11), +}; + static struct mv_sata_platform_data rd88f6281_sata_data = { .n_ports = 2, }; static void __init rd88f6281_init(void) { + u32 dev, rev; + /* * Basic setup. Needs to be called early. */ kirkwood_init(); kirkwood_ehci_init(); + kirkwood_ge00_init(&rd88f6281_ge00_data); + kirkwood_pcie_id(&dev, &rev); + if (rev == MV88F6281_REV_A0) { + rd88f6281_switch_data.sw_addr = 10; + kirkwood_ge01_init(&rd88f6281_ge01_data); + } else { + rd88f6281_switch_data.port_names[4] = "wan"; + } kirkwood_ge00_switch_init(&rd88f6281_switch_data, NO_IRQ); + kirkwood_rtc_init(); kirkwood_sata_init(&rd88f6281_sata_data); kirkwood_uart0_init(); diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig index ce1cf8de2b4d..2754daabda55 100644 --- a/arch/arm/mach-ks8695/Kconfig +++ b/arch/arm/mach-ks8695/Kconfig @@ -8,6 +8,12 @@ config MACH_KS8695 Say 'Y' here if you want your kernel to run on the original Kendin-Micrel KS8695 development board. +config MACH_DSM320 + bool "DSM-320 Wireless Media Player" + help + Say 'Y' here if you want your kernel to run on the D-Link + DSM-320 Wireless Media Player. + endmenu endif diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index ade42b73afbb..f735d2cc0294 100644 --- a/arch/arm/mach-ks8695/Makefile +++ b/arch/arm/mach-ks8695/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_LEDS) += leds.o # Board-specific support obj-$(CONFIG_MACH_KS8695) += board-micrel.o +obj-$(CONFIG_MACH_DSM320) += board-dsm320.o diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c new file mode 100644 index 000000000000..521ff0789f39 --- /dev/null +++ b/arch/arm/mach-ks8695/board-dsm320.c @@ -0,0 +1,131 @@ +/* + * arch/arm/mach-ks8695/board-dsm320.c + * + * DSM-320 D-Link Wireless Media Player, board support. + * + * Copyright 2008 Simtec Electronics + * Daniel Silverstone <dsilvers@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/partitions.h> + +#include <asm/mach-types.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/devices.h> +#include <mach/gpio.h> + +#include "generic.h" + +#ifdef CONFIG_PCI +static int dsm320_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + switch (slot) { + case 0: + /* PCI-AHB bridge? */ + return KS8695_IRQ_EXTERN0; + case 18: + /* Mini PCI slot */ + return KS8695_IRQ_EXTERN2; + case 20: + /* RealMAGIC chip */ + return KS8695_IRQ_EXTERN0; + } + BUG(); +} + +static struct ks8695_pci_cfg __initdata dsm320_pci = { + .mode = KS8695_MODE_MINIPCI, + .map_irq = dsm320_pci_map_irq, +}; + +static void __init dsm320_register_pci(void) +{ + /* Initialise the GPIO lines for interrupt mode */ + /* RealMAGIC */ + ks8695_gpio_interrupt(KS8695_GPIO_0, IRQ_TYPE_LEVEL_LOW); + /* MiniPCI Slot */ + ks8695_gpio_interrupt(KS8695_GPIO_2, IRQ_TYPE_LEVEL_LOW); + + ks8695_init_pci(&dsm320_pci); +} + +#else +static inline void __init dsm320_register_pci(void) { } +#endif + +static struct physmap_flash_data dsm320_nor_pdata = { + .width = 4, + .nr_parts = 0, +}; + +static struct resource dsm320_nor_resource[] = { + [0] = { + .start = SZ_32M, /* We expect the bootloader to map + * the flash here. + */ + .end = SZ_32M + SZ_4M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device dsm320_device_nor = { + .name = "physmap-flash", + .id = -1, + .num_resources = ARRAY_SIZE(dsm320_nor_resource), + .resource = dsm320_nor_resource, + .dev = { + .platform_data = &dsm320_nor_pdata, + }, +}; + +void __init dsm320_register_nor(void) +{ + int ret; + + ret = platform_device_register(&dsm320_device_nor); + if (ret < 0) + printk(KERN_ERR "failed to register physmap-flash device\n"); +} + +static void __init dsm320_init(void) +{ + /* GPIO registration */ + ks8695_register_gpios(); + + /* PCI registration */ + dsm320_register_pci(); + + /* Network device */ + ks8695_add_device_lan(); /* eth0 = LAN */ + + /* NOR devices */ + dsm320_register_nor(); +} + +MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player") + /* Maintainer: Simtec Electronics. */ + .phys_io = KS8695_IO_PA, + .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc, + .boot_params = KS8695_SDRAM_PA + 0x100, + .map_io = ks8695_map_io, + .init_irq = ks8695_init_irq, + .init_machine = dsm320_init, + .timer = &ks8695_timer, +MACHINE_END diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c index 0468e93b7d3b..8ceaf5ac6e2c 100644 --- a/arch/arm/mach-ks8695/board-micrel.c +++ b/arch/arm/mach-ks8695/board-micrel.c @@ -18,6 +18,7 @@ #include <asm/mach/map.h> #include <asm/mach/irq.h> +#include <mach/gpio.h> #include <mach/devices.h> #include "generic.h" @@ -39,6 +40,8 @@ static void __init micrel_init(void) { printk(KERN_INFO "Micrel KS8695 Development Board initializing\n"); + ks8695_register_gpios(); + #ifdef CONFIG_PCI ks8695_init_pci(&micrel_pci); #endif diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c index 4bd251482c8f..36ab0fd3d9b6 100644 --- a/arch/arm/mach-ks8695/devices.c +++ b/arch/arm/mach-ks8695/devices.c @@ -25,19 +25,20 @@ #include <mach/regs-wan.h> #include <mach/regs-lan.h> #include <mach/regs-hpna.h> +#include <mach/regs-switch.h> +#include <mach/regs-misc.h> /* -------------------------------------------------------------------- * Ethernet * -------------------------------------------------------------------- */ -#if defined(CONFIG_ARM_KS8695_ETHER) || defined(CONFIG_ARM_KS8695_ETHER_MODULE) static u64 eth_dmamask = 0xffffffffUL; static struct resource ks8695_wan_resources[] = { [0] = { - .start = KS8695_WAN_VA, - .end = KS8695_WAN_VA + 0x00ff, + .start = KS8695_WAN_PA, + .end = KS8695_WAN_PA + 0x00ff, .flags = IORESOURCE_MEM, }, [1] = { @@ -58,6 +59,12 @@ static struct resource ks8695_wan_resources[] = { .end = KS8695_IRQ_WAN_LINK, .flags = IORESOURCE_IRQ, }, + [4] = { + .name = "WAN PHY", + .start = KS8695_MISC_PA, + .end = KS8695_MISC_PA + 0x1f, + .flags = IORESOURCE_MEM, + }, }; static struct platform_device ks8695_wan_device = { @@ -74,8 +81,8 @@ static struct platform_device ks8695_wan_device = { static struct resource ks8695_lan_resources[] = { [0] = { - .start = KS8695_LAN_VA, - .end = KS8695_LAN_VA + 0x00ff, + .start = KS8695_LAN_PA, + .end = KS8695_LAN_PA + 0x00ff, .flags = IORESOURCE_MEM, }, [1] = { @@ -90,6 +97,12 @@ static struct resource ks8695_lan_resources[] = { .end = KS8695_IRQ_LAN_TX_STATUS, .flags = IORESOURCE_IRQ, }, + [3] = { + .name = "LAN SWITCH", + .start = KS8695_SWITCH_PA, + .end = KS8695_SWITCH_PA + 0x4f, + .flags = IORESOURCE_MEM, + }, }; static struct platform_device ks8695_lan_device = { @@ -106,8 +119,8 @@ static struct platform_device ks8695_lan_device = { static struct resource ks8695_hpna_resources[] = { [0] = { - .start = KS8695_HPNA_VA, - .end = KS8695_HPNA_VA + 0x00ff, + .start = KS8695_HPNA_PA, + .end = KS8695_HPNA_PA + 0x00ff, .flags = IORESOURCE_MEM, }, [1] = { @@ -149,18 +162,12 @@ void __init ks8696_add_device_hpna(void) { platform_device_register(&ks8695_hpna_device); } -#else -void __init ks8695_add_device_wan(void) {} -void __init ks8695_add_device_lan(void) {} -void __init ks8696_add_device_hpna(void) {} -#endif /* -------------------------------------------------------------------- * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_KS8695_WATCHDOG) || defined(CONFIG_KS8695_WATCHDOG_MODULE) static struct platform_device ks8695_wdt_device = { .name = "ks8695_wdt", .id = -1, @@ -171,9 +178,6 @@ static void __init ks8695_add_device_watchdog(void) { platform_device_register(&ks8695_wdt_device); } -#else -static void __init ks8695_add_device_watchdog(void) {} -#endif /* -------------------------------------------------------------------- @@ -190,7 +194,7 @@ void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) gpio_direction_output(cpu_led, 1); gpio_direction_output(timer_led, 1); - ks8695_leds_cpu = cpu_led; + ks8695_leds_cpu = cpu_led; ks8695_leds_timer = timer_led; } #else diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c index 9aecf0c4b8b1..55fbf7111a5b 100644 --- a/arch/arm/mach-ks8695/gpio.c +++ b/arch/arm/mach-ks8695/gpio.c @@ -2,6 +2,8 @@ * arch/arm/mach-ks8695/gpio.c * * Copyright (C) 2006 Andrew Victor + * Updated to GPIOLIB, Copyright 2008 Simtec Electronics + * Daniel Silverstone <dsilvers@simtec.co.uk> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -35,7 +37,7 @@ * Configure a GPIO line for either GPIO function, or its internal * function (Interrupt, Timer, etc). */ -static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio) +static void ks8695_gpio_mode(unsigned int pin, short gpio) { unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; unsigned long x, flags; @@ -61,7 +63,7 @@ static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8 /* * Configure GPIO pin as external interrupt source. */ -int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type) +int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) { unsigned long x, flags; @@ -94,7 +96,7 @@ EXPORT_SYMBOL(ks8695_gpio_interrupt); /* * Configure the GPIO line as an input. */ -int __init_or_module gpio_direction_input(unsigned int pin) +static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) { unsigned long x, flags; @@ -115,13 +117,13 @@ int __init_or_module gpio_direction_input(unsigned int pin) return 0; } -EXPORT_SYMBOL(gpio_direction_input); /* * Configure the GPIO line as an output, with default state. */ -int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state) +static int ks8695_gpio_direction_output(struct gpio_chip *gc, + unsigned int pin, int state) { unsigned long x, flags; @@ -150,13 +152,13 @@ int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state) return 0; } -EXPORT_SYMBOL(gpio_direction_output); /* * Set the state of an output GPIO line. */ -void gpio_set_value(unsigned int pin, unsigned int state) +static void ks8695_gpio_set_value(struct gpio_chip *gc, + unsigned int pin, int state) { unsigned long x, flags; @@ -175,13 +177,12 @@ void gpio_set_value(unsigned int pin, unsigned int state) local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_set_value); /* * Read the state of a GPIO line. */ -int gpio_get_value(unsigned int pin) +static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) { unsigned long x; @@ -191,21 +192,18 @@ int gpio_get_value(unsigned int pin) x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); return (x & IOPD(pin)) != 0; } -EXPORT_SYMBOL(gpio_get_value); /* * Map GPIO line to IRQ number. */ -int gpio_to_irq(unsigned int pin) +static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) { if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ return -EINVAL; return gpio_irq[pin]; } -EXPORT_SYMBOL(gpio_to_irq); - /* * Map IRQ number to GPIO line. @@ -219,6 +217,26 @@ int irq_to_gpio(unsigned int irq) } EXPORT_SYMBOL(irq_to_gpio); +/* GPIOLIB interface */ + +static struct gpio_chip ks8695_gpio_chip = { + .label = "KS8695", + .direction_input = ks8695_gpio_direction_input, + .direction_output = ks8695_gpio_direction_output, + .get = ks8695_gpio_get_value, + .set = ks8695_gpio_set_value, + .to_irq = ks8695_gpio_to_irq, + .base = 0, + .ngpio = 16, + .can_sleep = 0, +}; + +/* Register the GPIOs */ +void ks8695_register_gpios(void) +{ + if (gpiochip_add(&ks8695_gpio_chip)) + printk(KERN_ERR "Unable to register core GPIOs\n"); +} /* .... Debug interface ..................................................... */ diff --git a/arch/arm/mach-ks8695/include/mach/dma.h b/arch/arm/mach-ks8695/include/mach/dma.h deleted file mode 100644 index 561206280089..000000000000 --- a/arch/arm/mach-ks8695/include/mach/dma.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * arch/arm/mach-ks8695/include/mach/dma.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/arch/arm/mach-ks8695/include/mach/gpio.h b/arch/arm/mach-ks8695/include/mach/gpio.h index d4af5c335f16..86312d476bc6 100644 --- a/arch/arm/mach-ks8695/include/mach/gpio.h +++ b/arch/arm/mach-ks8695/include/mach/gpio.h @@ -30,53 +30,28 @@ #define KS8695_GPIO_14 14 #define KS8695_GPIO_15 15 - /* * Configure GPIO pin as external interrupt source. */ -int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type); - -/* - * Configure the GPIO line as an input. - */ -int __init_or_module gpio_direction_input(unsigned int pin); - -/* - * Configure the GPIO line as an output, with default state. - */ -int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state); - -/* - * Set the state of an output GPIO line. - */ -void gpio_set_value(unsigned int pin, unsigned int state); - -/* - * Read the state of a GPIO line. - */ -int gpio_get_value(unsigned int pin); - -/* - * Map GPIO line to IRQ number. - */ -int gpio_to_irq(unsigned int pin); +extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type); /* * Map IRQ number to GPIO line. */ -int irq_to_gpio(unsigned int irq); - +extern int irq_to_gpio(unsigned int irq); #include <asm-generic/gpio.h> -static inline int gpio_request(unsigned int pin, const char *label) -{ - return 0; -} +/* If it turns out that we need to optimise GPIO access for the + * Micrel's GPIOs, then these can be changed to check their argument + * directly as static inlines. However for now it's probably not + * worthwhile. + */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_to_irq __gpio_to_irq -static inline void gpio_free(unsigned int pin) -{ - might_sleep(); -} +/* Register the GPIOs */ +extern void ks8695_register_gpios(void); #endif diff --git a/arch/arm/mach-ks8695/include/mach/io.h b/arch/arm/mach-ks8695/include/mach/io.h index f364f24ffe1e..a7a63ac3ba4e 100644 --- a/arch/arm/mach-ks8695/include/mach/io.h +++ b/arch/arm/mach-ks8695/include/mach/io.h @@ -13,7 +13,7 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index 8fbc4c76c38b..6d5887cf5742 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h @@ -37,11 +37,6 @@ extern struct bus_type platform_bus_type; (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) #define __arch_page_to_dma(dev, x) __arch_virt_to_dma(dev, page_address(x)) -#else - -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif #endif diff --git a/arch/arm/mach-l7200/include/mach/dma.h b/arch/arm/mach-l7200/include/mach/dma.h deleted file mode 100644 index c7e48bd4590c..000000000000 --- a/arch/arm/mach-l7200/include/mach/dma.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/arm/mach-l7200/include/mach/dma.h - * - * Copyright (C) 2000 Steve Hill (sjhill@cotw.com) - * - * Changelog: - * 08-29-2000 SJH Created - */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -/* DMA is not yet implemented! It should be the same as acorn, copy over.. */ - -/* - * This is the maximum DMA address that can be DMAd to. - * There should not be more than (0xd0000000 - 0xc0000000) - * bytes of RAM. - */ -#define MAX_DMA_ADDRESS 0xd0000000 - -#define DMA_S0 0 - -#endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-l7200/include/mach/io.h b/arch/arm/mach-l7200/include/mach/io.h index d432ba9e5dff..a770a89fb708 100644 --- a/arch/arm/mach-l7200/include/mach/io.h +++ b/arch/arm/mach-l7200/include/mach/io.h @@ -10,18 +10,12 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff /* * There are not real ISA nor PCI buses, so we fake it. */ -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} -#define __io(a) __io(a) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-l7200/include/mach/memory.h b/arch/arm/mach-l7200/include/mach/memory.h index f338cf3ffd93..9fb40ed2f03b 100644 --- a/arch/arm/mach-l7200/include/mach/memory.h +++ b/arch/arm/mach-l7200/include/mach/memory.h @@ -17,9 +17,6 @@ */ #define PHYS_OFFSET UL(0xf0000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - /* * Cache flushing area - ROM */ diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c index 4fb23ac6b5ac..6182f5410b4d 100644 --- a/arch/arm/mach-lh7a40x/clocks.c +++ b/arch/arm/mach-lh7a40x/clocks.c @@ -14,21 +14,14 @@ #include <linux/err.h> struct module; -struct icst525_params; struct clk { struct list_head node; unsigned long rate; struct module *owner; const char *name; -// void *data; -// const struct icst525_params *params; -// void (*setvco)(struct clk *, struct icst525_vco vco); }; -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); - /* ----- */ #define MAINDIV1(c) (((c) >> 7) & 0x0f) @@ -79,31 +72,15 @@ unsigned int pclkfreq_get (void) /* ----- */ -static LIST_HEAD(clocks); -static DECLARE_MUTEX(clocks_sem); - struct clk *clk_get (struct device *dev, const char *id) { - struct clk *p; - struct clk *clk = ERR_PTR(-ENOENT); - - down (&clocks_sem); - list_for_each_entry (p, &clocks, node) { - if (strcmp (id, p->name) == 0 - && try_module_get(p->owner)) { - clk = p; - break; - } - } - up (&clocks_sem); - - return clk; + return dev && strcmp(dev_name(dev), "cldc-lh7a40x") == 0 + ? NULL : ERR_PTR(-ENOENT); } EXPORT_SYMBOL(clk_get); void clk_put (struct clk *clk) { - module_put(clk->owner); } EXPORT_SYMBOL(clk_put); @@ -118,20 +95,9 @@ void clk_disable (struct clk *clk) } EXPORT_SYMBOL(clk_disable); -int clk_use (struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_use); - -void clk_unuse (struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_unuse); - unsigned long clk_get_rate (struct clk *clk) { - return clk->rate; + return 0; } EXPORT_SYMBOL(clk_get_rate); @@ -143,56 +109,6 @@ EXPORT_SYMBOL(clk_round_rate); int clk_set_rate (struct clk *clk, unsigned long rate) { - int ret = -EIO; - return ret; + return -EIO; } EXPORT_SYMBOL(clk_set_rate); - -#if 0 -/* - * These are fixed clocks. - */ -static struct clk kmi_clk = { - .name = "KMIREFCLK", - .rate = 24000000, -}; - -static struct clk uart_clk = { - .name = "UARTCLK", - .rate = 24000000, -}; - -static struct clk mmci_clk = { - .name = "MCLK", - .rate = 33000000, -}; -#endif - -static struct clk clcd_clk = { - .name = "CLCDCLK", - .rate = 0, -}; - -int clk_register (struct clk *clk) -{ - down (&clocks_sem); - list_add (&clk->node, &clocks); - up (&clocks_sem); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister (struct clk *clk) -{ - down (&clocks_sem); - list_del (&clk->node); - up (&clocks_sem); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init (void) -{ - clk_register(&clcd_clk); - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-lh7a40x/include/mach/io.h b/arch/arm/mach-lh7a40x/include/mach/io.h index 031d26f9163c..6ece45911cbc 100644 --- a/arch/arm/mach-lh7a40x/include/mach/io.h +++ b/arch/arm/mach-lh7a40x/include/mach/io.h @@ -11,12 +11,10 @@ #ifndef __ASM_ARCH_IO_H #define __ASM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff /* No ISA or PCI bus on this machine. */ -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif /* __ASM_ARCH_IO_H */ diff --git a/arch/arm/mach-lh7a40x/include/mach/memory.h b/arch/arm/mach-lh7a40x/include/mach/memory.h index 1da14ff66c93..189d20e543e7 100644 --- a/arch/arm/mach-lh7a40x/include/mach/memory.h +++ b/arch/arm/mach-lh7a40x/include/mach/memory.h @@ -19,16 +19,6 @@ */ #define PHYS_OFFSET UL(0xc0000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #ifdef CONFIG_DISCONTIGMEM /* diff --git a/arch/arm/mach-loki/include/mach/dma.h b/arch/arm/mach-loki/include/mach/dma.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/arm/mach-loki/include/mach/dma.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h index a39533ab489d..2ed7e6e732c2 100644 --- a/arch/arm/mach-loki/include/mach/memory.h +++ b/arch/arm/mach-loki/include/mach/memory.h @@ -7,8 +7,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - - #endif diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h index c6a2feb268b0..aab964591db4 100644 --- a/arch/arm/mach-msm/include/mach/io.h +++ b/arch/arm/mach-msm/include/mach/io.h @@ -23,11 +23,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype); -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} -#define __io(a) __io(a) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 63fd47f2e62e..f4698baec976 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -19,9 +19,5 @@ /* physical offset of RAM */ #define PHYS_OFFSET UL(0x10000000) -/* bus address and physical addresses are identical */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 238a2f8c2d52..b0e4e0d8f506 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -167,6 +167,7 @@ void __init mv78xx0_map_io(void) ****************************************************************************/ static struct orion_ehci_data mv78xx0_ehci_data = { .dram = &mv78xx0_mbus_dram_info, + .phy_version = EHCI_PHY_NA, }; static u64 ehci_dmamask = 0xffffffffUL; diff --git a/arch/arm/mach-mv78xx0/include/mach/dma.h b/arch/arm/mach-mv78xx0/include/mach/dma.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/arm/mach-mv78xx0/include/mach/dma.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-mv78xx0/include/mach/gpio.h b/arch/arm/mach-mv78xx0/include/mach/gpio.h new file mode 100644 index 000000000000..d9d1535ea100 --- /dev/null +++ b/arch/arm/mach-mv78xx0/include/mach/gpio.h @@ -0,0 +1,40 @@ +/* + * arch/asm-arm/mach-mv78xx0/include/mach/gpio.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include <mach/irqs.h> +#include <plat/gpio.h> +#include <asm-generic/gpio.h> /* cansleep wrappers */ + +extern int mv78xx0_core_index(void); + +#define GPIO_MAX 32 +#define GPIO_OUT(pin) (DEV_BUS_VIRT_BASE + 0x0100) +#define GPIO_IO_CONF(pin) (DEV_BUS_VIRT_BASE + 0x0104) +#define GPIO_BLINK_EN(pin) (DEV_BUS_VIRT_BASE + 0x0108) +#define GPIO_IN_POL(pin) (DEV_BUS_VIRT_BASE + 0x010c) +#define GPIO_DATA_IN(pin) (DEV_BUS_VIRT_BASE + 0x0110) +#define GPIO_EDGE_CAUSE(pin) (DEV_BUS_VIRT_BASE + 0x0114) +#define GPIO_MASK_OFF (mv78xx0_core_index() ? 0x18 : 0) +#define GPIO_EDGE_MASK(pin) (DEV_BUS_VIRT_BASE + 0x0118 + GPIO_MASK_OFF) +#define GPIO_LEVEL_MASK(pin) (DEV_BUS_VIRT_BASE + 0x011c + GPIO_MASK_OFF) + +static inline int gpio_to_irq(int pin) +{ + return pin + IRQ_MV78XX0_GPIO_START; +} + +static inline int irq_to_gpio(int irq) +{ + return irq - IRQ_MV78XX0_GPIO_START; +} + + +#endif diff --git a/arch/arm/mach-mv78xx0/include/mach/irqs.h b/arch/arm/mach-mv78xx0/include/mach/irqs.h index bebc330281ec..fa1d422196c2 100644 --- a/arch/arm/mach-mv78xx0/include/mach/irqs.h +++ b/arch/arm/mach-mv78xx0/include/mach/irqs.h @@ -11,8 +11,6 @@ #ifndef __ASM_ARCH_IRQS_H #define __ASM_ARCH_IRQS_H -#include "mv78xx0.h" /* need GPIO_MAX */ - /* * MV78xx0 Low Interrupt Controller */ @@ -88,7 +86,7 @@ * MV78XX0 General Purpose Pins */ #define IRQ_MV78XX0_GPIO_START 96 -#define NR_GPIO_IRQS GPIO_MAX +#define NR_GPIO_IRQS 32 #define NR_IRQS (IRQ_MV78XX0_GPIO_START + NR_GPIO_IRQS) diff --git a/arch/arm/mach-mv78xx0/include/mach/memory.h b/arch/arm/mach-mv78xx0/include/mach/memory.h index 9e47a140ff7a..e663042d307f 100644 --- a/arch/arm/mach-mv78xx0/include/mach/memory.h +++ b/arch/arm/mach-mv78xx0/include/mach/memory.h @@ -7,8 +7,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - - #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h index ee9c5593ee92..e930ea5330a2 100644 --- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h +++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h @@ -122,7 +122,4 @@ #define SATA_PHYS_BASE (MV78XX0_REGS_PHYS_BASE | 0xa0000) -#define GPIO_MAX 32 - - #endif diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c index 503e5d195ae5..e273418797b4 100644 --- a/arch/arm/mach-mv78xx0/irq.c +++ b/arch/arm/mach-mv78xx0/irq.c @@ -11,13 +11,42 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/irq.h> +#include <asm/gpio.h> #include <mach/mv78xx0.h> #include <plat/irq.h> #include "common.h" +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + BUG_ON(irq < IRQ_MV78XX0_GPIO_0_7 || irq > IRQ_MV78XX0_GPIO_24_31); + + orion_gpio_irq_handler((irq - IRQ_MV78XX0_GPIO_0_7) << 3); +} + void __init mv78xx0_init_irq(void) { + int i; + orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF)); + + /* + * Mask and clear GPIO IRQ interrupts. + */ + writel(0, GPIO_LEVEL_MASK(0)); + writel(0, GPIO_EDGE_MASK(0)); + writel(0, GPIO_EDGE_CAUSE(0)); + + for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) { + set_irq_chip(i, &orion_gpio_irq_level_chip); + set_irq_handler(i, handle_level_irq); + irq_desc[i].status |= IRQ_LEVEL; + set_irq_flags(i, IRQF_VALID); + } + set_irq_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler); + set_irq_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler); + set_irq_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler); + set_irq_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler); } diff --git a/arch/arm/mach-mx1/Kconfig b/arch/arm/mach-mx1/Kconfig new file mode 100644 index 000000000000..2b59fc74784f --- /dev/null +++ b/arch/arm/mach-mx1/Kconfig @@ -0,0 +1,14 @@ +if ARCH_MX1 + +comment "MX1 Platforms" + +config MACH_MXLADS + bool + +config ARCH_MX1ADS + bool "MX1ADS platform" + select MACH_MXLADS + help + Say Y here if you are using Motorola MX1ADS/MXLADS boards + +endif diff --git a/arch/arm/mach-mx1/Makefile b/arch/arm/mach-mx1/Makefile new file mode 100644 index 000000000000..b969719011fa --- /dev/null +++ b/arch/arm/mach-mx1/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y += generic.o clock.o devices.o + +# Specific board support +obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o diff --git a/arch/arm/mach-mx1/Makefile.boot b/arch/arm/mach-mx1/Makefile.boot new file mode 100644 index 000000000000..8ed1492288a2 --- /dev/null +++ b/arch/arm/mach-mx1/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x08008000 +params_phys-y := 0x08000100 +initrd_phys-y := 0x08800000 + diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c new file mode 100644 index 000000000000..4bcd1ece55f5 --- /dev/null +++ b/arch/arm/mach-mx1/clock.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/math64.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <mach/clock.h> +#include <mach/hardware.h> +#include "crm_regs.h" + +static int _clk_enable(struct clk *clk) +{ + unsigned int reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + unsigned int reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size, + struct clk *parent) +{ + int i; + + for (i = 0; i < size; i++) + if (parent == clk_arr[i]) + return i; + + return -EINVAL; +} + +static unsigned long +_clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit) +{ + int div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > limit) + div = limit; + + return parent_rate / div; +} + +static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->set_rate(clk->parent, rate); +} + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref) +{ + unsigned long long ll; + unsigned long quot; + + u32 mfi = (pll >> 10) & 0xf; + u32 mfn = pll & 0x3ff; + u32 mfd = (pll >> 16) & 0x3ff; + u32 pd = (pll >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + + ll = 2 * (unsigned long long)f_ref * + ((mfi << 16) + (mfn << 16) / (mfd + 1)); + quot = (pd + 1) * (1 << 16); + ll += quot / 2; + do_div(ll, quot); + return (unsigned long)ll; +} + +static unsigned long clk16m_get_rate(struct clk *clk) +{ + return 16000000; +} + +static struct clk clk16m = { + .name = "CLK16M", + .get_rate = clk16m_get_rate, + .enable = _clk_enable, + .enable_reg = CCM_CSCR, + .enable_shift = CCM_CSCR_OSC_EN_SHIFT, + .disable = _clk_disable, +}; + +/* in Hz */ +static unsigned long clk32_rate; + +static unsigned long clk32_get_rate(struct clk *clk) +{ + return clk32_rate; +} + +static struct clk clk32 = { + .name = "CLK32", + .get_rate = clk32_get_rate, +}; + +static unsigned long clk32_premult_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 512; +} + +static struct clk clk32_premult = { + .name = "CLK32_premultiplier", + .parent = &clk32, + .get_rate = clk32_premult_get_rate, +}; + +static const struct clk *prem_clk_clocks[] = { + &clk32_premult, + &clk16m, +}; + +static int prem_clk_set_parent(struct clk *clk, struct clk *parent) +{ + int i; + unsigned int reg = __raw_readl(CCM_CSCR); + + i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks), + parent); + + switch (i) { + case 0: + reg &= ~CCM_CSCR_SYSTEM_SEL; + break; + case 1: + reg |= CCM_CSCR_SYSTEM_SEL; + break; + default: + return i; + } + + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk prem_clk = { + .name = "prem_clk", + .set_parent = prem_clk_set_parent, +}; + +static unsigned long system_clk_get_rate(struct clk *clk) +{ + return mx1_decode_pll(__raw_readl(CCM_SPCTL0), + clk_get_rate(clk->parent)); +} + +static struct clk system_clk = { + .name = "system_clk", + .parent = &prem_clk, + .get_rate = system_clk_get_rate, +}; + +static unsigned long mcu_clk_get_rate(struct clk *clk) +{ + return mx1_decode_pll(__raw_readl(CCM_MPCTL0), + clk_get_rate(clk->parent)); +} + +static struct clk mcu_clk = { + .name = "mcu_clk", + .parent = &clk32_premult, + .get_rate = mcu_clk_get_rate, +}; + +static unsigned long fclk_get_rate(struct clk *clk) +{ + unsigned long fclk = clk_get_rate(clk->parent); + + if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC) + fclk /= 2; + + return fclk; +} + +static struct clk fclk = { + .name = "fclk", + .parent = &mcu_clk, + .get_rate = fclk_get_rate, +}; + +/* + * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA ) + */ +static unsigned long hclk_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) & + CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1); +} + +static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int hclk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_BCLK_MASK; + reg |= div << CCM_CSCR_BCLK_OFFSET; + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk hclk = { + .name = "hclk", + .parent = &system_clk, + .get_rate = hclk_get_rate, + .round_rate = hclk_round_rate, + .set_rate = hclk_set_rate, +}; + +static unsigned long clk48m_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) & + CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1); +} + +static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 8); +} + +static int clk48m_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_USB_MASK; + reg |= div << CCM_CSCR_USB_OFFSET; + __raw_writel(reg, CCM_CSCR); + + return 0; +} + +static struct clk clk48m = { + .name = "CLK48M", + .parent = &system_clk, + .get_rate = clk48m_get_rate, + .round_rate = clk48m_round_rate, + .set_rate = clk48m_set_rate, +}; + +/* + * get peripheral clock 1 ( UART[12], Timer[12], PWM ) + */ +static unsigned long perclk1_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1); +} + +static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int perclk1_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK1_MASK; + reg |= div << CCM_PCDR_PCLK1_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +/* + * get peripheral clock 2 ( LCD, SD, SPI[12] ) + */ +static unsigned long perclk2_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1); +} + +static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 16); +} + +static int perclk2_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 16 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK2_MASK; + reg |= div << CCM_PCDR_PCLK2_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +/* + * get peripheral clock 3 ( SSI ) + */ +static unsigned long perclk3_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) & + CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1); +} + +static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate) +{ + return _clk_simple_round_rate(clk, rate, 128); +} + +static int perclk3_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int div; + unsigned int reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 128 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_PCDR); + reg &= ~CCM_PCDR_PCLK3_MASK; + reg |= div << CCM_PCDR_PCLK3_OFFSET; + __raw_writel(reg, CCM_PCDR); + + return 0; +} + +static struct clk perclk[] = { + { + .name = "perclk", + .id = 0, + .parent = &system_clk, + .get_rate = perclk1_get_rate, + .round_rate = perclk1_round_rate, + .set_rate = perclk1_set_rate, + }, { + .name = "perclk", + .id = 1, + .parent = &system_clk, + .get_rate = perclk2_get_rate, + .round_rate = perclk2_round_rate, + .set_rate = perclk2_set_rate, + }, { + .name = "perclk", + .id = 2, + .parent = &system_clk, + .get_rate = perclk3_get_rate, + .round_rate = perclk3_round_rate, + .set_rate = perclk3_set_rate, + } +}; + +static const struct clk *clko_clocks[] = { + &perclk[0], + &hclk, + &clk48m, + &clk16m, + &prem_clk, + &fclk, +}; + +static int clko_set_parent(struct clk *clk, struct clk *parent) +{ + int i; + unsigned int reg; + + i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent); + if (i < 0) + return i; + + reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK; + reg |= i << CCM_CSCR_CLKO_OFFSET; + __raw_writel(reg, CCM_CSCR); + + if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) { + clk->set_rate = _clk_parent_set_rate; + clk->round_rate = _clk_parent_round_rate; + } else { + clk->set_rate = NULL; + clk->round_rate = NULL; + } + + return 0; +} + +static struct clk clko_clk = { + .name = "clko_clk", + .set_parent = clko_set_parent, +}; + +static struct clk dma_clk = { + .name = "dma_clk", + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk csi_clk = { + .name = "csi_clk", + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk mma_clk = { + .name = "mma_clk", + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk usbd_clk = { + .name = "usbd_clk", + .parent = &clk48m, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + .enable = _clk_enable, + .enable_reg = SCM_GCCR, + .enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpt_clk = { + .name = "gpt_clk", + .parent = &perclk[0], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk uart_clk = { + .name = "uart_clk", + .parent = &perclk[0], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk i2c_clk = { + .name = "i2c_clk", + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk spi_clk = { + .name = "spi_clk", + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk sdhc_clk = { + .name = "sdhc_clk", + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .parent = &perclk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk mshc_clk = { + .name = "mshc_clk", + .parent = &hclk, + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk ssi_clk = { + .name = "ssi_clk", + .parent = &perclk[2], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, +}; + +static struct clk rtc_clk = { + .name = "rtc_clk", + .parent = &clk32, +}; + +static struct clk *mxc_clks[] = { + &clk16m, + &clk32, + &clk32_premult, + &prem_clk, + &system_clk, + &mcu_clk, + &fclk, + &hclk, + &clk48m, + &perclk[0], + &perclk[1], + &perclk[2], + &clko_clk, + &dma_clk, + &csi_clk, + &mma_clk, + &usbd_clk, + &gpt_clk, + &uart_clk, + &i2c_clk, + &spi_clk, + &sdhc_clk, + &lcdc_clk, + &mshc_clk, + &ssi_clk, + &rtc_clk, +}; + +int __init mxc_clocks_init(unsigned long fref) +{ + struct clk **clkp; + unsigned int reg; + + /* disable clocks we are able to */ + __raw_writel(0, SCM_GCCR); + + clk32_rate = fref; + reg = __raw_readl(CCM_CSCR); + + /* detect clock reference for system PLL */ + if (reg & CCM_CSCR_SYSTEM_SEL) { + prem_clk.parent = &clk16m; + } else { + /* ensure that oscillator is disabled */ + reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT); + __raw_writel(reg, CCM_CSCR); + prem_clk.parent = &clk32_premult; + } + + /* detect reference for CLKO */ + reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET; + clko_clk.parent = (struct clk *)clko_clocks[reg]; + + for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) + clk_register(*clkp); + + clk_enable(&hclk); + clk_enable(&fclk); + + return 0; +} diff --git a/arch/arm/mach-mx1/crm_regs.h b/arch/arm/mach-mx1/crm_regs.h new file mode 100644 index 000000000000..22e866ff0c09 --- /dev/null +++ b/arch/arm/mach-mx1/crm_regs.h @@ -0,0 +1,55 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> + * + * This file may be distributed under the terms of the GNU General + * Public License, version 2. + */ + +#ifndef __ARCH_ARM_MACH_MX1_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX1_CRM_REGS_H__ + +#define CCM_BASE IO_ADDRESS(CCM_BASE_ADDR) +#define SCM_BASE IO_ADDRESS(SCM_BASE_ADDR) + +/* CCM register addresses */ +#define CCM_CSCR (CCM_BASE + 0x0) +#define CCM_MPCTL0 (CCM_BASE + 0x4) +#define CCM_MPCTL1 (CCM_BASE + 0x8) +#define CCM_SPCTL0 (CCM_BASE + 0xC) +#define CCM_SPCTL1 (CCM_BASE + 0x10) +#define CCM_PCDR (CCM_BASE + 0x20) + +#define CCM_CSCR_CLKO_OFFSET 29 +#define CCM_CSCR_CLKO_MASK (0x7 << 29) +#define CCM_CSCR_USB_OFFSET 26 +#define CCM_CSCR_USB_MASK (0x7 << 26) +#define CCM_CSCR_SPLL_RESTART (1 << 22) +#define CCM_CSCR_MPLL_RESTART (1 << 21) +#define CCM_CSCR_OSC_EN_SHIFT 17 +#define CCM_CSCR_SYSTEM_SEL (1 << 16) +#define CCM_CSCR_BCLK_OFFSET 10 +#define CCM_CSCR_BCLK_MASK (0xF << 10) +#define CCM_CSCR_PRESC (1 << 15) +#define CCM_CSCR_SPEN (1 << 1) +#define CCM_CSCR_MPEN (1 << 0) + +#define CCM_PCDR_PCLK3_OFFSET 16 +#define CCM_PCDR_PCLK3_MASK (0x7F << 16) +#define CCM_PCDR_PCLK2_OFFSET 4 +#define CCM_PCDR_PCLK2_MASK (0xF << 4) +#define CCM_PCDR_PCLK1_OFFSET 0 +#define CCM_PCDR_PCLK1_MASK 0xF + +/* SCM register addresses */ +#define SCM_SIDR (SCM_BASE + 0x0) +#define SCM_FMCR (SCM_BASE + 0x4) +#define SCM_GPCR (SCM_BASE + 0x8) +#define SCM_GCCR (SCM_BASE + 0xC) + +#define SCM_GCCR_DMA_CLK_EN_OFFSET 3 +#define SCM_GCCR_CSI_CLK_EN_OFFSET 2 +#define SCM_GCCR_MMA_CLK_EN_OFFSET 1 +#define SCM_GCCR_USBD_CLK_EN_OFFSET 0 + +#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */ diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c new file mode 100644 index 000000000000..686d8d2dbb24 --- /dev/null +++ b/arch/arm/mach-mx1/devices.c @@ -0,0 +1,260 @@ +/* + * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Sascha Hauer, kernel@pengutronix.de + * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> + * Copyright (c) 2008 Darius Augulis <darius.augulis@teltonika.lt> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <mach/hardware.h> + +static struct resource imx_csi_resources[] = { + [0] = { + .start = 0x00224000, + .end = 0x00224010, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = CSI_INT, + .end = CSI_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 imx_csi_dmamask = 0xffffffffUL; + +struct platform_device imx_csi_device = { + .name = "imx-csi", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &imx_csi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = imx_csi_resources, + .num_resources = ARRAY_SIZE(imx_csi_resources), +}; + +static struct resource imx_i2c_resources[] = { + [0] = { + .start = 0x00217000, + .end = 0x00217010, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = I2C_INT, + .end = I2C_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_i2c_device = { + .name = "imx-i2c", + .id = 0, + .resource = imx_i2c_resources, + .num_resources = ARRAY_SIZE(imx_i2c_resources), +}; + +static struct resource imx_uart1_resources[] = { + [0] = { + .start = UART1_BASE_ADDR, + .end = UART1_BASE_ADDR + 0xD0, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = UART1_MINT_RX, + .end = UART1_MINT_RX, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = UART1_MINT_TX, + .end = UART1_MINT_TX, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = UART1_MINT_RTS, + .end = UART1_MINT_RTS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_uart1_device = { + .name = "imx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(imx_uart1_resources), + .resource = imx_uart1_resources, +}; + +static struct resource imx_uart2_resources[] = { + [0] = { + .start = UART2_BASE_ADDR, + .end = UART2_BASE_ADDR + 0xD0, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = UART2_MINT_RX, + .end = UART2_MINT_RX, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = UART2_MINT_TX, + .end = UART2_MINT_TX, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = UART2_MINT_RTS, + .end = UART2_MINT_RTS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_uart2_device = { + .name = "imx-uart", + .id = 1, + .num_resources = ARRAY_SIZE(imx_uart2_resources), + .resource = imx_uart2_resources, +}; + +static struct resource imx_rtc_resources[] = { + [0] = { + .start = 0x00204000, + .end = 0x00204024, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = RTC_INT, + .end = RTC_INT, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = RTC_SAMINT, + .end = RTC_SAMINT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_rtc_device = { + .name = "rtc-imx", + .id = 0, + .resource = imx_rtc_resources, + .num_resources = ARRAY_SIZE(imx_rtc_resources), +}; + +static struct resource imx_wdt_resources[] = { + [0] = { + .start = 0x00201000, + .end = 0x00201008, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = WDT_INT, + .end = WDT_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_wdt_device = { + .name = "imx-wdt", + .id = 0, + .resource = imx_wdt_resources, + .num_resources = ARRAY_SIZE(imx_wdt_resources), +}; + +static struct resource imx_usb_resources[] = { + [0] = { + .start = 0x00212000, + .end = 0x00212148, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = USBD_INT0, + .end = USBD_INT0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = USBD_INT1, + .end = USBD_INT1, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = USBD_INT2, + .end = USBD_INT2, + .flags = IORESOURCE_IRQ, + }, + [4] = { + .start = USBD_INT3, + .end = USBD_INT3, + .flags = IORESOURCE_IRQ, + }, + [5] = { + .start = USBD_INT4, + .end = USBD_INT4, + .flags = IORESOURCE_IRQ, + }, + [6] = { + .start = USBD_INT5, + .end = USBD_INT5, + .flags = IORESOURCE_IRQ, + }, + [7] = { + .start = USBD_INT6, + .end = USBD_INT6, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_usb_device = { + .name = "imx_udc", + .id = 0, + .num_resources = ARRAY_SIZE(imx_usb_resources), + .resource = imx_usb_resources, +}; + +/* GPIO port description */ +static struct mxc_gpio_port imx_gpio_ports[] = { + [0] = { + .chip.label = "gpio-0", + .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR), + .irq = GPIO_INT_PORTA, + .virtual_irq_start = MXC_GPIO_IRQ_START + }, + [1] = { + .chip.label = "gpio-1", + .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x100), + .irq = GPIO_INT_PORTB, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 + }, + [2] = { + .chip.label = "gpio-2", + .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x200), + .irq = GPIO_INT_PORTC, + .virtual_irq_start = MXC_GPIO_IRQ_START + 64 + }, + [3] = { + .chip.label = "gpio-3", + .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x300), + .irq = GPIO_INT_PORTD, + .virtual_irq_start = MXC_GPIO_IRQ_START + 96 + } +}; + +int __init mxc_register_gpios(void) +{ + return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports)); +} diff --git a/arch/arm/mach-mx1/devices.h b/arch/arm/mach-mx1/devices.h new file mode 100644 index 000000000000..0da5d7cce3a2 --- /dev/null +++ b/arch/arm/mach-mx1/devices.h @@ -0,0 +1,7 @@ +extern struct platform_device imx_csi_device; +extern struct platform_device imx_i2c_device; +extern struct platform_device imx_uart1_device; +extern struct platform_device imx_uart2_device; +extern struct platform_device imx_rtc_device; +extern struct platform_device imx_wdt_device; +extern struct platform_device imx_usb_device; diff --git a/arch/arm/mach-integrator/include/mach/dma.h b/arch/arm/mach-mx1/generic.c index fbebe85a2db7..0dec6f300ffc 100644 --- a/arch/arm/mach-integrator/include/mach/dma.h +++ b/arch/arm/mach-mx1/generic.c @@ -1,7 +1,9 @@ /* - * arch/arm/mach-integrator/include/mach/dma.h + * author: Sascha Hauer + * Created: april 20th, 2004 + * Copyright: Synertronixx GmbH * - * Copyright (C) 1997,1998 Russell King + * Common code for i.MX machines * * 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 @@ -16,4 +18,26 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <asm/mach/map.h> + +#include <mach/hardware.h> + +static struct map_desc imx_io_desc[] __initdata = { + { + .virtual = IMX_IO_BASE, + .pfn = __phys_to_pfn(IMX_IO_PHYS), + .length = IMX_IO_SIZE, + .type = MT_DEVICE + } +}; + +void __init mxc_map_io(void) +{ + iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc)); +} diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c new file mode 100644 index 000000000000..2e4b185fe4a9 --- /dev/null +++ b/arch/arm/mach-mx1/mx1ads.c @@ -0,0 +1,148 @@ +/* + * arch/arm/mach-imx/mx1ads.c + * + * Initially based on: + * linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c + * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * 2004 (c) MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> + +#include <mach/hardware.h> +#include <mach/common.h> +#include <mach/imx-uart.h> +#include <mach/iomux-mx1-mx2.h> +#include "devices.h" + +/* + * UARTs platform data + */ +static int mxc_uart1_pins[] = { + PC9_PF_UART1_CTS, + PC10_PF_UART1_RTS, + PC11_PF_UART1_TXD, + PC12_PF_UART1_RXD, +}; + +static int uart1_mxc_init(struct platform_device *pdev) +{ + return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins), "UART1"); +} + +static int uart1_mxc_exit(struct platform_device *pdev) +{ + mxc_gpio_release_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins)); + return 0; +} + +static int mxc_uart2_pins[] = { + PB28_PF_UART2_CTS, + PB29_PF_UART2_RTS, + PB30_PF_UART2_TXD, + PB31_PF_UART2_RXD, +}; + +static int uart2_mxc_init(struct platform_device *pdev) +{ + return mxc_gpio_setup_multiple_pins(mxc_uart2_pins, + ARRAY_SIZE(mxc_uart2_pins), "UART2"); +} + +static int uart2_mxc_exit(struct platform_device *pdev) +{ + mxc_gpio_release_multiple_pins(mxc_uart2_pins, + ARRAY_SIZE(mxc_uart2_pins)); + return 0; +} + +static struct imxuart_platform_data uart_pdata[] = { + { + .init = uart1_mxc_init, + .exit = uart1_mxc_exit, + .flags = IMXUART_HAVE_RTSCTS, + }, { + .init = uart2_mxc_init, + .exit = uart2_mxc_exit, + .flags = IMXUART_HAVE_RTSCTS, + }, +}; + +/* + * Physmap flash + */ + +static struct physmap_flash_data mx1ads_flash_data = { + .width = 4, /* bankwidth in bytes */ +}; + +static struct resource flash_resource = { + .start = IMX_CS0_PHYS, + .end = IMX_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device = { + .name = "physmap-flash", + .id = 0, + .resource = &flash_resource, + .num_resources = 1, +}; + +/* + * Board init + */ +static void __init mx1ads_init(void) +{ + /* UART */ + mxc_register_device(&imx_uart1_device, &uart_pdata[0]); + mxc_register_device(&imx_uart2_device, &uart_pdata[1]); + + /* Physmap flash */ + mxc_register_device(&flash_device, &mx1ads_flash_data); +} + +static void __init mx1ads_timer_init(void) +{ + mxc_clocks_init(32000); + mxc_timer_init("gpt_clk"); +} + +struct sys_timer mx1ads_timer = { + .init = mx1ads_timer_init, +}; + +MACHINE_START(MX1ADS, "Freescale MX1ADS") + /* Maintainer: Sascha Hauer, Pengutronix */ + .phys_io = IMX_IO_PHYS, + .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mxc_map_io, + .init_irq = mxc_init_irq, + .timer = &mx1ads_timer, + .init_machine = mx1ads_init, +MACHINE_END + +MACHINE_START(MXLADS, "Freescale MXLADS") + .phys_io = IMX_IO_PHYS, + .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mxc_map_io, + .init_irq = mxc_init_irq, + .timer = &mx1ads_timer, + .init_machine = mx1ads_init, +MACHINE_END diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index bd0559d5933e..af121f5ab710 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -190,38 +190,72 @@ struct platform_device mxc_wdt = { .resource = mxc_wdt_resources, }; +static struct resource mxc_w1_master_resources[] = { + { + .start = OWIRE_BASE_ADDR, + .end = OWIRE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mxc_w1_master_device = { + .name = "mxc_w1", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_w1_master_resources), + .resource = mxc_w1_master_resources, +}; + +static struct resource mxc_nand_resources[] = { + { + .start = NFC_BASE_ADDR, + .end = NFC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC_INT_NANDFC, + .end = MXC_INT_NANDFC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_nand_device = { + .name = "mxc_nand", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_nand_resources), + .resource = mxc_nand_resources, +}; + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { .chip.label = "gpio-0", .irq = MXC_INT_GPIO, .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 0), - .virtual_irq_start = MXC_MAX_INT_LINES, + .virtual_irq_start = MXC_GPIO_IRQ_START, }, [1] = { .chip.label = "gpio-1", .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 1), - .virtual_irq_start = MXC_MAX_INT_LINES + 32, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, }, [2] = { .chip.label = "gpio-2", .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 2), - .virtual_irq_start = MXC_MAX_INT_LINES + 64, + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, }, [3] = { .chip.label = "gpio-3", .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 3), - .virtual_irq_start = MXC_MAX_INT_LINES + 96, + .virtual_irq_start = MXC_GPIO_IRQ_START + 96, }, [4] = { .chip.label = "gpio-4", .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 4), - .virtual_irq_start = MXC_MAX_INT_LINES + 128, + .virtual_irq_start = MXC_GPIO_IRQ_START + 128, }, [5] = { .chip.label = "gpio-5", .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 5), - .virtual_irq_start = MXC_MAX_INT_LINES + 160, + .virtual_irq_start = MXC_GPIO_IRQ_START + 160, } }; diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index c77a4b8f73b4..1e8cb577a642 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -12,4 +12,5 @@ extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_uart_device3; extern struct platform_device mxc_uart_device4; extern struct platform_device mxc_uart_device5; - +extern struct platform_device mxc_w1_master_device; +extern struct platform_device mxc_nand_device; diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 56e22d3ca075..2b5c67f54571 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -68,15 +68,14 @@ static int mxc_uart0_pins[] = { static int uart_mxc_port0_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart0_pins, - ARRAY_SIZE(mxc_uart0_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART0"); + ARRAY_SIZE(mxc_uart0_pins), "UART0"); } static int uart_mxc_port0_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart0_pins, - ARRAY_SIZE(mxc_uart0_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART0"); + mxc_gpio_release_multiple_pins(mxc_uart0_pins, + ARRAY_SIZE(mxc_uart0_pins)); + return 0; } static int mxc_uart1_pins[] = { @@ -89,15 +88,14 @@ static int mxc_uart1_pins[] = { static int uart_mxc_port1_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, - ARRAY_SIZE(mxc_uart1_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART1"); + ARRAY_SIZE(mxc_uart1_pins), "UART1"); } static int uart_mxc_port1_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, - ARRAY_SIZE(mxc_uart1_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART1"); + mxc_gpio_release_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins)); + return 0; } static int mxc_uart2_pins[] = { @@ -110,15 +108,14 @@ static int mxc_uart2_pins[] = { static int uart_mxc_port2_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart2_pins, - ARRAY_SIZE(mxc_uart2_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART2"); + ARRAY_SIZE(mxc_uart2_pins), "UART2"); } static int uart_mxc_port2_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart2_pins, - ARRAY_SIZE(mxc_uart2_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART2"); + mxc_gpio_release_multiple_pins(mxc_uart2_pins, + ARRAY_SIZE(mxc_uart2_pins)); + return 0; } static int mxc_uart3_pins[] = { @@ -131,15 +128,13 @@ static int mxc_uart3_pins[] = { static int uart_mxc_port3_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart3_pins, - ARRAY_SIZE(mxc_uart3_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART3"); + ARRAY_SIZE(mxc_uart3_pins), "UART3"); } static int uart_mxc_port3_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart3_pins, - ARRAY_SIZE(mxc_uart3_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART3"); + mxc_gpio_release_multiple_pins(mxc_uart3_pins, + ARRAY_SIZE(mxc_uart3_pins)); } static int mxc_uart4_pins[] = { @@ -152,15 +147,14 @@ static int mxc_uart4_pins[] = { static int uart_mxc_port4_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart4_pins, - ARRAY_SIZE(mxc_uart4_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART4"); + ARRAY_SIZE(mxc_uart4_pins), "UART4"); } static int uart_mxc_port4_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart4_pins, - ARRAY_SIZE(mxc_uart4_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART4"); + mxc_gpio_release_multiple_pins(mxc_uart4_pins, + ARRAY_SIZE(mxc_uart4_pins)); + return 0; } static int mxc_uart5_pins[] = { @@ -173,15 +167,14 @@ static int mxc_uart5_pins[] = { static int uart_mxc_port5_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart5_pins, - ARRAY_SIZE(mxc_uart5_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART5"); + ARRAY_SIZE(mxc_uart5_pins), "UART5"); } static int uart_mxc_port5_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart5_pins, - ARRAY_SIZE(mxc_uart5_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART5"); + mxc_gpio_release_multiple_pins(mxc_uart5_pins, + ARRAY_SIZE(mxc_uart5_pins)); + return 0; } static struct platform_device *platform_devices[] __initdata = { @@ -212,15 +205,13 @@ static int mxc_fec_pins[] = { static void gpio_fec_active(void) { mxc_gpio_setup_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "FEC"); + ARRAY_SIZE(mxc_fec_pins), "FEC"); } static void gpio_fec_inactive(void) { - mxc_gpio_setup_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "FEC"); + mxc_gpio_release_multiple_pins(mxc_fec_pins, + ARRAY_SIZE(mxc_fec_pins)); } static struct imxuart_platform_data uart_pdata[] = { diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 7f55746e2591..dfd4156da7d5 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/mtd/physmap.h> +#include <linux/mtd/plat-ram.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/common.h> @@ -27,10 +28,36 @@ #include <asm/mach/time.h> #include <mach/imx-uart.h> #include <mach/board-pcm038.h> +#include <mach/mxc_nand.h> #include "devices.h" /* + * Phytec's PCM038 comes with 2MiB battery buffered SRAM, + * 16 bit width + */ + +static struct platdata_mtd_ram pcm038_sram_data = { + .bankwidth = 2, +}; + +static struct resource pcm038_sram_resource = { + .start = CS1_BASE_ADDR, + .end = CS1_BASE_ADDR + 512 * 1024 - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device pcm038_sram_mtd_device = { + .name = "mtd-ram", + .id = 0, + .dev = { + .platform_data = &pcm038_sram_data, + }, + .num_resources = 1, + .resource = &pcm038_sram_resource, +}; + +/* * Phytec's phyCORE-i.MX27 comes with 32MiB flash, * 16 bit width */ @@ -64,15 +91,14 @@ static int mxc_uart0_pins[] = { static int uart_mxc_port0_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart0_pins, - ARRAY_SIZE(mxc_uart0_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART0"); + ARRAY_SIZE(mxc_uart0_pins), "UART0"); } static int uart_mxc_port0_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart0_pins, - ARRAY_SIZE(mxc_uart0_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART0"); + mxc_gpio_release_multiple_pins(mxc_uart0_pins, + ARRAY_SIZE(mxc_uart0_pins)); + return 0; } static int mxc_uart1_pins[] = { @@ -85,15 +111,14 @@ static int mxc_uart1_pins[] = { static int uart_mxc_port1_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, - ARRAY_SIZE(mxc_uart1_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART1"); + ARRAY_SIZE(mxc_uart1_pins), "UART1"); } static int uart_mxc_port1_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, - ARRAY_SIZE(mxc_uart1_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART1"); + mxc_gpio_release_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins)); + return 0; } static int mxc_uart2_pins[] = { PE10_PF_UART3_CTS, @@ -104,15 +129,14 @@ static int mxc_uart2_pins[] = { PE10_PF_UART3_CTS, static int uart_mxc_port2_init(struct platform_device *pdev) { return mxc_gpio_setup_multiple_pins(mxc_uart2_pins, - ARRAY_SIZE(mxc_uart2_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "UART2"); + ARRAY_SIZE(mxc_uart2_pins), "UART2"); } static int uart_mxc_port2_exit(struct platform_device *pdev) { - return mxc_gpio_setup_multiple_pins(mxc_uart2_pins, - ARRAY_SIZE(mxc_uart2_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "UART2"); + mxc_gpio_release_multiple_pins(mxc_uart2_pins, + ARRAY_SIZE(mxc_uart2_pins)); + return 0; } static struct imxuart_platform_data uart_pdata[] = { @@ -155,29 +179,47 @@ static int mxc_fec_pins[] = { static void gpio_fec_active(void) { mxc_gpio_setup_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins), - MXC_GPIO_ALLOC_MODE_NORMAL, "FEC"); + ARRAY_SIZE(mxc_fec_pins), "FEC"); } static void gpio_fec_inactive(void) { - mxc_gpio_setup_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins), - MXC_GPIO_ALLOC_MODE_RELEASE, "FEC"); + mxc_gpio_release_multiple_pins(mxc_fec_pins, + ARRAY_SIZE(mxc_fec_pins)); } +static struct mxc_nand_platform_data pcm038_nand_board_info = { + .width = 1, + .hw_ecc = 1, +}; + static struct platform_device *platform_devices[] __initdata = { &pcm038_nor_mtd_device, + &mxc_w1_master_device, + &pcm038_sram_mtd_device, }; +/* On pcm038 there's a sram attached to CS1, we enable the chipselect here and + * setup other stuffs to access the sram. */ +static void __init pcm038_init_sram(void) +{ + __raw_writel(0x0000d843, CSCR_U(1)); + __raw_writel(0x22252521, CSCR_L(1)); + __raw_writel(0x22220a00, CSCR_A(1)); +} + static void __init pcm038_init(void) { gpio_fec_active(); + pcm038_init_sram(); mxc_register_device(&mxc_uart_device0, &uart_pdata[0]); mxc_register_device(&mxc_uart_device1, &uart_pdata[1]); mxc_register_device(&mxc_uart_device2, &uart_pdata[2]); + mxc_gpio_mode(PE16_AF_RTCK); /* OWIRE */ + mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info); + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); #ifdef CONFIG_MACH_PCM970_BASEBOARD diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index db9431dee1b4..e79659e8176e 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -21,5 +21,19 @@ config MACH_MX31LITE Include support for MX31 LITEKIT platform. This includes specific configurations for the board and its peripherals. +config MACH_MX31_3DS + bool "Support MX31PDK (3DS)" + default n + help + Include support for MX31PDK (3DS) platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX31MOBOARD + bool "Support mx31moboard platforms (EPFL Mobots group)" + default n + help + Include support for mx31moboard platform. This includes specific + configurations for the board and its peripherals. + endmenu diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index 8b21abb71fb0..5a151540fe83 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -8,3 +8,5 @@ obj-y := mm.o clock.o devices.o iomux.o obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o obj-$(CONFIG_MACH_PCM037) += pcm037.o +obj-$(CONFIG_MACH_MX31_3DS) += mx31pdk.o +obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 9f14a871ee7c..b1746aae1f89 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -24,6 +24,7 @@ #include <linux/err.h> #include <linux/io.h> #include <mach/clock.h> +#include <mach/hardware.h> #include <asm/div64.h> #include "crm_regs.h" diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index a6bdcc07f3c9..1d46cb4adf96 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -125,19 +125,19 @@ static struct mxc_gpio_port imx_gpio_ports[] = { .chip.label = "gpio-0", .base = IO_ADDRESS(GPIO1_BASE_ADDR), .irq = MXC_INT_GPIO1, - .virtual_irq_start = MXC_GPIO_INT_BASE + .virtual_irq_start = MXC_GPIO_IRQ_START, }, [1] = { .chip.label = "gpio-1", .base = IO_ADDRESS(GPIO2_BASE_ADDR), .irq = MXC_INT_GPIO2, - .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, }, [2] = { .chip.label = "gpio-2", .base = IO_ADDRESS(GPIO3_BASE_ADDR), .irq = MXC_INT_GPIO3, - .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 2 + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, } }; @@ -145,3 +145,37 @@ int __init mxc_register_gpios(void) { return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports)); } + +static struct resource mxc_w1_master_resources[] = { + { + .start = OWIRE_BASE_ADDR, + .end = OWIRE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mxc_w1_master_device = { + .name = "mxc_w1", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_w1_master_resources), + .resource = mxc_w1_master_resources, +}; + +static struct resource mxc_nand_resources[] = { + { + .start = NFC_BASE_ADDR, + .end = NFC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC_INT_NANDFC, + .end = MXC_INT_NANDFC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_nand_device = { + .name = "mxc_nand", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_nand_resources), + .resource = mxc_nand_resources, +}; diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 4dc03f9e6001..9949ef4e0694 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -4,3 +4,5 @@ extern struct platform_device mxc_uart_device1; extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_uart_device3; extern struct platform_device mxc_uart_device4; +extern struct platform_device mxc_w1_master_device; +extern struct platform_device mxc_nand_device; diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c index 6e664be8cc13..7a5088b519a8 100644 --- a/arch/arm/mach-mx3/iomux.c +++ b/arch/arm/mach-mx3/iomux.c @@ -74,17 +74,18 @@ void mxc_iomux_set_pad(enum iomux_pins pin, u32 config) u32 field, l; void __iomem *reg; - reg = IOMUXSW_PAD_CTL + (pin + 2) / 3; + pin &= IOMUX_PADNUM_MASK; + reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4; field = (pin + 2) % 3; - pr_debug("%s: reg offset = 0x%x field = %d\n", + pr_debug("%s: reg offset = 0x%x, field = %d\n", __func__, (pin + 2) / 3, field); spin_lock(&gpio_mux_lock); l = __raw_readl(reg); - l &= ~(0x1ff << (field * 9)); - l |= config << (field * 9); + l &= ~(0x1ff << (field * 10)); + l |= config << (field * 10); __raw_writel(l, reg); spin_unlock(&gpio_mux_lock); diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c new file mode 100644 index 000000000000..c29098af7394 --- /dev/null +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 Valentin Longchamp, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> + +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/partitions.h> +#include <linux/memory.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/mach/map.h> +#include <mach/common.h> +#include <mach/imx-uart.h> +#include <mach/iomux-mx3.h> + +#include "devices.h" + +static struct physmap_flash_data mx31moboard_flash_data = { + .width = 2, +}; + +static struct resource mx31moboard_flash_resource = { + .start = 0xa0000000, + .end = 0xa1ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device mx31moboard_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &mx31moboard_flash_data, + }, + .resource = &mx31moboard_flash_resource, + .num_resources = 1, +}; + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct platform_device *devices[] __initdata = { + &mx31moboard_flash, +}; + +/* + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); + + mxc_iomux_mode(MX31_PIN_CTS1__CTS1); + mxc_iomux_mode(MX31_PIN_RTS1__RTS1); + mxc_iomux_mode(MX31_PIN_TXD1__TXD1); + mxc_iomux_mode(MX31_PIN_RXD1__RXD1); + + mxc_register_device(&mxc_uart_device0, &uart_pdata); + + mxc_iomux_mode(MX31_PIN_CTS2__CTS2); + mxc_iomux_mode(MX31_PIN_RTS2__RTS2); + mxc_iomux_mode(MX31_PIN_TXD2__TXD2); + mxc_iomux_mode(MX31_PIN_RXD2__RXD2); + + mxc_register_device(&mxc_uart_device1, &uart_pdata); + + mxc_iomux_mode(MX31_PIN_PC_RST__CTS5); + mxc_iomux_mode(MX31_PIN_PC_VS2__RTS5); + mxc_iomux_mode(MX31_PIN_PC_BVD2__TXD5); + mxc_iomux_mode(MX31_PIN_PC_BVD1__RXD5); + + mxc_register_device(&mxc_uart_device4, &uart_pdata); +} + +/* + * This structure defines static mappings for the mx31moboard. + */ +static struct map_desc mx31moboard_io_desc[] __initdata = { + { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED + }, +}; + +/* + * Set up static virtual mappings. + */ +void __init mx31moboard_map_io(void) +{ + mxc_map_io(); + iotable_init(mx31moboard_io_desc, ARRAY_SIZE(mx31moboard_io_desc)); +} + +static void __init mx31moboard_timer_init(void) +{ + mxc_clocks_init(26000000); + mxc_timer_init("ipg_clk.0"); +} + +struct sys_timer mx31moboard_timer = { + .init = mx31moboard_timer_init, +}; + +MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") + /* Maintainer: Valentin Longchamp, EPFL Mobots group */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mx31moboard_map_io, + .init_irq = mxc_init_irq, + .init_machine = mxc_board_init, + .timer = &mx31moboard_timer, +MACHINE_END + diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c new file mode 100644 index 000000000000..d464d068a4a6 --- /dev/null +++ b/arch/arm/mach-mx3/mx31pdk.c @@ -0,0 +1,115 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/irq.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/memory.h> +#include <asm/mach/map.h> +#include <mach/common.h> +#include <mach/board-mx31pdk.h> +#include <mach/imx-uart.h> +#include <mach/iomux-mx3.h> +#include "devices.h" + +/*! + * @file mx31pdk.c + * + * @brief This file contains the board-specific initialization routines. + * + * @ingroup System + */ + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static inline void mxc_init_imx_uart(void) +{ + mxc_iomux_mode(MX31_PIN_CTS1__CTS1); + mxc_iomux_mode(MX31_PIN_RTS1__RTS1); + mxc_iomux_mode(MX31_PIN_TXD1__TXD1); + mxc_iomux_mode(MX31_PIN_RXD1__RXD1); + + mxc_register_device(&mxc_uart_device0, &uart_pdata); +} + +/*! + * This structure defines static mappings for the i.MX31PDK board. + */ +static struct map_desc mx31pdk_io_desc[] __initdata = { + { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED + }, +}; + +/*! + * Set up static virtual mappings. + */ +static void __init mx31pdk_map_io(void) +{ + mxc_map_io(); + iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc)); +} + +/*! + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + mxc_init_imx_uart(); +} + +static void __init mx31pdk_timer_init(void) +{ + mxc_clocks_init(26000000); + mxc_timer_init("ipg_clk.0"); +} + +static struct sys_timer mx31pdk_timer = { + .init = mx31pdk_timer_init, +}; + +/* + * The following uses standard kernel macros defined in arch.h in order to + * initialize __mach_desc_MX31PDK data structure. + */ +MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") + /* Maintainer: Freescale Semiconductor, Inc. */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mx31pdk_map_io, + .init_irq = mxc_init_irq, + .init_machine = mxc_board_init, + .timer = &mx31pdk_timer, +MACHINE_END diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 843f68c8ead1..8cea82587222 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -21,7 +21,11 @@ #include <linux/platform_device.h> #include <linux/mtd/physmap.h> +#include <linux/mtd/plat-ram.h> #include <linux/memory.h> +#include <linux/gpio.h> +#include <linux/smc911x.h> +#include <linux/interrupt.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -32,6 +36,7 @@ #include <mach/imx-uart.h> #include <mach/iomux-mx3.h> #include <mach/board-pcm037.h> +#include <mach/mxc_nand.h> #include "devices.h" @@ -59,8 +64,63 @@ static struct imxuart_platform_data uart_pdata = { .flags = IMXUART_HAVE_RTSCTS, }; +static struct resource smc911x_resources[] = { + [0] = { + .start = CS1_BASE_ADDR + 0x300, + .end = CS1_BASE_ADDR + 0x300 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), + .end = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smc911x_platdata smc911x_info = { + .flags = SMC911X_USE_32BIT, + .irq_flags = IRQF_SHARED | IRQF_TRIGGER_LOW, +}; + +static struct platform_device pcm037_eth = { + .name = "smc911x", + .id = -1, + .num_resources = ARRAY_SIZE(smc911x_resources), + .resource = smc911x_resources, + .dev = { + .platform_data = &smc911x_info, + }, +}; + +static struct platdata_mtd_ram pcm038_sram_data = { + .bankwidth = 2, +}; + +static struct resource pcm038_sram_resource = { + .start = CS4_BASE_ADDR, + .end = CS4_BASE_ADDR + 512 * 1024 - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device pcm037_sram_device = { + .name = "mtd-ram", + .id = 0, + .dev = { + .platform_data = &pcm038_sram_data, + }, + .num_resources = 1, + .resource = &pcm038_sram_resource, +}; + +static struct mxc_nand_platform_data pcm037_nand_board_info = { + .width = 1, + .hw_ecc = 1, +}; + static struct platform_device *devices[] __initdata = { &pcm037_flash, + &pcm037_eth, + &pcm037_sram_device, }; /* @@ -81,6 +141,16 @@ static void __init mxc_board_init(void) mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3); mxc_register_device(&mxc_uart_device2, &uart_pdata); + + mxc_iomux_mode(MX31_PIN_BATT_LINE__OWIRE); + mxc_register_device(&mxc_w1_master_device, NULL); + + /* SMSC9215 IRQ pin */ + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)); + if (!gpio_request(MX31_PIN_GPIO3_1, "pcm037-eth")) + gpio_direction_input(MX31_PIN_GPIO3_1); + + mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); } /* diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c index 24c79650f9f3..8f1f992f002e 100644 --- a/arch/arm/mach-netx/fb.c +++ b/arch/arm/mach-netx/fb.c @@ -22,14 +22,11 @@ #include <linux/dma-mapping.h> #include <linux/amba/bus.h> #include <linux/amba/clcd.h> +#include <linux/err.h> #include <mach/netx-regs.h> #include <mach/hardware.h> -struct clk {}; - -static struct clk fb_clk; - static struct clcd_panel *netx_panel; void netx_clcd_enable(struct clcd_fb *fb) @@ -85,7 +82,7 @@ int clk_enable(struct clk *clk) struct clk *clk_get(struct device *dev, const char *id) { - return &fb_clk; + return dev && strcmp(dev_name(dev), "fb") == 0 ? NULL : ERR_PTR(-ENOENT); } void clk_put(struct clk *clk) diff --git a/arch/arm/mach-netx/include/mach/dma.h b/arch/arm/mach-netx/include/mach/dma.h deleted file mode 100644 index 690b3ebc43ac..000000000000 --- a/arch/arm/mach-netx/include/mach/dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * arch/arm/mach-netx/include/mach/dma.h - * - * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define MAX_DMA_CHANNELS 0 -#define MAX_DMA_ADDRESS ~0 diff --git a/arch/arm/mach-netx/include/mach/io.h b/arch/arm/mach-netx/include/mach/io.h index 468b92a82585..c3921cb3b6a6 100644 --- a/arch/arm/mach-netx/include/mach/io.h +++ b/arch/arm/mach-netx/include/mach/io.h @@ -22,7 +22,7 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-netx/include/mach/memory.h b/arch/arm/mach-netx/include/mach/memory.h index 53745a1378de..9a363f297f90 100644 --- a/arch/arm/mach-netx/include/mach/memory.h +++ b/arch/arm/mach-netx/include/mach/memory.h @@ -22,15 +22,5 @@ #define PHYS_OFFSET UL(0x80000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-netx/include/mach/netx-regs.h b/arch/arm/mach-netx/include/mach/netx-regs.h index 5104a00d40f4..08c60ff227be 100644 --- a/arch/arm/mach-netx/include/mach/netx-regs.h +++ b/arch/arm/mach-netx/include/mach/netx-regs.h @@ -328,6 +328,28 @@ #define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2)) #define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2)) + +/******************************* + * Memory Controller * + *******************************/ + +/* Registers */ +#define NETX_MEMCR_REG(ofs) __io(NETX_VA_MEMCR + (ofs)) +#define NETX_MEMCR_SRAM_CTRL(cs) NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */ +#define NETX_MEMCR_SDRAM_CFG_CTRL NETX_MEMCR_REG(0x40) +#define NETX_MEMCR_SDRAM_TIMING_CTRL NETX_MEMCR_REG(0x44) +#define NETX_MEMCR_SDRAM_MODE NETX_MEMCR_REG(0x48) +#define NETX_MEMCR_SDRAM_EXT_MODE NETX_MEMCR_REG(0x4c) +#define NETX_MEMCR_PRIO_TIMESLOT_CTRL NETX_MEMCR_REG(0x80) +#define NETX_MEMCR_PRIO_ACCESS_CTRL NETX_MEMCR_REG(0x84) + +/* Bits */ +#define NETX_MEMCR_SRAM_CTRL_WIDTHEXTMEM(x) (((x) & 0x3) << 24) +#define NETX_MEMCR_SRAM_CTRL_WSPOSTPAUSEEXTMEM(x) (((x) & 0x3) << 16) +#define NETX_MEMCR_SRAM_CTRL_WSPREPASEEXTMEM(x) (((x) & 0x3) << 8) +#define NETX_MEMCR_SRAM_CTRL_WSEXTMEM(x) (((x) & 0x1f) << 0) + + /******************************* * Dual Port Memory * *******************************/ diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 7c540c1f01fa..d51d627ce7cf 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -21,43 +21,100 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/clocksource.h> +#include <linux/clockchips.h> #include <linux/io.h> #include <mach/hardware.h> #include <asm/mach/time.h> #include <mach/netx-regs.h> +#define TIMER_CLOCKEVENT 0 +#define TIMER_CLOCKSOURCE 1 + +static void netx_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + u32 tmode; + + /* disable timer */ + writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + writel(LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); + tmode = NETX_GPIO_COUNTER_CTRL_RST_EN | + NETX_GPIO_COUNTER_CTRL_IRQ_EN | + NETX_GPIO_COUNTER_CTRL_RUN; + break; + + case CLOCK_EVT_MODE_ONESHOT: + writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); + tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | + NETX_GPIO_COUNTER_CTRL_RUN; + break; + + default: + WARN(1, "%s: unhandled mode %d\n", __func__, mode); + /* fall through */ + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + tmode = 0; + break; + } + + writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); +} + +static int netx_set_next_event(unsigned long evt, + struct clock_event_device *clk) +{ + writel(0 - evt, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKEVENT)); + return 0; +} + +static struct clock_event_device netx_clockevent = { + .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = netx_set_next_event, + .set_mode = netx_set_mode, +}; + /* * IRQ handler for the timer */ static irqreturn_t netx_timer_interrupt(int irq, void *dev_id) { - timer_tick(); + struct clock_event_device *evt = &netx_clockevent; /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + evt->event_handler(evt); + return IRQ_HANDLED; } static struct irqaction netx_timer_irq = { - .name = "NetX Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = netx_timer_interrupt, + .name = "NetX Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = netx_timer_interrupt, }; cycle_t netx_get_cycles(void) { - return readl(NETX_GPIO_COUNTER_CURRENT(1)); + return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); } static struct clocksource clocksource_netx = { - .name = "netx_timer", + .name = "netx_timer", .rating = 200, .read = netx_get_cycles, .mask = CLOCKSOURCE_MASK(32), - .shift = 20, + .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -77,24 +134,37 @@ static void __init netx_timer_init(void) /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); - /* Enable the interrupt in the specific timer register and start timer */ + /* Enable the interrupt in the specific timer + * register and start timer + */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(0)); + NETX_GPIO_COUNTER_CTRL(0)); setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); /* Setup timer one for clocksource */ - writel(0, NETX_GPIO_COUNTER_CTRL(1)); - writel(0, NETX_GPIO_COUNTER_CURRENT(1)); - writel(0xFFFFFFFF, NETX_GPIO_COUNTER_MAX(1)); + writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); + writel(0, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); + writel(0xffffffff, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKSOURCE)); - writel(NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(1)); + writel(NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); clocksource_netx.mult = clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift); clocksource_register(&clocksource_netx); + + netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, + netx_clockevent.shift); + netx_clockevent.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &netx_clockevent); + /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine. + * Adding some safety ... */ + netx_clockevent.min_delta_ns = + clockevent_delta2ns(0xa00, &netx_clockevent); + netx_clockevent.cpumask = cpumask_of_cpu(0); + clockevents_register_device(&netx_clockevent); } struct sys_timer netx_timer = { diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c index 32eabf5dfa4f..8fc6205dc3a5 100644 --- a/arch/arm/mach-netx/xc.c +++ b/arch/arm/mach-netx/xc.c @@ -92,10 +92,10 @@ static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) return -1; } -static int xc_patch(struct xc *x, void *patch, int count) +static int xc_patch(struct xc *x, const void *patch, int count) { unsigned int val, adr; - unsigned int *data = patch; + const unsigned int *data = patch; int i; for (i = 0; i < count; i++) { @@ -117,7 +117,7 @@ int xc_request_firmware(struct xc *x) struct fw_header *head; unsigned int size; int i; - void *src; + const void *src; unsigned long dst; sprintf(name, "xc%d.bin", x->no); diff --git a/arch/arm/mach-ns9xxx/include/mach/dma.h b/arch/arm/mach-ns9xxx/include/mach/dma.h deleted file mode 100644 index 3f50d8c9e5c7..000000000000 --- a/arch/arm/mach-ns9xxx/include/mach/dma.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * arch/arm/mach-ns9xxx/include/mach/dma.h - * - * Copyright (C) 2006 by Digi International Inc. - * 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 version 2 as published by - * the Free Software Foundation. - */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#endif /* ifndef __ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-ns9xxx/include/mach/hardware.h b/arch/arm/mach-ns9xxx/include/mach/hardware.h index 6dbb2030f563..76631128e11c 100644 --- a/arch/arm/mach-ns9xxx/include/mach/hardware.h +++ b/arch/arm/mach-ns9xxx/include/mach/hardware.h @@ -11,8 +11,6 @@ #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H -#include <asm/memory.h> - /* * NetSilicon NS9xxx internal mapping: * diff --git a/arch/arm/mach-ns9xxx/include/mach/io.h b/arch/arm/mach-ns9xxx/include/mach/io.h index 027bf649645a..f08451d2e1bc 100644 --- a/arch/arm/mach-ns9xxx/include/mach/io.h +++ b/arch/arm/mach-ns9xxx/include/mach/io.h @@ -13,7 +13,7 @@ #define IO_SPACE_LIMIT 0xffffffff /* XXX */ -#define __io(a) ((void __iomem *)(a)) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) #define __mem_isa(a) (IO_BASE + (a)) diff --git a/arch/arm/mach-ns9xxx/include/mach/memory.h b/arch/arm/mach-ns9xxx/include/mach/memory.h index 649ee6235b94..6107193adbfe 100644 --- a/arch/arm/mach-ns9xxx/include/mach/memory.h +++ b/arch/arm/mach-ns9xxx/include/mach/memory.h @@ -21,7 +21,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 79f0b1f8497b..10a301e32434 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -4,16 +4,19 @@ comment "OMAP Core Type" config ARCH_OMAP730 depends on ARCH_OMAP1 bool "OMAP730 Based System" + select CPU_ARM926T select ARCH_OMAP_OTG config ARCH_OMAP15XX depends on ARCH_OMAP1 default y bool "OMAP15xx Based System" + select CPU_ARM925T config ARCH_OMAP16XX depends on ARCH_OMAP1 bool "OMAP16xx Based System" + select CPU_ARM926T select ARCH_OMAP_OTG comment "OMAP Board Type" diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index db789461fca4..30308294e7c1 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -205,7 +205,7 @@ static struct platform_device *devices[] __initdata = { static int nand_dev_ready(struct omap_nand_platform_data *data) { - return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN); + return gpio_get_value(P2_NAND_RB_GPIO_PIN); } static struct omap_uart_config fsample_uart_config __initdata = { @@ -223,8 +223,9 @@ static struct omap_board_config_kernel fsample_config[] = { static void __init omap_fsample_init(void) { - if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN))) - nand_data.dev_ready = nand_dev_ready; + if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0) + BUG(); + nand_data.dev_ready = nand_dev_ready; omap_cfg_reg(L3_1610_FLASH_CS2B_OE); omap_cfg_reg(M8_1610_FLASH_CS2B_WE); diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c index ab9ee5820c48..409fa56d0a87 100644 --- a/arch/arm/mach-omap1/board-h2-mmc.c +++ b/arch/arm/mach-omap1/board-h2-mmc.c @@ -12,90 +12,68 @@ * published by the Free Software Foundation. */ +#include <linux/platform_device.h> + +#include <linux/i2c/tps65010.h> + #include <mach/mmc.h> #include <mach/gpio.h> -#ifdef CONFIG_MMC_OMAP -static int slot_cover_open; -static struct device *mmc_device; +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -static int h2_mmc_set_power(struct device *dev, int slot, int power_on, +static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, - power_on ? "on" : "off", vdd); -#endif - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } + if (power_on) + gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1); + else + gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0); return 0; } -static int h2_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) +static int mmc_late_init(struct device *dev) { -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1, - bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); -#endif - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } + int ret; - return 0; -} + ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power"); + if (ret < 0) + return ret; -static int h2_mmc_get_cover_state(struct device *dev, int slot) -{ - BUG_ON(slot != 0); - - return slot_cover_open; -} - -void h2_mmc_slot_cover_handler(void *arg, int state) -{ - if (mmc_device == NULL) - return; - - slot_cover_open = state; - omap_mmc_notify_cover_event(mmc_device, 0, state); -} - -static int h2_mmc_late_init(struct device *dev) -{ - int ret = 0; - - mmc_device = dev; + gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0); return ret; } -static void h2_mmc_cleanup(struct device *dev) +static void mmc_shutdown(struct device *dev) { + gpio_free(H2_TPS_GPIO_MMC_PWR_EN); } -static struct omap_mmc_platform_data h2_mmc_data = { +/* + * H2 could use the following functions tested: + * - mmc_get_cover_state that uses OMAP_MPUIO(1) + * - mmc_get_wp that uses OMAP_MPUIO(3) + */ +static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, - .switch_slot = NULL, - .init = h2_mmc_late_init, - .cleanup = h2_mmc_cleanup, + .init = mmc_late_init, + .shutdown = mmc_shutdown, + .dma_mask = 0xffffffff, .slots[0] = { - .set_power = h2_mmc_set_power, - .set_bus_mode = h2_mmc_set_bus_mode, - .get_ro = NULL, - .get_cover_state = h2_mmc_get_cover_state, + .set_power = mmc_set_power, .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 | MMC_VDD_32_33 | MMC_VDD_33_34, .name = "mmcblk", }, }; +static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC]; + void __init h2_mmc_init(void) { - omap_set_mmc_info(1, &h2_mmc_data); + mmc_data[0] = &mmc1_data; + omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC); } #else @@ -104,7 +82,4 @@ void __init h2_mmc_init(void) { } -void h2_mmc_slot_cover_handler(void *arg, int state) -{ -} #endif diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 3b65914b9141..b240c5f861da 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -250,11 +250,8 @@ static struct platform_device h2_kp_device = { #if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) static int h2_transceiver_mode(struct device *dev, int state) { - if (state & IR_SIRMODE) - omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0); - else /* MIR/FIR */ - omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1); - + /* SIR when low, else MIR/FIR when HIGH */ + gpio_set_value(H2_IRDA_FIRSEL_GPIO_PIN, !(state & IR_SIRMODE)); return 0; } #endif @@ -342,16 +339,31 @@ static struct platform_device *h2_devices[] __initdata = { static void __init h2_init_smc91x(void) { - if ((omap_request_gpio(0)) < 0) { + if (gpio_request(0, "SMC91x irq") < 0) { printk("Error requesting gpio 0 for smc91x irq\n"); return; } } +static int tps_setup(struct i2c_client *client, void *context) +{ + tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | + TPS_LDO1_ENABLE | TPS_VLDO1_3_0V); + + return 0; +} + +static struct tps65010_board tps_board = { + .base = H2_TPS_GPIO_BASE, + .outmask = 0x0f, + .setup = tps_setup, +}; + static struct i2c_board_info __initdata h2_i2c_board_info[] = { { I2C_BOARD_INFO("tps65010", 0x48), .irq = OMAP_GPIO_IRQ(58), + .platform_data = &tps_board, }, { I2C_BOARD_INFO("isp1301_omap", 0x2d), .irq = OMAP_GPIO_IRQ(2), @@ -381,15 +393,6 @@ static struct omap_usb_config h2_usb_config __initdata = { .pins[1] = 3, }; -static struct omap_mmc_config h2_mmc_config __initdata = { - .mmc[0] = { - .enabled = 1, - .wire4 = 1, - }, -}; - -extern struct omap_mmc_platform_data h2_mmc_data; - static struct omap_uart_config h2_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; @@ -400,7 +403,6 @@ static struct omap_lcd_config h2_lcd_config __initdata = { static struct omap_board_config_kernel h2_config[] __initdata = { { OMAP_TAG_USB, &h2_usb_config }, - { OMAP_TAG_MMC, &h2_mmc_config }, { OMAP_TAG_UART, &h2_uart_config }, { OMAP_TAG_LCD, &h2_lcd_config }, }; @@ -409,7 +411,7 @@ static struct omap_board_config_kernel h2_config[] __initdata = { static int h2_nand_dev_ready(struct omap_nand_platform_data *data) { - return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN); + return gpio_get_value(H2_NAND_RB_GPIO_PIN); } static void __init h2_init(void) @@ -428,8 +430,9 @@ static void __init h2_init(void) h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS; h2_nand_resource.end += SZ_4K - 1; - if (!(omap_request_gpio(H2_NAND_RB_GPIO_PIN))) - h2_nand_data.dev_ready = h2_nand_dev_ready; + if (gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0) + BUG(); + gpio_direction_input(H2_NAND_RB_GPIO_PIN); omap_cfg_reg(L3_1610_FLASH_CS2B_OE); omap_cfg_reg(M8_1610_FLASH_CS2B_WE); @@ -441,10 +444,10 @@ static void __init h2_init(void) /* Irda */ #if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A); - if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) { - omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0); - h2_irda_data.transceiver_mode = h2_transceiver_mode; - } + if (gpio_request(H2_IRDA_FIRSEL_GPIO_PIN, "IRDA mode") < 0) + BUG(); + gpio_direction_output(H2_IRDA_FIRSEL_GPIO_PIN, 0); + h2_irda_data.transceiver_mode = h2_transceiver_mode; #endif platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index 36085819098c..fdfe793d56f2 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -12,94 +12,55 @@ * published by the Free Software Foundation. */ +#include <linux/platform_device.h> + +#include <linux/i2c/tps65010.h> + #include <mach/mmc.h> #include <mach/gpio.h> -#ifdef CONFIG_MMC_OMAP -static int slot_cover_open; -static struct device *mmc_device; +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -static int h3_mmc_set_power(struct device *dev, int slot, int power_on, +static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, - power_on ? "on" : "off", vdd); -#endif - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } + if (power_on) + gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1); + else + gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0); return 0; } -static int h3_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) -{ - int ret = 0; - -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1, - bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); -#endif - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } - - /* Treated on upper level */ - - return bus_mode; -} - -static int h3_mmc_get_cover_state(struct device *dev, int slot) -{ - BUG_ON(slot != 0); - - return slot_cover_open; -} - -void h3_mmc_slot_cover_handler(void *arg, int state) -{ - if (mmc_device == NULL) - return; - - slot_cover_open = state; - omap_mmc_notify_cover_event(mmc_device, 0, state); -} - -static int h3_mmc_late_init(struct device *dev) -{ - int ret = 0; - - mmc_device = dev; - - return ret; -} - -static void h3_mmc_cleanup(struct device *dev) -{ -} - -static struct omap_mmc_platform_data h3_mmc_data = { +/* + * H3 could use the following functions tested: + * - mmc_get_cover_state that uses OMAP_MPUIO(1) + * - mmc_get_wp that maybe uses OMAP_MPUIO(3) + */ +static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, - .switch_slot = NULL, - .init = h3_mmc_late_init, - .cleanup = h3_mmc_cleanup, + .dma_mask = 0xffffffff, .slots[0] = { - .set_power = h3_mmc_set_power, - .set_bus_mode = h3_mmc_set_bus_mode, - .get_ro = NULL, - .get_cover_state = h3_mmc_get_cover_state, + .set_power = mmc_set_power, .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 | MMC_VDD_32_33 | MMC_VDD_33_34, .name = "mmcblk", }, }; +static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC]; + void __init h3_mmc_init(void) { - omap_set_mmc_info(1, &h3_mmc_data); + int ret; + + ret = gpio_request(H3_TPS_GPIO_MMC_PWR_EN, "MMC power"); + if (ret < 0) + return; + gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0); + + mmc_data[0] = &mmc1_data; + omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC); } #else @@ -108,7 +69,4 @@ void __init h3_mmc_init(void) { } -void h3_mmc_slot_cover_handler(void *arg, int state) -{ -} #endif diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index adfcd7b51393..5157eea9be35 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -447,15 +447,6 @@ static struct omap_usb_config h3_usb_config __initdata = { .pins[1] = 3, }; -static struct omap_mmc_config h3_mmc_config __initdata = { - .mmc[0] = { - .enabled = 1, - .wire4 = 1, - }, -}; - -extern struct omap_mmc_platform_data h3_mmc_data; - static struct omap_uart_config h3_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; @@ -466,7 +457,6 @@ static struct omap_lcd_config h3_lcd_config __initdata = { static struct omap_board_config_kernel h3_config[] __initdata = { { OMAP_TAG_USB, &h3_usb_config }, - { OMAP_TAG_MMC, &h3_mmc_config }, { OMAP_TAG_UART, &h3_uart_config }, { OMAP_TAG_LCD, &h3_lcd_config }, }; @@ -498,7 +488,7 @@ static struct omap_gpio_switch h3_gpio_switches[] __initdata = { static int nand_dev_ready(struct omap_nand_platform_data *data) { - return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN); + return gpio_get_value(H3_NAND_RB_GPIO_PIN); } static void __init h3_init(void) @@ -516,8 +506,9 @@ static void __init h3_init(void) nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS; nand_resource.end += SZ_4K - 1; - if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN))) - nand_data.dev_ready = nand_dev_ready; + if (gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0) + BUG(); + nand_data.dev_ready = nand_dev_ready; /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */ /* GPIO10 pullup/down register, Enable pullup on GPIO10 */ @@ -537,7 +528,7 @@ static void __init h3_init(void) static void __init h3_init_smc91x(void) { omap_cfg_reg(W15_1710_GPIO40); - if (omap_request_gpio(40) < 0) { + if (gpio_request(40, "SMC91x irq") < 0) { printk("Error requesting gpio 40 for smc91x irq\n"); return; } diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index cbc11be5cd2a..af2fb9070083 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -39,6 +39,7 @@ #include <mach/common.h> #include <mach/mcbsp.h> #include <mach/omap-alsa.h> +#include <mach/mmc.h> static int innovator_keymap[] = { KEY(0, 0, KEY_F1), @@ -301,7 +302,7 @@ static void __init innovator_init_smc91x(void) OMAP1510_FPGA_RST); udelay(750); } else { - if ((omap_request_gpio(0)) < 0) { + if (gpio_request(0, "SMC91x irq") < 0) { printk("Error requesting gpio 0 for smc91x irq\n"); return; } @@ -360,16 +361,49 @@ static struct omap_lcd_config innovator1610_lcd_config __initdata = { }; #endif -static struct omap_mmc_config innovator_mmc_config __initdata = { - .mmc [0] = { - .enabled = 1, - .wire4 = 1, - .wp_pin = OMAP_MPUIO(3), - .power_pin = -1, /* FPGA F3 UIO42 */ - .switch_pin = -1, /* FPGA F4 UIO43 */ +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +static int mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + if (power_on) + fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), + OMAP1510_FPGA_POWER); + else + fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3), + OMAP1510_FPGA_POWER); + + return 0; +} + +/* + * Innovator could use the following functions tested: + * - mmc_get_wp that uses OMAP_MPUIO(3) + * - mmc_get_cover_state that uses FPGA F4 UIO43 + */ +static struct omap_mmc_platform_data mmc1_data = { + .nr_slots = 1, + .slots[0] = { + .set_power = mmc_set_power, + .wires = 4, + .name = "mmcblk", }, }; +static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC]; + +void __init innovator_mmc_init(void) +{ + mmc_data[0] = &mmc1_data; + omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC); +} + +#else +static inline void innovator_mmc_init(void) +{ +} +#endif + static struct omap_uart_config innovator_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; @@ -377,7 +411,6 @@ static struct omap_uart_config innovator_uart_config __initdata = { static struct omap_board_config_kernel innovator_config[] = { { OMAP_TAG_USB, NULL }, { OMAP_TAG_LCD, NULL }, - { OMAP_TAG_MMC, &innovator_mmc_config }, { OMAP_TAG_UART, &innovator_uart_config }, }; @@ -412,6 +445,7 @@ static void __init innovator_init(void) omap_board_config_size = ARRAY_SIZE(innovator_config); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); + innovator_mmc_init(); } static void __init innovator_map_io(void) diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 38d9783ac6d6..4970c402a594 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -35,6 +35,7 @@ #include <mach/aic23.h> #include <mach/omapfb.h> #include <mach/lcd_mipid.h> +#include <mach/mmc.h> #define ADS7846_PENDOWN_GPIO 15 @@ -102,7 +103,7 @@ static void mipid_shutdown(struct mipid_platform_data *pdata) { if (pdata->nreset_gpio != -1) { printk(KERN_INFO "shutdown LCD\n"); - omap_set_gpio_dataout(pdata->nreset_gpio, 0); + gpio_set_value(pdata->nreset_gpio, 0); msleep(120); } } @@ -124,13 +125,13 @@ static void mipid_dev_init(void) static void ads7846_dev_init(void) { - if (omap_request_gpio(ADS7846_PENDOWN_GPIO) < 0) + if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0) printk(KERN_ERR "can't get ads7846 pen down GPIO\n"); } static int ads7846_get_pendown_state(void) { - return !omap_get_gpio_datain(ADS7846_PENDOWN_GPIO); + return !gpio_get_value(ADS7846_PENDOWN_GPIO); } static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = { @@ -173,26 +174,68 @@ static struct omap_usb_config nokia770_usb_config __initdata = { .pins[0] = 6, }; -static struct omap_mmc_config nokia770_mmc_config __initdata = { - .mmc[0] = { - .enabled = 0, - .wire4 = 0, - .wp_pin = -1, - .power_pin = -1, - .switch_pin = -1, - }, - .mmc[1] = { - .enabled = 0, - .wire4 = 0, - .wp_pin = -1, - .power_pin = -1, - .switch_pin = -1, +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +#define NOKIA770_GPIO_MMC_POWER 41 +#define NOKIA770_GPIO_MMC_SWITCH 23 + +static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + if (power_on) + gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1); + else + gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0); + + return 0; +} + +static int nokia770_mmc_get_cover_state(struct device *dev, int slot) +{ + return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH); +} + +static struct omap_mmc_platform_data nokia770_mmc2_data = { + .nr_slots = 1, + .dma_mask = 0xffffffff, + .slots[0] = { + .set_power = nokia770_mmc_set_power, + .get_cover_state = nokia770_mmc_get_cover_state, + .name = "mmcblk", }, }; +static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC]; + +static void __init nokia770_mmc_init(void) +{ + int ret; + + ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power"); + if (ret < 0) + return; + gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0); + + ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover"); + if (ret < 0) { + gpio_free(NOKIA770_GPIO_MMC_POWER); + return; + } + gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH); + + /* Only the second MMC controller is used */ + nokia770_mmc_data[1] = &nokia770_mmc2_data; + omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC); +} + +#else +static inline void nokia770_mmc_init(void) +{ +} +#endif + static struct omap_board_config_kernel nokia770_config[] __initdata = { { OMAP_TAG_USB, NULL }, - { OMAP_TAG_MMC, &nokia770_mmc_config }, }; #if defined(CONFIG_OMAP_DSP) @@ -228,9 +271,9 @@ static void nokia770_audio_pwr_up(void) /* Turn on codec */ aic23_power_up(); - if (omap_get_gpio_datain(HEADPHONE_GPIO)) + if (gpio_get_value(HEADPHONE_GPIO)) /* HP not connected, turn on amplifier */ - omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1); + gpio_set_value(AMPLIFIER_CTRL_GPIO, 1); else /* HP connected, do not turn on amplifier */ printk("HP connected\n"); @@ -250,7 +293,7 @@ static DECLARE_DELAYED_WORK(codec_power_down_work, codec_delayed_power_down); static void nokia770_audio_pwr_down(void) { /* Turn off amplifier */ - omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0); + gpio_set_value(AMPLIFIER_CTRL_GPIO, 0); /* Turn off codec: schedule delayed work */ schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */ @@ -335,6 +378,7 @@ static void __init omap_nokia770_init(void) omap_dsp_init(); ads7846_dev_init(); mipid_dev_init(); + nokia770_mmc_init(); } static void __init omap_nokia770_map_io(void) diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 3e766e49f7cc..ff9e67baa5c9 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -188,7 +188,8 @@ static struct gpio_led tps_leds[] = { /* NOTE: D9 and D2 have hardware blink support. * Also, D9 requires non-battery power. */ - { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", }, + { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", + .default_trigger = "ide-disk", }, { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", }, { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1, .default_trigger = "heartbeat", }, @@ -260,7 +261,6 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = { }, /* TODO when driver support is ready: * - aic23 audio chip at 0x1a - * - on Mistral, 24c04 eeprom at 0x50 * - optionally on Mistral, ov9640 camera sensor at 0x30 */ }; @@ -288,7 +288,7 @@ static void __init osk_init_cf(void) return; } /* the CF I/O IRQ is really active-low */ - set_irq_type(OMAP_GPIO_IRQ(62), IRQ_TYPE_EDGE_FALLING); + set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING); } static void __init osk_init_irq(void) @@ -337,11 +337,28 @@ static struct omap_board_config_kernel osk_config[] __initdata = { #ifdef CONFIG_OMAP_OSK_MISTRAL #include <linux/input.h> +#include <linux/i2c/at24.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> #include <mach/keypad.h> +static struct at24_platform_data at24c04 = { + .byte_len = SZ_4K / 8, + .page_size = 16, +}; + +static struct i2c_board_info __initdata mistral_i2c_board_info[] = { + { + /* NOTE: powered from LCD supply */ + I2C_BOARD_INFO("24c04", 0x50), + .platform_data = &at24c04, + }, + /* TODO when driver support is ready: + * - optionally ov9640 camera sensor at 0x30 + */ +}; + static const int osk_keymap[] = { /* KEY(col, row, code) */ KEY(0, 0, KEY_F1), /* SW4 */ @@ -483,23 +500,30 @@ static void __init osk_mistral_init(void) omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */ gpio_request(4, "ts_int"); gpio_direction_input(4); - set_irq_type(OMAP_GPIO_IRQ(4), IRQ_TYPE_EDGE_FALLING); + set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING); spi_register_board_info(mistral_boardinfo, ARRAY_SIZE(mistral_boardinfo)); - /* the sideways button (SW1) is for use as a "wakeup" button */ + /* the sideways button (SW1) is for use as a "wakeup" button + * + * NOTE: The Mistral board has the wakeup button (SW1) wired + * to the LCD 3.3V rail, which is powered down during suspend. + * To allow this button to wake up the omap, work around this + * HW bug by rewiring SW1 to use the main 3.3V rail. + */ omap_cfg_reg(N15_1610_MPUIO2); if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) { int ret = 0; + int irq = gpio_to_irq(OMAP_MPUIO(2)); gpio_direction_input(OMAP_MPUIO(2)); - set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQ_TYPE_EDGE_RISING); + set_irq_type(irq, IRQ_TYPE_EDGE_RISING); #ifdef CONFIG_PM /* share the IRQ in case someone wants to use the * button for more than wakeup from system sleep. */ - ret = request_irq(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), + ret = request_irq(irq, &osk_mistral_wake_interrupt, IRQF_SHARED, "mistral_wakeup", &osk_mistral_wake_interrupt); @@ -508,7 +532,7 @@ static void __init osk_mistral_init(void) printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n", ret); } else - enable_irq_wake(OMAP_GPIO_IRQ(OMAP_MPUIO(2))); + enable_irq_wake(irq); #endif } else printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n"); @@ -520,6 +544,9 @@ static void __init osk_mistral_init(void) if (gpio_request(2, "lcd_pwr") == 0) gpio_direction_output(2, 1); + i2c_register_board_info(1, mistral_i2c_board_info, + ARRAY_SIZE(mistral_i2c_board_info)); + platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices)); } #else diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index b58043644a6f..75e32d35afd9 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -255,7 +255,7 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery) { int charging, batt, hi, lo, mid; - charging = !omap_get_gpio_datain(PALMTE_DC_GPIO); + charging = !gpio_get_value(PALMTE_DC_GPIO); batt = battery[0]; if (charging) batt -= 60; @@ -316,7 +316,6 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery) static struct omap_board_config_kernel palmte_config[] __initdata = { { OMAP_TAG_USB, &palmte_usb_config }, - { OMAP_TAG_MMC, &palmte_mmc_config }, { OMAP_TAG_LCD, &palmte_lcd_config }, { OMAP_TAG_UART, &palmte_uart_config }, }; @@ -335,11 +334,11 @@ static void palmte_headphones_detect(void *data, int state) { if (state) { /* Headphones connected, disable speaker */ - omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0); + gpio_set_value(PALMTE_SPEAKER_GPIO, 0); printk(KERN_INFO "PM: speaker off\n"); } else { /* Headphones unplugged, re-enable speaker */ - omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1); + gpio_set_value(PALMTE_SPEAKER_GPIO, 1); printk(KERN_INFO "PM: speaker on\n"); } } @@ -347,18 +346,18 @@ static void palmte_headphones_detect(void *data, int state) static void __init palmte_misc_gpio_setup(void) { /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */ - if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) { + if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) { printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n"); return; } - omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1); + gpio_direction_input(PALMTE_PINTDAV_GPIO); /* Set USB-or-DC-IN pin as input (unused) */ - if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) { + if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) { printk(KERN_ERR "Could not reserve cable signal GPIO!\n"); return; } - omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1); + gpio_direction_input(PALMTE_USB_OR_DC_GPIO); } static void __init omap_palmte_init(void) diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 40f9860a09df..5c001afe8062 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -268,7 +268,7 @@ static struct platform_device *palmtt_devices[] __initdata = { static int palmtt_get_pendown_state(void) { - return !omap_get_gpio_datain(6); + return !gpio_get_value(6); } static const struct ads7846_platform_data palmtt_ts_info = { diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index e719294250b1..cc05257eb1cd 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -239,7 +239,7 @@ static struct platform_device *devices[] __initdata = { static int palmz71_get_pendown_state(void) { - return !omap_get_gpio_datain(PALMZ71_PENIRQ_GPIO); + return !gpio_get_value(PALMZ71_PENIRQ_GPIO); } static const struct ads7846_platform_data palmz71_ts_info = { @@ -267,16 +267,6 @@ static struct omap_usb_config palmz71_usb_config __initdata = { .pins[0] = 2, }; -static struct omap_mmc_config palmz71_mmc_config __initdata = { - .mmc[0] = { - .enabled = 1, - .wire4 = 0, - .wp_pin = PALMZ71_MMC_WP_GPIO, - .power_pin = -1, - .switch_pin = PALMZ71_MMC_IN_GPIO, - }, -}; - static struct omap_lcd_config palmz71_lcd_config __initdata = { .ctrl_name = "internal", }; @@ -287,7 +277,6 @@ static struct omap_uart_config palmz71_uart_config __initdata = { static struct omap_board_config_kernel palmz71_config[] __initdata = { {OMAP_TAG_USB, &palmz71_usb_config}, - {OMAP_TAG_MMC, &palmz71_mmc_config}, {OMAP_TAG_LCD, &palmz71_lcd_config}, {OMAP_TAG_UART, &palmz71_uart_config}, }; @@ -295,13 +284,13 @@ static struct omap_board_config_kernel palmz71_config[] __initdata = { static irqreturn_t palmz71_powercable(int irq, void *dev_id) { - if (omap_get_gpio_datain(PALMZ71_USBDETECT_GPIO)) { + if (gpio_get_value(PALMZ71_USBDETECT_GPIO)) { printk(KERN_INFO "PM: Power cable connected\n"); - set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO), + set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO), IRQ_TYPE_EDGE_FALLING); } else { printk(KERN_INFO "PM: Power cable disconnected\n"); - set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO), + set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO), IRQ_TYPE_EDGE_RISING); } return IRQ_HANDLED; @@ -323,29 +312,28 @@ palmz71_gpio_setup(int early) { if (early) { /* Only set GPIO1 so we have a working serial */ - omap_set_gpio_dataout(1, 1); - omap_set_gpio_direction(1, 0); + gpio_direction_output(1, 1); } else { /* Set MMC/SD host WP pin as input */ - if (omap_request_gpio(PALMZ71_MMC_WP_GPIO)) { + if (gpio_request(PALMZ71_MMC_WP_GPIO, "MMC WP") < 0) { printk(KERN_ERR "Could not reserve WP GPIO!\n"); return; } - omap_set_gpio_direction(PALMZ71_MMC_WP_GPIO, 1); + gpio_direction_input(PALMZ71_MMC_WP_GPIO); /* Monitor the Power-cable-connected signal */ - if (omap_request_gpio(PALMZ71_USBDETECT_GPIO)) { + if (gpio_request(PALMZ71_USBDETECT_GPIO, "USB detect") < 0) { printk(KERN_ERR "Could not reserve cable signal GPIO!\n"); return; } - omap_set_gpio_direction(PALMZ71_USBDETECT_GPIO, 1); - if (request_irq(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO), + gpio_direction_input(PALMZ71_USBDETECT_GPIO); + if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO), palmz71_powercable, IRQF_SAMPLE_RANDOM, "palmz71-cable", 0)) printk(KERN_ERR "IRQ request for power cable failed!\n"); - palmz71_powercable(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO), 0); + palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), 0); } } diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index b715917bfdaf..3b9f907aa899 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -205,7 +205,7 @@ static struct platform_device *devices[] __initdata = { static int nand_dev_ready(struct omap_nand_platform_data *data) { - return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN); + return gpio_get_value(P2_NAND_RB_GPIO_PIN); } static struct omap_uart_config perseus2_uart_config __initdata = { @@ -223,8 +223,9 @@ static struct omap_board_config_kernel perseus2_config[] __initdata = { static void __init omap_perseus2_init(void) { - if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN))) - nand_data.dev_ready = nand_dev_ready; + if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0) + BUG(); + nand_data.dev_ready = nand_dev_ready; omap_cfg_reg(L3_1610_FLASH_CS2B_OE); omap_cfg_reg(M8_1610_FLASH_CS2B_WE); diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c index 0be4ebaa2842..66a4d7d5255d 100644 --- a/arch/arm/mach-omap1/board-sx1-mmc.c +++ b/arch/arm/mach-omap1/board-sx1-mmc.c @@ -12,30 +12,20 @@ * published by the Free Software Foundation. */ +#include <linux/platform_device.h> + #include <mach/hardware.h> #include <mach/mmc.h> #include <mach/gpio.h> -#ifdef CONFIG_MMC_OMAP -static int slot_cover_open; -static struct device *mmc_device; +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -static int sx1_mmc_set_power(struct device *dev, int slot, int power_on, +static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { int err; u8 dat = 0; -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, - power_on ? "on" : "off", vdd); -#endif - - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } - err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat); if (err < 0) return err; @@ -48,68 +38,23 @@ static int sx1_mmc_set_power(struct device *dev, int slot, int power_on, return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat); } -static int sx1_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) -{ -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1, - bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); -#endif - if (slot != 0) { - dev_err(dev, "No such slot %d\n", slot + 1); - return -ENODEV; - } - - return 0; -} - -static int sx1_mmc_get_cover_state(struct device *dev, int slot) -{ - BUG_ON(slot != 0); - - return slot_cover_open; -} - -void sx1_mmc_slot_cover_handler(void *arg, int state) -{ - if (mmc_device == NULL) - return; - - slot_cover_open = state; - omap_mmc_notify_cover_event(mmc_device, 0, state); -} - -static int sx1_mmc_late_init(struct device *dev) -{ - int ret = 0; - - mmc_device = dev; - - return ret; -} - -static void sx1_mmc_cleanup(struct device *dev) -{ -} - -static struct omap_mmc_platform_data sx1_mmc_data = { +/* Cover switch is at OMAP_MPUIO(3) */ +static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, - .switch_slot = NULL, - .init = sx1_mmc_late_init, - .cleanup = sx1_mmc_cleanup, .slots[0] = { - .set_power = sx1_mmc_set_power, - .set_bus_mode = sx1_mmc_set_bus_mode, - .get_ro = NULL, - .get_cover_state = sx1_mmc_get_cover_state, + .set_power = mmc_set_power, .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 | MMC_VDD_32_33 | MMC_VDD_33_34, .name = "mmcblk", }, }; +static struct omap_mmc_platform_data *mmc_data[OMAP15XX_NR_MMC]; + void __init sx1_mmc_init(void) { - omap_set_mmc_info(1, &sx1_mmc_data); + mmc_data[0] = &mmc1_data; + omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC); } #else @@ -118,7 +63,4 @@ void __init sx1_mmc_init(void) { } -void sx1_mmc_slot_cover_handler(void *arg, int state) -{ -} #endif diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 130bcc6fd082..8171fe0ca082 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -378,15 +378,6 @@ static struct omap_usb_config sx1_usb_config __initdata = { .pins[2] = 0, }; -/*----------- MMC -------------------------*/ - -static struct omap_mmc_config sx1_mmc_config __initdata = { - .mmc [0] = { - .enabled = 1, - .wire4 = 0, - }, -}; - /*----------- LCD -------------------------*/ static struct platform_device sx1_lcd_device = { @@ -414,7 +405,6 @@ static struct omap_uart_config sx1_uart_config __initdata = { static struct omap_board_config_kernel sx1_config[] __initdata = { { OMAP_TAG_USB, &sx1_usb_config }, - { OMAP_TAG_MMC, &sx1_mmc_config }, { OMAP_TAG_LCD, &sx1_lcd_config }, { OMAP_TAG_UART, &sx1_uart_config }, }; @@ -436,14 +426,9 @@ static void __init omap_sx1_init(void) omap_request_gpio(1); /* A_IRDA_OFF */ omap_request_gpio(11); /* A_SWITCH */ omap_request_gpio(15); /* A_USB_ON */ - omap_set_gpio_direction(1, 0);/* gpio1 -> output */ - omap_set_gpio_direction(11, 0);/* gpio11 -> output */ - omap_set_gpio_direction(15, 0);/* gpio15 -> output */ - /* set GPIO data */ - omap_set_gpio_dataout(1, 1);/*A_IRDA_OFF = 1 */ - omap_set_gpio_dataout(11, 0);/*A_SWITCH = 0 */ - omap_set_gpio_dataout(15, 0);/*A_USB_ON = 0 */ - + gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */ + gpio_direction_output(11, 0); /*A_SWITCH = 0 */ + gpio_direction_output(15, 0); /*A_USB_ON = 0 */ } /*----------------------------------------*/ static void __init omap_sx1_init_irq(void) diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 45a01311669a..c224f3c64235 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/notifier.h> @@ -140,21 +141,12 @@ static struct omap_usb_config voiceblue_usb_config __initdata = { .pins[2] = 6, }; -static struct omap_mmc_config voiceblue_mmc_config __initdata = { - .mmc[0] = { - .enabled = 1, - .power_pin = 2, - .switch_pin = -1, - }, -}; - static struct omap_uart_config voiceblue_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; static struct omap_board_config_kernel voiceblue_config[] = { { OMAP_TAG_USB, &voiceblue_usb_config }, - { OMAP_TAG_MMC, &voiceblue_mmc_config }, { OMAP_TAG_UART, &voiceblue_uart_config }, }; @@ -168,29 +160,27 @@ static void __init voiceblue_init_irq(void) static void __init voiceblue_init(void) { /* Watchdog */ - omap_request_gpio(0); + gpio_request(0, "Watchdog"); /* smc91x reset */ - omap_request_gpio(7); - omap_set_gpio_direction(7, 0); - omap_set_gpio_dataout(7, 1); + gpio_request(7, "SMC91x reset"); + gpio_direction_output(7, 1); udelay(2); /* wait at least 100ns */ - omap_set_gpio_dataout(7, 0); + gpio_set_value(7, 0); mdelay(50); /* 50ms until PHY ready */ /* smc91x interrupt pin */ - omap_request_gpio(8); + gpio_request(8, "SMC91x irq"); /* 16C554 reset*/ - omap_request_gpio(6); - omap_set_gpio_direction(6, 0); - omap_set_gpio_dataout(6, 0); + gpio_request(6, "16C554 reset"); + gpio_direction_output(6, 0); /* 16C554 interrupt pins */ - omap_request_gpio(12); - omap_request_gpio(13); - omap_request_gpio(14); - omap_request_gpio(15); - set_irq_type(OMAP_GPIO_IRQ(12), IRQ_TYPE_EDGE_RISING); - set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING); - set_irq_type(OMAP_GPIO_IRQ(14), IRQ_TYPE_EDGE_RISING); - set_irq_type(OMAP_GPIO_IRQ(15), IRQ_TYPE_EDGE_RISING); + gpio_request(12, "16C554 irq"); + gpio_request(13, "16C554 irq"); + gpio_request(14, "16C554 irq"); + gpio_request(15, "16C554 irq"); + set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING); + set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING); platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); omap_board_config = voiceblue_config; @@ -244,19 +234,18 @@ static int wdt_gpio_state; void voiceblue_wdt_enable(void) { - omap_set_gpio_direction(0, 0); - omap_set_gpio_dataout(0, 0); - omap_set_gpio_dataout(0, 1); - omap_set_gpio_dataout(0, 0); + gpio_direction_output(0, 0); + gpio_set_value(0, 1); + gpio_set_value(0, 0); wdt_gpio_state = 0; } void voiceblue_wdt_disable(void) { - omap_set_gpio_dataout(0, 0); - omap_set_gpio_dataout(0, 1); - omap_set_gpio_dataout(0, 0); - omap_set_gpio_direction(0, 1); + gpio_set_value(0, 0); + gpio_set_value(0, 1); + gpio_set_value(0, 0); + gpio_direction_input(0); } void voiceblue_wdt_ping(void) @@ -265,7 +254,7 @@ void voiceblue_wdt_ping(void) return; wdt_gpio_state = !wdt_gpio_state; - omap_set_gpio_dataout(0, wdt_gpio_state); + gpio_set_value(0, wdt_gpio_state); } void voiceblue_reset(void) diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 5635b511ab6f..c1dcdf18d8dd 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -705,7 +705,6 @@ static struct clk bclk_16xx = { static struct clk mmc1_ck = { .name = "mmc_ck", - .id = 1, /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, @@ -720,7 +719,7 @@ static struct clk mmc1_ck = { static struct clk mmc2_ck = { .name = "mmc_ck", - .id = 2, + .id = 1, /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index e382b438c64e..77382d8b6b2f 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -22,6 +22,7 @@ #include <mach/board.h> #include <mach/mux.h> #include <mach/gpio.h> +#include <mach/mmc.h> /*-------------------------------------------------------------------------*/ @@ -99,6 +100,95 @@ static inline void omap_init_mbox(void) static inline void omap_init_mbox(void) { } #endif +/*-------------------------------------------------------------------------*/ + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller, + int controller_nr) +{ + if (controller_nr == 0) { + omap_cfg_reg(MMC_CMD); + omap_cfg_reg(MMC_CLK); + omap_cfg_reg(MMC_DAT0); + if (cpu_is_omap1710()) { + omap_cfg_reg(M15_1710_MMC_CLKI); + omap_cfg_reg(P19_1710_MMC_CMDDIR); + omap_cfg_reg(P20_1710_MMC_DATDIR0); + } + if (mmc_controller->slots[0].wires == 4) { + omap_cfg_reg(MMC_DAT1); + /* NOTE: DAT2 can be on W10 (here) or M15 */ + if (!mmc_controller->slots[0].nomux) + omap_cfg_reg(MMC_DAT2); + omap_cfg_reg(MMC_DAT3); + } + } + + /* Block 2 is on newer chips, and has many pinout options */ + if (cpu_is_omap16xx() && controller_nr == 1) { + if (!mmc_controller->slots[1].nomux) { + omap_cfg_reg(Y8_1610_MMC2_CMD); + omap_cfg_reg(Y10_1610_MMC2_CLK); + omap_cfg_reg(R18_1610_MMC2_CLKIN); + omap_cfg_reg(W8_1610_MMC2_DAT0); + if (mmc_controller->slots[1].wires == 4) { + omap_cfg_reg(V8_1610_MMC2_DAT1); + omap_cfg_reg(W15_1610_MMC2_DAT2); + omap_cfg_reg(R10_1610_MMC2_DAT3); + } + + /* These are needed for the level shifter */ + omap_cfg_reg(V9_1610_MMC2_CMDDIR); + omap_cfg_reg(V5_1610_MMC2_DATDIR0); + omap_cfg_reg(W19_1610_MMC2_DATDIR1); + } + + /* Feedback clock must be set on OMAP-1710 MMC2 */ + if (cpu_is_omap1710()) + omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), + MOD_CONF_CTRL_1); + } +} + +void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers) +{ + int i; + + for (i = 0; i < nr_controllers; i++) { + unsigned long base, size; + unsigned int irq = 0; + + if (!mmc_data[i]) + continue; + + omap1_mmc_mux(mmc_data[i], i); + + switch (i) { + case 0: + base = OMAP1_MMC1_BASE; + irq = INT_MMC; + break; + case 1: + if (!cpu_is_omap16xx()) + return; + base = OMAP1_MMC2_BASE; + irq = INT_1610_MMC2; + break; + default: + continue; + } + size = OMAP1_MMC_SIZE; + + omap_mmc_add(i, base, size, irq, mmc_data[i]); + }; +} + +#endif + +/*-------------------------------------------------------------------------*/ + #if defined(CONFIG_OMAP_STI) #define OMAP1_STI_BASE 0xfffea000 diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index 04995381aa5c..4f2b8a7adb19 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c @@ -177,9 +177,9 @@ void omap1510_fpga_init_irq(void) * NOTE: For general GPIO/MPUIO access and interrupts, please see * gpio.[ch] */ - omap_request_gpio(13); - omap_set_gpio_direction(13, 1); - set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING); + gpio_request(13, "FPGA irq"); + gpio_direction_input(13); + set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING); set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux); } diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c index 13083d7e692d..89bb8756f450 100644 --- a/arch/arm/mach-omap1/id.c +++ b/arch/arm/mach-omap1/id.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <mach/cpu.h> #define OMAP_DIE_ID_0 0xfffe1800 #define OMAP_DIE_ID_1 0xfffe1804 @@ -30,6 +31,8 @@ struct omap_id { u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ }; +static unsigned int omap_revision; + /* Register values to detect the OMAP version */ static struct omap_id omap_ids[] __initdata = { { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, @@ -53,6 +56,12 @@ static struct omap_id omap_ids[] __initdata = { { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, }; +unsigned int omap_rev(void) +{ + return omap_revision; +} +EXPORT_SYMBOL(omap_rev); + /* * Get OMAP type from PROD_ID. * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. @@ -121,17 +130,18 @@ void __init omap_check_revision(void) omap_id = omap_readl(OMAP32_ID_0); #ifdef DEBUG - printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); - printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", + printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); + printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", omap_readl(OMAP_DIE_ID_1), (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); - printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0)); - printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", + printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n", + omap_readl(OMAP_PRODUCTION_ID_0)); + printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", omap_readl(OMAP_PRODUCTION_ID_1), omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); - printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); - printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); - printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); + printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); + printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); + printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); #endif system_serial_high = omap_readl(OMAP_DIE_ID_0); @@ -140,7 +150,7 @@ void __init omap_check_revision(void) /* First check only the major version in a safe way */ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { if (jtag_id == (omap_ids[i].jtag_id)) { - system_rev = omap_ids[i].type; + omap_revision = omap_ids[i].type; break; } } @@ -148,7 +158,7 @@ void __init omap_check_revision(void) /* Check if we can find the die revision */ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { - system_rev = omap_ids[i].type; + omap_revision = omap_ids[i].type; break; } } @@ -158,38 +168,35 @@ void __init omap_check_revision(void) if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev && omap_id == omap_ids[i].omap_id) { - system_rev = omap_ids[i].type; + omap_revision = omap_ids[i].type; break; } } /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ - cpu_type = system_rev >> 24; + cpu_type = omap_revision >> 24; switch (cpu_type) { case 0x07: - system_rev |= 0x07; + omap_revision |= 0x07; break; case 0x03: case 0x15: - system_rev |= 0x15; + omap_revision |= 0x15; break; case 0x16: case 0x17: - system_rev |= 0x16; - break; - case 0x24: - system_rev |= 0x24; + omap_revision |= 0x16; break; default: - printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type); + printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type); } - printk("OMAP%04x", system_rev >> 16); - if ((system_rev >> 8) & 0xff) - printk("%x", (system_rev >> 8) & 0xff); - printk(" revision %i handled as %02xxx id: %08x%08x\n", - die_rev, system_rev & 0xff, system_serial_low, + printk(KERN_INFO "OMAP%04x", omap_revision >> 16); + if ((omap_revision >> 8) & 0xff) + printk(KERN_INFO "%x", (omap_revision >> 8) & 0xff); + printk(KERN_INFO " revision %i handled as %02xxx id: %08x%08x\n", + die_rev, omap_revision & 0xff, system_serial_low, system_serial_high); } diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index 71fe2cc7f7cf..17c9d0e04216 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c @@ -65,8 +65,8 @@ void h2p2_dbg_leds_event(led_event_t evt) /* all leds off during suspend or shutdown */ if (! machine_is_omap_perseus2()) { - omap_set_gpio_dataout(GPIO_TIMER, 0); - omap_set_gpio_dataout(GPIO_IDLE, 0); + gpio_set_value(GPIO_TIMER, 0); + gpio_set_value(GPIO_IDLE, 0); } __raw_writew(~0, &fpga->leds); @@ -94,7 +94,7 @@ void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2()) hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; else { - omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON); + gpio_set_value(GPIO_TIMER, led_state & LED_TIMER_ON); goto done; } @@ -106,7 +106,7 @@ void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2()) hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; else { - omap_set_gpio_dataout(GPIO_IDLE, 1); + gpio_set_value(GPIO_IDLE, 1); goto done; } @@ -116,7 +116,7 @@ void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2()) hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; else { - omap_set_gpio_dataout(GPIO_IDLE, 0); + gpio_set_value(GPIO_IDLE, 0); goto done; } diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c index 98e789622dfd..499d7ad8697d 100644 --- a/arch/arm/mach-omap1/leds-osk.c +++ b/arch/arm/mach-omap1/leds-osk.c @@ -44,8 +44,8 @@ static void mistral_setled(void) green = 1; /* else both sides are disabled */ - omap_set_gpio_dataout(GPIO_LED_GREEN, green); - omap_set_gpio_dataout(GPIO_LED_RED, red); + gpio_set_value(GPIO_LED_GREEN, green); + gpio_set_value(GPIO_LED_RED, red); } #endif diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c index 6cdad93c4a00..8cbf2562dcaa 100644 --- a/arch/arm/mach-omap1/leds.c +++ b/arch/arm/mach-omap1/leds.c @@ -47,14 +47,14 @@ omap_leds_init(void) * that's a different kind of LED (just one color at a time). */ omap_cfg_reg(P18_1610_GPIO3); - if (omap_request_gpio(3) == 0) - omap_set_gpio_direction(3, 0); + if (gpio_request(3, "LED red") == 0) + gpio_direction_output(3, 1); else printk(KERN_WARNING "LED: can't get GPIO3/red?\n"); omap_cfg_reg(MPUIO4); - if (omap_request_gpio(OMAP_MPUIO(4)) == 0) - omap_set_gpio_direction(OMAP_MPUIO(4), 0); + if (gpio_request(OMAP_MPUIO(4), "LED green") == 0) + gpio_direction_output(OMAP_MPUIO(4), 1); else printk(KERN_WARNING "LED: can't get MPUIO4/green?\n"); } diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 770d256c790b..9774c1f5311e 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -226,7 +226,8 @@ void omap_pm_suspend(void) { unsigned long arg0 = 0, arg1 = 0; - printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev); + printk(KERN_INFO "PM: OMAP%x is trying to enter deep sleep...\n", + omap_rev()); omap_serial_wake_trigger(1); @@ -421,7 +422,8 @@ void omap_pm_suspend(void) omap_serial_wake_trigger(0); - printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev); + printk(KERN_INFO "PM: OMAP%x is re-starting from deep sleep...\n", + omap_rev()); } #if defined(DEBUG) && defined(CONFIG_PROC_FS) diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 528691d5cb51..0002084e0655 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -244,22 +244,22 @@ static void __init omap_serial_set_port_wakeup(int gpio_nr) { int ret; - ret = omap_request_gpio(gpio_nr); + ret = gpio_request(gpio_nr, "UART wake"); if (ret < 0) { printk(KERN_ERR "Could not request UART wake GPIO: %i\n", gpio_nr); return; } - omap_set_gpio_direction(gpio_nr, 1); - ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt, + gpio_direction_input(gpio_nr); + ret = request_irq(gpio_to_irq(gpio_nr), &omap_serial_wake_interrupt, IRQF_TRIGGER_RISING, "serial wakeup", NULL); if (ret) { - omap_free_gpio(gpio_nr); + gpio_free(gpio_nr); printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", gpio_nr); return; } - enable_irq_wake(OMAP_GPIO_IRQ(gpio_nr)); + enable_irq_wake(gpio_to_irq(gpio_nr)); } static int __init omap_serial_wakeup_init(void) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 4832fcc7d04a..3754b79092ab 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -55,3 +55,7 @@ config MACH_OMAP_LDP config MACH_OVERO bool "Gumstix Overo board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP3_PANDORA + bool "OMAP3 Pandora" + depends on ARCH_OMAP3 && ARCH_OMAP34XX
\ No newline at end of file diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index c69392372c99..bbd12bc10fdc 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -27,9 +27,15 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o -obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o +obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \ + mmc-twl4030.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o -obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o -obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o -obj-$(CONFIG_MACH_OVERO) += board-overo.o +obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \ + mmc-twl4030.o +obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \ + mmc-twl4030.o +obj-$(CONFIG_MACH_OVERO) += board-overo.o \ + mmc-twl4030.o +obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ + mmc-twl4030.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 24688efaa445..83fa37211d77 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -19,6 +19,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/delay.h> +#include <linux/i2c/twl4030.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> @@ -35,6 +36,7 @@ #include <mach/common.h> #include <mach/gpmc.h> +#include "mmc-twl4030.h" #define SDP2430_FLASH_CS 0 #define SDP2430_SMC91X_CS 5 @@ -168,13 +170,13 @@ static inline void __init sdp2430_init_smc91x(void) sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f; udelay(100); - if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) { + if (gpio_request(OMAP24XX_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", OMAP24XX_ETHR_GPIO_IRQ); gpmc_cs_free(eth_cs); goto out; } - omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1); + gpio_direction_input(OMAP24XX_ETHR_GPIO_IRQ); out: clk_disable(gpmc_fck); @@ -197,12 +199,58 @@ static struct omap_board_config_kernel sdp2430_config[] = { {OMAP_TAG_UART, &sdp2430_uart_config}, }; + +static struct twl4030_gpio_platform_data sdp2430_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, +}; + +static struct twl4030_platform_data sdp2430_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .gpio = &sdp2430_gpio_data, +}; + +static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_24XX_SYS_NIRQ, + .platform_data = &sdp2430_twldata, + }, +}; + +static int __init omap2430_i2c_init(void) +{ + omap_register_i2c_bus(1, 400, NULL, 0); + omap_register_i2c_bus(2, 2600, sdp2430_i2c_boardinfo, + ARRAY_SIZE(sdp2430_i2c_boardinfo)); + return 0; +} + +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + .ext_clock = 1, + }, + {} /* Terminator */ +}; + static void __init omap_2430sdp_init(void) { + omap2430_i2c_init(); + platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); omap_board_config = sdp2430_config; omap_board_config_size = ARRAY_SIZE(sdp2430_config); omap_serial_init(); + twl4030_mmc_init(mmc); } static void __init omap_2430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 989ad152d7f8..bf1e5d32c2a3 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -236,13 +236,13 @@ static inline void __init apollon_init_smc91x(void) udelay(100); omap_cfg_reg(W4__24XX_GPIO74); - if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) { + if (gpio_request(APOLLON_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", APOLLON_ETHR_GPIO_IRQ); gpmc_cs_free(APOLLON_ETH_CS); goto out; } - omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1); + gpio_direction_input(APOLLON_ETHR_GPIO_IRQ); out: clk_disable(gpmc_fck); @@ -261,16 +261,6 @@ static struct omap_uart_config apollon_uart_config __initdata = { .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2), }; -static struct omap_mmc_config apollon_mmc_config __initdata = { - .mmc [0] = { - .enabled = 1, - .wire4 = 1, - .wp_pin = -1, - .power_pin = -1, - .switch_pin = -1, - }, -}; - static struct omap_usb_config apollon_usb_config __initdata = { .register_dev = 1, .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */ @@ -284,7 +274,6 @@ static struct omap_lcd_config apollon_lcd_config __initdata = { static struct omap_board_config_kernel apollon_config[] = { { OMAP_TAG_UART, &apollon_uart_config }, - { OMAP_TAG_MMC, &apollon_mmc_config }, { OMAP_TAG_USB, &apollon_usb_config }, { OMAP_TAG_LCD, &apollon_lcd_config }, }; @@ -327,15 +316,15 @@ static void __init apollon_sw_init(void) /* Enter SW - Y11 */ omap_cfg_reg(Y11_242X_GPIO16); omap_request_gpio(SW_ENTER_GPIO16); - omap_set_gpio_direction(SW_ENTER_GPIO16, 1); + gpio_direction_input(SW_ENTER_GPIO16); /* Up SW - AA12 */ omap_cfg_reg(AA12_242X_GPIO17); omap_request_gpio(SW_UP_GPIO17); - omap_set_gpio_direction(SW_UP_GPIO17, 1); + gpio_direction_input(SW_UP_GPIO17); /* Down SW - AA8 */ omap_cfg_reg(AA8_242X_GPIO58); omap_request_gpio(SW_DOWN_GPIO58); - omap_set_gpio_direction(SW_DOWN_GPIO58, 1); + gpio_direction_input(SW_DOWN_GPIO58); set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQ_TYPE_EDGE_RISING); if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt, @@ -359,9 +348,8 @@ static void __init apollon_usb_init(void) /* USB device */ /* DEVICE_SUSPEND */ omap_cfg_reg(P21_242X_GPIO12); - omap_request_gpio(12); - omap_set_gpio_direction(12, 0); /* OUT */ - omap_set_gpio_dataout(12, 0); + gpio_request(12, "USB suspend"); + gpio_direction_output(12, 0); } static void __init omap_apollon_init(void) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 9ba097868e72..3b34c20d1df4 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -41,19 +41,8 @@ static struct omap_uart_config generic_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_mmc_config generic_mmc_config __initdata = { - .mmc [0] = { - .enabled = 0, - .wire4 = 0, - .wp_pin = -1, - .power_pin = -1, - .switch_pin = -1, - }, -}; - static struct omap_board_config_kernel generic_config[] = { { OMAP_TAG_UART, &generic_uart_config }, - { OMAP_TAG_MMC, &generic_mmc_config }, }; static void __init omap_generic_init(void) diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 2fef2c845083..5e9b14675b1e 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -19,6 +19,7 @@ #include <linux/delay.h> #include <linux/workqueue.h> #include <linux/i2c.h> +#include <linux/i2c/at24.h> #include <linux/input.h> #include <linux/err.h> #include <linux/clk.h> @@ -372,31 +373,33 @@ static struct omap_uart_config h4_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_mmc_config h4_mmc_config __initdata = { - .mmc [0] = { - .enabled = 1, - .wire4 = 1, - .wp_pin = -1, - .power_pin = -1, - .switch_pin = -1, - }, -}; - static struct omap_lcd_config h4_lcd_config __initdata = { .ctrl_name = "internal", }; static struct omap_board_config_kernel h4_config[] = { { OMAP_TAG_UART, &h4_uart_config }, - { OMAP_TAG_MMC, &h4_mmc_config }, { OMAP_TAG_LCD, &h4_lcd_config }, }; +static struct at24_platform_data m24c01 = { + .byte_len = SZ_1K / 8, + .page_size = 16, +}; + static struct i2c_board_info __initdata h4_i2c_board_info[] = { { I2C_BOARD_INFO("isp1301_omap", 0x2d), .irq = OMAP_GPIO_IRQ(125), }, + { /* EEPROM on mainboard */ + I2C_BOARD_INFO("24c01", 0x52), + .platform_data = &m24c01, + }, + { /* EEPROM on cpu card */ + I2C_BOARD_INFO("24c01", 0x57), + .platform_data = &m24c01, + }, }; static void __init omap_h4_init(void) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 1ea59986aa7a..aa6972781e4a 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> +#include <linux/i2c/twl4030.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -38,11 +39,69 @@ #include <asm/delay.h> #include <mach/control.h> +#include "mmc-twl4030.h" + +#define SDP3430_SMC91X_CS 3 + +static struct resource ldp_smc911x_resources[] = { + [0] = { + .start = OMAP34XX_ETHR_START, + .end = OMAP34XX_ETHR_START + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct platform_device ldp_smc911x_device = { + .name = "smc911x", + .id = -1, + .num_resources = ARRAY_SIZE(ldp_smc911x_resources), + .resource = ldp_smc911x_resources, +}; + +static struct platform_device *ldp_devices[] __initdata = { + &ldp_smc911x_device, +}; + +static inline void __init ldp_init_smc911x(void) +{ + int eth_cs; + unsigned long cs_mem_base; + int eth_gpio = 0; + + eth_cs = LDP_SMC911X_CS; + + if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smc911x\n"); + return; + } + + ldp_smc911x_resources[0].start = cs_mem_base + 0x0; + ldp_smc911x_resources[0].end = cs_mem_base + 0xf; + udelay(100); + + eth_gpio = LDP_SMC911X_GPIO; + + ldp_smc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio); + + if (omap_request_gpio(eth_gpio) < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smc911x IRQ\n", + eth_gpio); + return; + } + gpio_direction_input(eth_gpio); +} + static void __init omap_ldp_init_irq(void) { omap2_init_common_hw(); omap_init_irq(); omap_gpio_init(); + ldp_init_smc911x(); } static struct omap_uart_config ldp_uart_config __initdata = { @@ -53,20 +112,56 @@ static struct omap_board_config_kernel ldp_config[] __initdata = { { OMAP_TAG_UART, &ldp_uart_config }, }; +static struct twl4030_gpio_platform_data ldp_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, +}; + +static struct twl4030_platform_data ldp_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .gpio = &ldp_gpio_data, +}; + +static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &ldp_twldata, + }, +}; + static int __init omap_i2c_init(void) { - omap_register_i2c_bus(1, 2600, NULL, 0); + omap_register_i2c_bus(1, 2600, ldp_i2c_boardinfo, + ARRAY_SIZE(ldp_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); return 0; } +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap_ldp_init(void) { omap_i2c_init(); + platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); omap_board_config = ldp_config; omap_board_config_size = ARRAY_SIZE(ldp_config); omap_serial_init(); + twl4030_mmc_init(mmc); } static void __init omap_ldp_map_io(void) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index baa79674e9d5..9e5ada01b5fa 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -38,7 +38,9 @@ #include <mach/common.h> #include <mach/gpmc.h> #include <mach/nand.h> +#include <mach/mux.h> +#include "mmc-twl4030.h" #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 @@ -103,6 +105,78 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct twl4030_hsmmc_info mmc[] = { + { + .mmc = 1, + .wires = 8, + .gpio_wp = 29, + }, + {} /* Terminator */ +}; + +static struct gpio_led gpio_leds[]; + +static int beagle_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ + + /* REVISIT: need ehci-omap hooks for external VBUS + * power switch and overcurrent detect + */ + + gpio_request(gpio + 1, "EHCI_nOC"); + gpio_direction_input(gpio + 1); + + /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); + + /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; + + return 0; +} + +static struct twl4030_gpio_platform_data beagle_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .use_leds = true, + .pullups = BIT(1), + .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) + | BIT(15) | BIT(16) | BIT(17), + .setup = beagle_twl_gpio_setup, +}; + +static struct twl4030_platform_data beagle_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .gpio = &beagle_gpio_data, +}; + +static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &beagle_twldata, + }, +}; + +static int __init omap3_beagle_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, + ARRAY_SIZE(beagle_i2c_boardinfo)); +#ifdef CONFIG_I2C2_OMAP_BEAGLE + omap_register_i2c_bus(2, 400, NULL, 0); +#endif + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + static void __init omap3_beagle_init_irq(void) { omap2_init_common_hw(); @@ -130,6 +204,11 @@ static struct gpio_led gpio_leds[] = { .default_trigger = "mmc0", .gpio = 149, }, + { + .name = "beagleboard::pmu_stat", + .gpio = -EINVAL, /* gets replaced */ + .active_low = true, + }, }; static struct gpio_led_platform_data gpio_led_info = { @@ -218,11 +297,22 @@ static void __init omap3beagle_flash_init(void) static void __init omap3_beagle_init(void) { + omap3_beagle_i2c_init(); platform_add_devices(omap3_beagle_devices, ARRAY_SIZE(omap3_beagle_devices)); omap_board_config = omap3_beagle_config; omap_board_config_size = ARRAY_SIZE(omap3_beagle_config); omap_serial_init(); + + omap_cfg_reg(AH8_34XX_GPIO29); + mmc[0].gpio_cd = gpio + 0; + twl4030_mmc_init(mmc); + + omap_cfg_reg(J25_34XX_GPIO170); + gpio_request(170, "DVI_nPD"); + /* REVISIT leave DVI powered down until it's needed ... */ + gpio_direction_output(170, true); + omap3beagle_flash_init(); } diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c new file mode 100644 index 000000000000..b3196107afdb --- /dev/null +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -0,0 +1,212 @@ +/* + * board-omap3pandora.c (Pandora Handheld Console) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> +#include <linux/i2c/twl4030.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/board.h> +#include <mach/common.h> +#include <mach/gpio.h> +#include <mach/hardware.h> +#include <mach/mcspi.h> + +#include "mmc-twl4030.h" + +#define OMAP3_PANDORA_TS_GPIO 94 + +static struct twl4030_hsmmc_info omap3pandora_mmc[] = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = 126, + .ext_clock = 0, + }, + { + .mmc = 2, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = 127, + .ext_clock = 1, + }, + {} /* Terminator */ +}; + +static struct omap_uart_config omap3pandora_uart_config __initdata = { + .enabled_uarts = (1 << 2), /* UART3 */ +}; + +static int omap3pandora_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + /* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */ + omap3pandora_mmc[0].gpio_cd = gpio + 0; + omap3pandora_mmc[1].gpio_cd = gpio + 1; + twl4030_mmc_init(omap3pandora_mmc); + + return 0; +} + +static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .setup = omap3pandora_twl_gpio_setup, +}; + +static struct twl4030_usb_data omap3pandora_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct twl4030_platform_data omap3pandora_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + .gpio = &omap3pandora_gpio_data, + .usb = &omap3pandora_usb_data, +}; + +static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("tps65950", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3pandora_twldata, + }, +}; + +static int __init omap3pandora_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, omap3pandora_i2c_boardinfo, + ARRAY_SIZE(omap3pandora_i2c_boardinfo)); + /* i2c2 pins are not connected */ + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + +static void __init omap3pandora_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); +} + +static void __init omap3pandora_ads7846_init(void) +{ + int gpio = OMAP3_PANDORA_TS_GPIO; + int ret; + + ret = gpio_request(gpio, "ads7846_pen_down"); + if (ret < 0) { + printk(KERN_ERR "Failed to request GPIO %d for " + "ads7846 pen down IRQ\n", gpio); + return; + } + + gpio_direction_input(gpio); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_PANDORA_TS_GPIO); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info omap3pandora_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_PANDORA_TS_GPIO), + .platform_data = &ads7846_config, + } +}; + +static struct platform_device omap3pandora_lcd_device = { + .name = "pandora_lcd", + .id = -1, +}; + +static struct omap_lcd_config omap3pandora_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel omap3pandora_config[] __initdata = { + { OMAP_TAG_UART, &omap3pandora_uart_config }, + { OMAP_TAG_LCD, &omap3pandora_lcd_config }, +}; + +static struct platform_device *omap3pandora_devices[] __initdata = { + &omap3pandora_lcd_device, +}; + +static void __init omap3pandora_init(void) +{ + omap3pandora_i2c_init(); + platform_add_devices(omap3pandora_devices, + ARRAY_SIZE(omap3pandora_devices)); + omap_board_config = omap3pandora_config; + omap_board_config_size = ARRAY_SIZE(omap3pandora_config); + omap_serial_init(); + spi_register_board_info(omap3pandora_spi_board_info, + ARRAY_SIZE(omap3pandora_spi_board_info)); + omap3pandora_ads7846_init(); +} + +static void __init omap3pandora_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3pandora_map_io, + .init_irq = omap3pandora_init_irq, + .init_machine = omap3pandora_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e09aa59a399c..82b3dc557c96 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -26,6 +26,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/platform_device.h> +#include <linux/i2c/twl4030.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -44,6 +45,8 @@ #include <mach/hardware.h> #include <mach/nand.h> +#include "mmc-twl4030.h" + #define NAND_BLOCK_SIZE SZ_128K #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 @@ -139,8 +142,31 @@ static struct omap_uart_config overo_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct twl4030_gpio_platform_data overo_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, +}; + +static struct twl4030_platform_data overo_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + .gpio = &overo_gpio_data, +}; + +static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &overo_twldata, + }, +}; + static int __init overo_i2c_init(void) { + omap_register_i2c_bus(1, 2600, overo_i2c_boardinfo, + ARRAY_SIZE(overo_i2c_boardinfo)); /* i2c2 pins are used for gpio */ omap_register_i2c_bus(3, 400, NULL, 0); return 0; @@ -171,6 +197,22 @@ static struct platform_device *overo_devices[] __initdata = { &overo_lcd_device, }; +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + { + .mmc = 2, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init overo_init(void) { overo_i2c_init(); @@ -178,6 +220,7 @@ static void __init overo_init(void) omap_board_config = overo_config; omap_board_config_size = ARRAY_SIZE(overo_config); omap_serial_init(); + twl4030_mmc_init(mmc); overo_flash_init(); if ((gpio_request(OVERO_GPIO_W2W_NRESET, diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 242a19d86ccd..ff6cd14d254d 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -2522,7 +2522,6 @@ static struct clk usbhs_ick = { static struct clk mmchs1_ick = { .name = "mmchs_ick", - .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2533,7 +2532,6 @@ static struct clk mmchs1_ick = { static struct clk mmchs1_fck = { .name = "mmchs_fck", - .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2544,7 +2542,7 @@ static struct clk mmchs1_fck = { static struct clk mmchs2_ick = { .name = "mmchs_ick", - .id = 2, + .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2555,7 +2553,7 @@ static struct clk mmchs2_ick = { static struct clk mmchs2_fck = { .name = "mmchs_fck", - .id = 2, + .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), @@ -2595,7 +2593,6 @@ static struct clk mdm_intc_ick = { static struct clk mmchsdb1_fck = { .name = "mmchsdb_fck", - .id = 1, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2606,7 +2603,7 @@ static struct clk mmchsdb1_fck = { static struct clk mmchsdb2_fck = { .name = "mmchsdb_fck", - .id = 2, + .id = 1, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 084e11082f80..31bb7010bd48 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -475,7 +475,7 @@ int __init omap2_clk_init(void) * Update this if there are further clock changes between ES2 * and production parts */ - if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) { + if (omap_rev() == OMAP3430_REV_ES1_0) { /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */ cpu_clkflg |= CLOCK_IN_OMAP3430ES1; } else { diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index c38a8a09692f..a826094d89b5 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1374,7 +1374,7 @@ static struct clk core_96m_fck = { static struct clk mmchs3_fck = { .name = "mmchs_fck", - .id = 3, + .id = 2, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, @@ -1385,7 +1385,7 @@ static struct clk mmchs3_fck = { static struct clk mmchs2_fck = { .name = "mmchs_fck", - .id = 2, + .id = 1, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, @@ -1406,7 +1406,6 @@ static struct clk mspro_fck = { static struct clk mmchs1_fck = { .name = "mmchs_fck", - .id = 1, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, @@ -1722,7 +1721,7 @@ static struct clk usbtll_ick = { static struct clk mmchs3_ick = { .name = "mmchs_ick", - .id = 3, + .id = 2, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, @@ -1774,7 +1773,7 @@ static struct clk des2_ick = { static struct clk mmchs2_ick = { .name = "mmchs_ick", - .id = 2, + .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, @@ -1785,7 +1784,6 @@ static struct clk mmchs2_ick = { static struct clk mmchs1_ick = { .name = "mmchs_ick", - .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, @@ -2280,8 +2278,8 @@ static struct clk wkup_32k_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio1_fck = { - .name = "gpio1_fck", +static struct clk gpio1_dbck = { + .name = "gpio1_dbck", .parent = &wkup_32k_fck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, @@ -2527,8 +2525,8 @@ static struct clk per_32k_alwon_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio6_fck = { - .name = "gpio6_fck", +static struct clk gpio6_dbck = { + .name = "gpio6_dbck", .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, @@ -2537,8 +2535,8 @@ static struct clk gpio6_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio5_fck = { - .name = "gpio5_fck", +static struct clk gpio5_dbck = { + .name = "gpio5_dbck", .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, @@ -2547,8 +2545,8 @@ static struct clk gpio5_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio4_fck = { - .name = "gpio4_fck", +static struct clk gpio4_dbck = { + .name = "gpio4_dbck", .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, @@ -2557,8 +2555,8 @@ static struct clk gpio4_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio3_fck = { - .name = "gpio3_fck", +static struct clk gpio3_dbck = { + .name = "gpio3_dbck", .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, @@ -2567,8 +2565,8 @@ static struct clk gpio3_fck = { .recalc = &followparent_recalc, }; -static struct clk gpio2_fck = { - .name = "gpio2_fck", +static struct clk gpio2_dbck = { + .name = "gpio2_dbck", .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, @@ -3170,7 +3168,7 @@ static struct clk *onchip_34xx_clks[] __initdata = { &usim_fck, &gpt1_fck, &wkup_32k_fck, - &gpio1_fck, + &gpio1_dbck, &wdt2_fck, &wkup_l4_ick, &usim_ick, @@ -3192,11 +3190,11 @@ static struct clk *onchip_34xx_clks[] __initdata = { &gpt8_fck, &gpt9_fck, &per_32k_alwon_fck, - &gpio6_fck, - &gpio5_fck, - &gpio4_fck, - &gpio3_fck, - &gpio2_fck, + &gpio6_dbck, + &gpio5_dbck, + &gpio4_dbck, + &gpio3_dbck, + &gpio2_dbck, &wdt3_fck, &per_l4_ick, &gpio6_ick, diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 90af2ac469aa..9d7216ff6c9f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -14,16 +14,19 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/clk.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/map.h> +#include <mach/control.h> #include <mach/tc.h> #include <mach/board.h> #include <mach/mux.h> #include <mach/gpio.h> #include <mach/eac.h> +#include <mach/mmc.h> #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) @@ -295,6 +298,171 @@ static void omap_init_sha1_md5(void) static inline void omap_init_sha1_md5(void) { } #endif +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_ARCH_OMAP3 + +#define MMCHS_SYSCONFIG 0x0010 +#define MMCHS_SYSCONFIG_SWRESET (1 << 1) +#define MMCHS_SYSSTATUS 0x0014 +#define MMCHS_SYSSTATUS_RESETDONE (1 << 0) + +static struct platform_device dummy_pdev = { + .dev = { + .bus = &platform_bus_type, + }, +}; + +/** + * omap_hsmmc_reset() - Full reset of each HS-MMC controller + * + * Ensure that each MMC controller is fully reset. Controllers + * left in an unknown state (by bootloader) may prevent retention + * or OFF-mode. This is especially important in cases where the + * MMC driver is not enabled, _or_ built as a module. + * + * In order for reset to work, interface, functional and debounce + * clocks must be enabled. The debounce clock comes from func_32k_clk + * and is not under SW control, so we only enable i- and f-clocks. + **/ +static void __init omap_hsmmc_reset(void) +{ + u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC : + OMAP24XX_NR_MMC; + + for (i = 0; i < nr_controllers; i++) { + u32 v, base = 0; + struct clk *iclk, *fclk; + struct device *dev = &dummy_pdev.dev; + + switch (i) { + case 0: + base = OMAP2_MMC1_BASE; + break; + case 1: + base = OMAP2_MMC2_BASE; + break; + case 2: + base = OMAP3_MMC3_BASE; + break; + } + + dummy_pdev.id = i; + iclk = clk_get(dev, "mmchs_ick"); + if (iclk && clk_enable(iclk)) + iclk = NULL; + + fclk = clk_get(dev, "mmchs_fck"); + if (fclk && clk_enable(fclk)) + fclk = NULL; + + if (!iclk || !fclk) { + printk(KERN_WARNING + "%s: Unable to enable clocks for MMC%d, " + "cannot reset.\n", __func__, i); + break; + } + + omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG); + v = omap_readl(base + MMCHS_SYSSTATUS); + while (!(omap_readl(base + MMCHS_SYSSTATUS) & + MMCHS_SYSSTATUS_RESETDONE)) + cpu_relax(); + + if (fclk) { + clk_disable(fclk); + clk_put(fclk); + } + if (iclk) { + clk_disable(iclk); + clk_put(iclk); + } + } +} +#else +static inline void omap_hsmmc_reset(void) {} +#endif + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ + defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) + +static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, + int controller_nr) +{ + if (cpu_is_omap2420() && controller_nr == 0) { + omap_cfg_reg(H18_24XX_MMC_CMD); + omap_cfg_reg(H15_24XX_MMC_CLKI); + omap_cfg_reg(G19_24XX_MMC_CLKO); + omap_cfg_reg(F20_24XX_MMC_DAT0); + omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); + omap_cfg_reg(G18_24XX_MMC_CMD_DIR); + if (mmc_controller->slots[0].wires == 4) { + omap_cfg_reg(H14_24XX_MMC_DAT1); + omap_cfg_reg(E19_24XX_MMC_DAT2); + omap_cfg_reg(D19_24XX_MMC_DAT3); + omap_cfg_reg(E20_24XX_MMC_DAT_DIR1); + omap_cfg_reg(F18_24XX_MMC_DAT_DIR2); + omap_cfg_reg(E18_24XX_MMC_DAT_DIR3); + } + + /* + * Use internal loop-back in MMC/SDIO Module Input Clock + * selection + */ + if (mmc_controller->slots[0].internal_clock) { + u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + v |= (1 << 24); + omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); + } + } +} + +void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers) +{ + int i; + + for (i = 0; i < nr_controllers; i++) { + unsigned long base, size; + unsigned int irq = 0; + + if (!mmc_data[i]) + continue; + + omap2_mmc_mux(mmc_data[i], i); + + switch (i) { + case 0: + base = OMAP2_MMC1_BASE; + irq = INT_24XX_MMC_IRQ; + break; + case 1: + base = OMAP2_MMC2_BASE; + irq = INT_24XX_MMC2_IRQ; + break; + case 2: + if (!cpu_is_omap34xx()) + return; + base = OMAP3_MMC3_BASE; + irq = INT_34XX_MMC3_IRQ; + break; + default: + continue; + } + + if (cpu_is_omap2420()) + size = OMAP2420_MMC_SIZE; + else + size = HSMMC_SIZE; + + omap_mmc_add(i, base, size, irq, mmc_data[i]); + }; +} + +#endif + +/*-------------------------------------------------------------------------*/ + #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) #define OMAP_HDQ_BASE 0x480B2000 @@ -334,6 +502,7 @@ static int __init omap2_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ + omap_hsmmc_reset(); omap_init_mbox(); omap_init_mcspi(); omap_hdq_init(); diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index bf45ff39a7b5..b0f8e7d62798 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -22,40 +22,15 @@ #include <mach/control.h> #include <mach/cpu.h> -static u32 class; -static void __iomem *tap_base; -static u16 tap_prod_id; - -#define OMAP_TAP_IDCODE 0x0204 -#define OMAP_TAP_DIE_ID_0 0x0218 -#define OMAP_TAP_DIE_ID_1 0x021C -#define OMAP_TAP_DIE_ID_2 0x0220 -#define OMAP_TAP_DIE_ID_3 0x0224 - -/* system_rev fields for OMAP2 processors: - * CPU id bits [31:16], - * CPU device type [15:12], (unprg,normal,POP) - * CPU revision [11:08] - * CPU class bits [07:00] - */ - -struct omap_id { - u16 hawkeye; /* Silicon type (Hawkeye id) */ - u8 dev; /* Device type from production_id reg */ - u32 type; /* combined type id copied to system_rev */ -}; +static struct omap_chip_id omap_chip; +static unsigned int omap_revision; -/* Register values to detect the OMAP version */ -static struct omap_id omap_ids[] __initdata = { - { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200000 }, - { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201000 }, - { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202000 }, - { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220000 }, - { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230000 }, - { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300000 }, -}; -static struct omap_chip_id omap_chip; +unsigned int omap_rev(void) +{ + return omap_revision; +} +EXPORT_SYMBOL(omap_rev); /** * omap_chip_is - test whether currently running OMAP matches a chip type @@ -70,135 +45,41 @@ int omap_chip_is(struct omap_chip_id oci) } EXPORT_SYMBOL(omap_chip_is); -static u32 __init read_tap_reg(int reg) -{ - unsigned int regval = 0; - u32 cpuid; - - /* Reading the IDCODE register on 3430 ES1 results in a - * data abort as the register is not exposed on the OCP - * Hence reading the Cortex Rev - */ - cpuid = read_cpuid(CPUID_ID); - - /* If the processor type is Cortex-A8 and the revision is 0x0 - * it means its Cortex r0p0 which is 3430 ES1 - */ - if ((((cpuid >> 4) & 0xFFF) == 0xC08) && ((cpuid & 0xF) == 0x0)) { - - if (reg == tap_prod_id) { - regval = 0x000F00F0; - goto out; - } - - switch (reg) { - case OMAP_TAP_IDCODE : regval = 0x0B7AE02F; break; - /* Making DevType as 0xF in ES1 to differ from ES2 */ - case OMAP_TAP_DIE_ID_0: regval = 0x01000000; break; - case OMAP_TAP_DIE_ID_1: regval = 0x1012d687; break; - case OMAP_TAP_DIE_ID_2: regval = 0x00000000; break; - case OMAP_TAP_DIE_ID_3: regval = 0x2d2c0000; break; - } - } else - regval = __raw_readl(tap_base + reg); - -out: - return regval; - -} +/*----------------------------------------------------------------------------*/ -/* - * _set_system_rev - set the system_rev global based on current OMAP chip type - * - * Set the system_rev global. This is primarily used by the cpu_is_omapxxxx() - * macros. - */ -static void __init _set_system_rev(u32 type, u8 rev) -{ - u32 i, ctrl_status; - - /* - * system_rev encoding is as follows - * system_rev & 0xff000000 -> Omap Class (24xx/34xx) - * system_rev & 0xfff00000 -> Omap Sub Class (242x/343x) - * system_rev & 0xffff0000 -> Omap type (2420/2422/2423/2430/3430) - * system_rev & 0x0000f000 -> Silicon revision (ES1, ES2 ) - * system_rev & 0x00000700 -> Device Type ( EMU/HS/GP/BAD ) - * system_rev & 0x000000c0 -> IDCODE revision[6:7] - * system_rev & 0x0000003f -> sys_boot[0:5] - */ - /* Embedding the ES revision info in type field */ - system_rev = type; - /* Also add IDCODE revision info only two lower bits */ - system_rev |= ((rev & 0x3) << 6); - - /* Add in the device type and sys_boot fields (see above) */ - if (cpu_is_omap24xx()) { - i = OMAP24XX_CONTROL_STATUS; - } else if (cpu_is_omap343x()) { - i = OMAP343X_CONTROL_STATUS; - } else { - printk(KERN_ERR "id: unknown CPU type\n"); - BUG(); - } - ctrl_status = omap_ctrl_readl(i); - system_rev |= (ctrl_status & (OMAP2_SYSBOOT_5_MASK | - OMAP2_SYSBOOT_4_MASK | - OMAP2_SYSBOOT_3_MASK | - OMAP2_SYSBOOT_2_MASK | - OMAP2_SYSBOOT_1_MASK | - OMAP2_SYSBOOT_0_MASK)); - system_rev |= (ctrl_status & OMAP2_DEVICETYPE_MASK); -} - - -/* - * _set_omap_chip - set the omap_chip global based on OMAP chip type - * - * Build the omap_chip bits. This variable is used by powerdomain and - * clockdomain code to indicate whether structures are applicable for - * the current OMAP chip type by ANDing it against a 'platform' bitfield - * in the structure. - */ -static void __init _set_omap_chip(void) -{ - if (cpu_is_omap343x()) { - - omap_chip.oc = CHIP_IS_OMAP3430; - if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) - omap_chip.oc |= CHIP_IS_OMAP3430ES1; - else if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) - omap_chip.oc |= CHIP_IS_OMAP3430ES2; - - } else if (cpu_is_omap243x()) { - - /* Currently only supports 2430ES2.1 and 2430-all */ - omap_chip.oc |= CHIP_IS_OMAP2430; - - } else if (cpu_is_omap242x()) { - - /* Currently only supports 2420ES2.1.1 and 2420-all */ - omap_chip.oc |= CHIP_IS_OMAP2420; +#define OMAP_TAP_IDCODE 0x0204 +#define OMAP_TAP_DIE_ID_0 0x0218 +#define OMAP_TAP_DIE_ID_1 0x021C +#define OMAP_TAP_DIE_ID_2 0x0220 +#define OMAP_TAP_DIE_ID_3 0x0224 - } else { +#define read_tap_reg(reg) __raw_readl(tap_base + (reg)) - /* Current CPU not supported by this code. */ - printk(KERN_WARNING "OMAP chip type code does not yet support " - "this CPU type.\n"); - WARN_ON(1); +struct omap_id { + u16 hawkeye; /* Silicon type (Hawkeye id) */ + u8 dev; /* Device type from production_id reg */ + u32 type; /* Combined type id copied to omap_revision */ +}; - } +/* Register values to detect the OMAP version */ +static struct omap_id omap_ids[] __initdata = { + { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200024 }, + { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201024 }, + { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202024 }, + { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220024 }, + { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230024 }, + { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300024 }, +}; -} +static void __iomem *tap_base; +static u16 tap_prod_id; -void __init omap2_check_revision(void) +void __init omap24xx_check_revision(void) { int i, j; - u32 idcode; - u32 prod_id; + u32 idcode, prod_id; u16 hawkeye; - u8 dev_type; - u8 rev; + u8 dev_type, rev; idcode = read_tap_reg(OMAP_TAP_IDCODE); prod_id = read_tap_reg(tap_prod_id); @@ -220,18 +101,6 @@ void __init omap2_check_revision(void) pr_debug("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n", prod_id, dev_type); - /* - * Detection for 34xx ES2.0 and above can be done with just - * hawkeye and rev. See TRM 1.5.2 Device Identification. - * Note that rev cannot be used directly as ES1.0 uses value 0. - */ - if (hawkeye == 0xb7ae) { - system_rev = 0x34300000 | ((1 + rev) << 12); - pr_info("OMAP%04x ES2.%i\n", system_rev >> 16, rev); - _set_omap_chip(); - return; - } - /* Check hawkeye ids */ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { if (hawkeye == omap_ids[i].hawkeye) @@ -255,23 +124,115 @@ void __init omap2_check_revision(void) j = i; } - _set_system_rev(omap_ids[j].type, rev); + pr_info("OMAP%04x", omap_rev() >> 16); + if ((omap_rev() >> 8) & 0x0f) + pr_info("ES%x", (omap_rev() >> 12) & 0xf); + pr_info("\n"); +} - _set_omap_chip(); +void __init omap34xx_check_revision(void) +{ + u32 cpuid, idcode; + u16 hawkeye; + u8 rev; + char *rev_name = "ES1.0"; - pr_info("OMAP%04x", system_rev >> 16); - if ((system_rev >> 8) & 0x0f) - pr_info("ES%x", (system_rev >> 12) & 0xf); - pr_info("\n"); + /* + * We cannot access revision registers on ES1.0. + * If the processor type is Cortex-A8 and the revision is 0x0 + * it means its Cortex r0p0 which is 3430 ES1.0. + */ + cpuid = read_cpuid(CPUID_ID); + if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) { + omap_revision = OMAP3430_REV_ES1_0; + goto out; + } + /* + * Detection for 34xx ES2.0 and above can be done with just + * hawkeye and rev. See TRM 1.5.2 Device Identification. + * Note that rev does not map directly to our defined processor + * revision numbers as ES1.0 uses value 0. + */ + idcode = read_tap_reg(OMAP_TAP_IDCODE); + hawkeye = (idcode >> 12) & 0xffff; + rev = (idcode >> 28) & 0xff; + + if (hawkeye == 0xb7ae) { + switch (rev) { + case 0: + omap_revision = OMAP3430_REV_ES2_0; + rev_name = "ES2.0"; + break; + case 2: + omap_revision = OMAP3430_REV_ES2_1; + rev_name = "ES2.1"; + break; + case 3: + omap_revision = OMAP3430_REV_ES3_0; + rev_name = "ES3.0"; + break; + default: + /* Use the latest known revision as default */ + omap_revision = OMAP3430_REV_ES3_0; + rev_name = "Unknown revision\n"; + } + } + +out: + pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name); } +/* + * Try to detect the exact revision of the omap we're running on + */ +void __init omap2_check_revision(void) +{ + /* + * At this point we have an idea about the processor revision set + * earlier with omap2_set_globals_tap(). + */ + if (cpu_is_omap24xx()) + omap24xx_check_revision(); + else if (cpu_is_omap34xx()) + omap34xx_check_revision(); + else + pr_err("OMAP revision unknown, please fix!\n"); + + /* + * OK, now we know the exact revision. Initialize omap_chip bits + * for powerdowmain and clockdomain code. + */ + if (cpu_is_omap243x()) { + /* Currently only supports 2430ES2.1 and 2430-all */ + omap_chip.oc |= CHIP_IS_OMAP2430; + } else if (cpu_is_omap242x()) { + /* Currently only supports 2420ES2.1.1 and 2420-all */ + omap_chip.oc |= CHIP_IS_OMAP2420; + } else if (cpu_is_omap343x()) { + omap_chip.oc = CHIP_IS_OMAP3430; + if (omap_rev() == OMAP3430_REV_ES1_0) + omap_chip.oc |= CHIP_IS_OMAP3430ES1; + else if (omap_rev() > OMAP3430_REV_ES1_0) + omap_chip.oc |= CHIP_IS_OMAP3430ES2; + } else { + pr_err("Uninitialized omap_chip, please fix!\n"); + } +} + +/* + * Set up things for map_io and processor detection later on. Gets called + * pretty much first thing from board init. For multi-omap, this gets + * cpu_is_omapxxxx() working accurately enough for map_io. Then we'll try to + * detect the exact revision later on in omap2_detect_revision() once map_io + * is done. + */ void __init omap2_set_globals_tap(struct omap_globals *omap2_globals) { - class = omap2_globals->class; + omap_revision = omap2_globals->class; tap_base = omap2_globals->tap; - if (class == 0x3430) + if (cpu_is_omap34xx()) tap_prod_id = 0x0210; else tap_prod_id = 0x0208; diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index c40fc378a251..636e2821af7d 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -23,6 +23,7 @@ #define INTC_REVISION 0x0000 #define INTC_SYSCONFIG 0x0010 #define INTC_SYSSTATUS 0x0014 +#define INTC_SIR 0x0040 #define INTC_CONTROL 0x0048 #define INTC_MIR_CLEAR0 0x0088 #define INTC_MIR_SET0 0x008c @@ -60,6 +61,30 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) return __raw_readl(bank->base_reg + reg); } +static int previous_irq; + +/* + * On 34xx we can get occasional spurious interrupts if the ack from + * an interrupt handler does not get posted before we unmask. Warn about + * the interrupt handlers that need to flush posted writes. + */ +static int omap_check_spurious(unsigned int irq) +{ + u32 sir, spurious; + + sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR); + spurious = sir >> 6; + + if (spurious > 1) { + printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush " + "posted write for irq %i\n", + irq, sir, previous_irq); + return spurious; + } + + return 0; +} + /* XXX: FIQ and additional INTC support (only MPU at the moment) */ static void omap_ack_irq(unsigned int irq) { @@ -70,6 +95,20 @@ static void omap_mask_irq(unsigned int irq) { int offset = irq & (~(IRQ_BITS_PER_REG - 1)); + if (cpu_is_omap34xx()) { + int spurious = 0; + + /* + * INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because + * it is the highest irq number? + */ + if (irq == INT_34XX_GPT12_IRQ) + spurious = omap_check_spurious(irq); + + if (!spurious) + previous_irq = irq; + } + irq &= (IRQ_BITS_PER_REG - 1); intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset); diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c new file mode 100644 index 000000000000..437f52073f6e --- /dev/null +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -0,0 +1,408 @@ +/* + * linux/arch/arm/mach-omap2/mmc-twl4030.c + * + * Copyright (C) 2007-2008 Texas Instruments + * Copyright (C) 2008 Nokia Corporation + * Author: Texas Instruments + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/hardware.h> +#include <mach/control.h> +#include <mach/mmc.h> +#include <mach/board.h> + +#include "mmc-twl4030.h" + +#if defined(CONFIG_TWL4030_CORE) && \ + (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) + +#define LDO_CLR 0x00 +#define VSEL_S2_CLR 0x40 + +#define VMMC1_DEV_GRP 0x27 +#define VMMC1_CLR 0x00 +#define VMMC1_315V 0x03 +#define VMMC1_300V 0x02 +#define VMMC1_285V 0x01 +#define VMMC1_185V 0x00 +#define VMMC1_DEDICATED 0x2A + +#define VMMC2_DEV_GRP 0x2B +#define VMMC2_CLR 0x40 +#define VMMC2_315V 0x0c +#define VMMC2_300V 0x0b +#define VMMC2_285V 0x0a +#define VMMC2_260V 0x08 +#define VMMC2_185V 0x06 +#define VMMC2_DEDICATED 0x2E + +#define VMMC_DEV_GRP_P1 0x20 + +static u16 control_pbias_offset; +static u16 control_devconf1_offset; + +#define HSMMC_NAME_LEN 9 + +static struct twl_mmc_controller { + struct omap_mmc_platform_data *mmc; + u8 twl_vmmc_dev_grp; + u8 twl_mmc_dedicated; + char name[HSMMC_NAME_LEN]; +} hsmmc[] = { + { + .twl_vmmc_dev_grp = VMMC1_DEV_GRP, + .twl_mmc_dedicated = VMMC1_DEDICATED, + }, + { + .twl_vmmc_dev_grp = VMMC2_DEV_GRP, + .twl_mmc_dedicated = VMMC2_DEDICATED, + }, +}; + +static int twl_mmc_card_detect(int irq) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { + struct omap_mmc_platform_data *mmc; + + mmc = hsmmc[i].mmc; + if (!mmc) + continue; + if (irq != mmc->slots[0].card_detect_irq) + continue; + + /* NOTE: assumes card detect signal is active-low */ + return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); + } + return -ENOSYS; +} + +static int twl_mmc_get_ro(struct device *dev, int slot) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + /* NOTE: assumes write protect signal is active-high */ + return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); +} + +/* + * MMC Slot Initialization. + */ +static int twl_mmc_late_init(struct device *dev) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + int ret = 0; + int i; + + ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); + if (ret) + goto done; + ret = gpio_direction_input(mmc->slots[0].switch_pin); + if (ret) + goto err; + + for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { + if (hsmmc[i].name == mmc->slots[0].name) { + hsmmc[i].mmc = mmc; + break; + } + } + + return 0; + +err: + gpio_free(mmc->slots[0].switch_pin); +done: + mmc->slots[0].card_detect_irq = 0; + mmc->slots[0].card_detect = NULL; + + dev_err(dev, "err %d configuring card detect\n", ret); + return ret; +} + +static void twl_mmc_cleanup(struct device *dev) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + gpio_free(mmc->slots[0].switch_pin); +} + +#ifdef CONFIG_PM + +static int twl_mmc_suspend(struct device *dev, int slot) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + disable_irq(mmc->slots[0].card_detect_irq); + return 0; +} + +static int twl_mmc_resume(struct device *dev, int slot) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + enable_irq(mmc->slots[0].card_detect_irq); + return 0; +} + +#else +#define twl_mmc_suspend NULL +#define twl_mmc_resume NULL +#endif + +/* + * Sets the MMC voltage in twl4030 + */ +static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) +{ + int ret; + u8 vmmc, dev_grp_val; + + switch (1 << vdd) { + case MMC_VDD_35_36: + case MMC_VDD_34_35: + case MMC_VDD_33_34: + case MMC_VDD_32_33: + case MMC_VDD_31_32: + case MMC_VDD_30_31: + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + vmmc = VMMC1_315V; + else + vmmc = VMMC2_315V; + break; + case MMC_VDD_29_30: + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + vmmc = VMMC1_315V; + else + vmmc = VMMC2_300V; + break; + case MMC_VDD_27_28: + case MMC_VDD_26_27: + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + vmmc = VMMC1_285V; + else + vmmc = VMMC2_285V; + break; + case MMC_VDD_25_26: + case MMC_VDD_24_25: + case MMC_VDD_23_24: + case MMC_VDD_22_23: + case MMC_VDD_21_22: + case MMC_VDD_20_21: + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + vmmc = VMMC1_285V; + else + vmmc = VMMC2_260V; + break; + case MMC_VDD_165_195: + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + vmmc = VMMC1_185V; + else + vmmc = VMMC2_185V; + break; + default: + vmmc = 0; + break; + } + + if (vmmc) + dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ + else + dev_grp_val = LDO_CLR; /* Power down */ + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + dev_grp_val, c->twl_vmmc_dev_grp); + if (ret) + return ret; + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + vmmc, c->twl_mmc_dedicated); + + return ret; +} + +static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + u32 reg; + int ret = 0; + struct twl_mmc_controller *c = &hsmmc[0]; + struct omap_mmc_platform_data *mmc = dev->platform_data; + + if (power_on) { + if (cpu_is_omap2430()) { + reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); + if ((1 << vdd) >= MMC_VDD_30_31) + reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE; + else + reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE; + omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); + } + + if (mmc->slots[0].internal_clock) { + reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + reg |= OMAP2_MMCSDIO1ADPCLKISEL; + omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); + } + + reg = omap_ctrl_readl(control_pbias_offset); + reg |= OMAP2_PBIASSPEEDCTRL0; + reg &= ~OMAP2_PBIASLITEPWRDNZ0; + omap_ctrl_writel(reg, control_pbias_offset); + + ret = twl_mmc_set_voltage(c, vdd); + + /* 100ms delay required for PBIAS configuration */ + msleep(100); + reg = omap_ctrl_readl(control_pbias_offset); + reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); + if ((1 << vdd) <= MMC_VDD_165_195) + reg &= ~OMAP2_PBIASLITEVMODE0; + else + reg |= OMAP2_PBIASLITEVMODE0; + omap_ctrl_writel(reg, control_pbias_offset); + } else { + reg = omap_ctrl_readl(control_pbias_offset); + reg &= ~OMAP2_PBIASLITEPWRDNZ0; + omap_ctrl_writel(reg, control_pbias_offset); + + ret = twl_mmc_set_voltage(c, 0); + + /* 100ms delay required for PBIAS configuration */ + msleep(100); + reg = omap_ctrl_readl(control_pbias_offset); + reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | + OMAP2_PBIASLITEVMODE0); + omap_ctrl_writel(reg, control_pbias_offset); + } + + return ret; +} + +static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd) +{ + int ret; + struct twl_mmc_controller *c = &hsmmc[1]; + struct omap_mmc_platform_data *mmc = dev->platform_data; + + if (power_on) { + if (mmc->slots[0].internal_clock) { + u32 reg; + + reg = omap_ctrl_readl(control_devconf1_offset); + reg |= OMAP2_MMCSDIO2ADPCLKISEL; + omap_ctrl_writel(reg, control_devconf1_offset); + } + ret = twl_mmc_set_voltage(c, vdd); + } else { + ret = twl_mmc_set_voltage(c, 0); + } + + return ret; +} + +static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; + +void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) +{ + struct twl4030_hsmmc_info *c; + int nr_hsmmc = ARRAY_SIZE(hsmmc_data); + + if (cpu_is_omap2430()) { + control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; + control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; + nr_hsmmc = 2; + } else { + control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; + control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; + } + + for (c = controllers; c->mmc; c++) { + struct twl_mmc_controller *twl = hsmmc + c->mmc - 1; + struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; + + if (!c->mmc || c->mmc > nr_hsmmc) { + pr_debug("MMC%d: no such controller\n", c->mmc); + continue; + } + if (mmc) { + pr_debug("MMC%d: already configured\n", c->mmc); + continue; + } + + mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + if (!mmc) { + pr_err("Cannot allocate memory for mmc device!\n"); + return; + } + + sprintf(twl->name, "mmc%islot%i", c->mmc, 1); + mmc->slots[0].name = twl->name; + mmc->nr_slots = 1; + mmc->slots[0].ocr_mask = MMC_VDD_165_195 | + MMC_VDD_26_27 | MMC_VDD_27_28 | + MMC_VDD_29_30 | + MMC_VDD_30_31 | MMC_VDD_31_32; + mmc->slots[0].wires = c->wires; + mmc->slots[0].internal_clock = !c->ext_clock; + mmc->dma_mask = 0xffffffff; + + /* note: twl4030 card detect GPIOs normally switch VMMCx ... */ + if (gpio_is_valid(c->gpio_cd)) { + mmc->init = twl_mmc_late_init; + mmc->cleanup = twl_mmc_cleanup; + mmc->suspend = twl_mmc_suspend; + mmc->resume = twl_mmc_resume; + + mmc->slots[0].switch_pin = c->gpio_cd; + mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); + mmc->slots[0].card_detect = twl_mmc_card_detect; + } else + mmc->slots[0].switch_pin = -EINVAL; + + /* write protect normally uses an OMAP gpio */ + if (gpio_is_valid(c->gpio_wp)) { + gpio_request(c->gpio_wp, "mmc_wp"); + gpio_direction_input(c->gpio_wp); + + mmc->slots[0].gpio_wp = c->gpio_wp; + mmc->slots[0].get_ro = twl_mmc_get_ro; + } else + mmc->slots[0].gpio_wp = -EINVAL; + + /* NOTE: we assume OMAP's MMC1 and MMC2 use + * the TWL4030's VMMC1 and VMMC2, respectively; + * and that OMAP's MMC3 isn't used. + */ + + switch (c->mmc) { + case 1: + mmc->slots[0].set_power = twl_mmc1_set_power; + break; + case 2: + mmc->slots[0].set_power = twl_mmc2_set_power; + break; + default: + pr_err("MMC%d configuration not supported!\n", c->mmc); + continue; + } + hsmmc_data[c->mmc - 1] = mmc; + } + + omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); +} + +#endif diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h new file mode 100644 index 000000000000..e1c8076400ca --- /dev/null +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -0,0 +1,29 @@ +/* + * MMC definitions for OMAP2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +struct twl4030_hsmmc_info { + u8 mmc; /* controller 1/2/3 */ + u8 wires; /* 1/4/8 wires */ + int gpio_cd; /* or -EINVAL */ + int gpio_wp; /* or -EINVAL */ + int ext_clock:1; /* use external pin for input clock */ +}; + +#if defined(CONFIG_TWL4030_CORE) && \ + (defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ + defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) + +void twl4030_mmc_init(struct twl4030_hsmmc_info *); + +#else + +static inline void twl4030_mmc_init(struct twl4030_hsmmc_info *info) +{ +} + +#endif diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index b1393673d95d..dacb41f130c0 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -203,6 +203,15 @@ MUX_CFG_24XX("AE9_2430_USB0HS_NXT", 0x13D, 0, 0, 0, 1) MUX_CFG_24XX("AC7_2430_USB0HS_DATA7", 0x13E, 0, 0, 0, 1) /* 2430 McBSP */ +MUX_CFG_24XX("AD6_2430_MCBSP_CLKS", 0x011E, 0, 0, 0, 1) + +MUX_CFG_24XX("AB2_2430_MCBSP1_CLKR", 0x011A, 0, 0, 0, 1) +MUX_CFG_24XX("AD5_2430_MCBSP1_FSR", 0x011B, 0, 0, 0, 1) +MUX_CFG_24XX("AA1_2430_MCBSP1_DX", 0x011C, 0, 0, 0, 1) +MUX_CFG_24XX("AF3_2430_MCBSP1_DR", 0x011D, 0, 0, 0, 1) +MUX_CFG_24XX("AB3_2430_MCBSP1_FSX", 0x011F, 0, 0, 0, 1) +MUX_CFG_24XX("Y9_2430_MCBSP1_CLKX", 0x0120, 0, 0, 0, 1) + MUX_CFG_24XX("AC10_2430_MCBSP2_FSX", 0x012E, 1, 0, 0, 1) MUX_CFG_24XX("AD16_2430_MCBSP2_CLX", 0x012F, 1, 0, 0, 1) MUX_CFG_24XX("AE13_2430_MCBSP2_DX", 0x0130, 1, 0, 0, 1) @@ -211,6 +220,31 @@ MUX_CFG_24XX("AC10_2430_MCBSP2_FSX_OFF",0x012E, 0, 0, 0, 1) MUX_CFG_24XX("AD16_2430_MCBSP2_CLX_OFF",0x012F, 0, 0, 0, 1) MUX_CFG_24XX("AE13_2430_MCBSP2_DX_OFF", 0x0130, 0, 0, 0, 1) MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF", 0x0131, 0, 0, 0, 1) + +MUX_CFG_24XX("AC9_2430_MCBSP3_CLKX", 0x0103, 0, 0, 0, 1) +MUX_CFG_24XX("AE4_2430_MCBSP3_FSX", 0x0104, 0, 0, 0, 1) +MUX_CFG_24XX("AE2_2430_MCBSP3_DR", 0x0105, 0, 0, 0, 1) +MUX_CFG_24XX("AF4_2430_MCBSP3_DX", 0x0106, 0, 0, 0, 1) + +MUX_CFG_24XX("N3_2430_MCBSP4_CLKX", 0x010B, 1, 0, 0, 1) +MUX_CFG_24XX("AD23_2430_MCBSP4_DR", 0x010C, 1, 0, 0, 1) +MUX_CFG_24XX("AB25_2430_MCBSP4_DX", 0x010D, 1, 0, 0, 1) +MUX_CFG_24XX("AC25_2430_MCBSP4_FSX", 0x010E, 1, 0, 0, 1) + +MUX_CFG_24XX("AE16_2430_MCBSP5_CLKX", 0x00ED, 1, 0, 0, 1) +MUX_CFG_24XX("AF12_2430_MCBSP5_FSX", 0x00ED, 1, 0, 0, 1) +MUX_CFG_24XX("K7_2430_MCBSP5_DX", 0x00EF, 1, 0, 0, 1) +MUX_CFG_24XX("M1_2430_MCBSP5_DR", 0x00F0, 1, 0, 0, 1) + +/* 2430 MCSPI1 */ +MUX_CFG_24XX("Y18_2430_MCSPI1_CLK", 0x010F, 0, 0, 0, 1) +MUX_CFG_24XX("AD15_2430_MCSPI1_SIMO", 0x0110, 0, 0, 0, 1) +MUX_CFG_24XX("AE17_2430_MCSPI1_SOMI", 0x0111, 0, 0, 0, 1) +MUX_CFG_24XX("U1_2430_MCSPI1_CS0", 0x0112, 0, 0, 0, 1) + +/* Touchscreen GPIO */ +MUX_CFG_24XX("AF19_2430_GPIO_85", 0x0113, 3, 0, 0, 1) + }; #define OMAP24XX_PINS_SZ ARRAY_SIZE(omap24xx_pins) @@ -417,6 +451,14 @@ MUX_CFG_34XX("AD2_3430_USB3FS_PHY_MM3_TXDAT", 0x188, MUX_CFG_34XX("AC1_3430_USB3FS_PHY_MM3_TXEN_N", 0x18a, OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + +/* 34XX GPIO - bidirectional, unless the name has an "_OUT" suffix. + * No internal pullup/pulldown without "_UP" or "_DOWN" suffix. + */ +MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) }; #define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins) @@ -452,7 +494,7 @@ static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 r #endif #ifdef CONFIG_ARCH_OMAP24XX -int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg) +static int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg) { static DEFINE_SPINLOCK(mux_spin_lock); unsigned long flags; diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 10ef464d6be7..15e509013def 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -12,11 +12,11 @@ #include <linux/errno.h> #include <linux/delay.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <linux/usb/musb.h> #include <mach/gpmc.h> -#include <mach/gpio.h> #include <mach/mux.h> @@ -292,12 +292,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, ); /* IRQ */ - status = omap_request_gpio(irq); + status = gpio_request(irq, "TUSB6010 irq"); if (status < 0) { printk(error, 3, status); return status; } - omap_set_gpio_direction(irq, 1); + gpio_direction_input(irq); tusb_resources[2].start = irq + IH_GPIO_BASE; /* set up memory timings ... can speed them up later */ diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index 3d4a1bc12355..edc38e2c856f 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o +obj-y += common.o addr-map.o pci.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 437065c25c9c..0a623379789f 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -72,6 +72,7 @@ void __init orion5x_map_io(void) ****************************************************************************/ static struct orion_ehci_data orion5x_ehci_data = { .dram = &orion5x_mbus_dram_info, + .phy_version = EHCI_PHY_ORION, }; static u64 ehci_dmamask = 0xffffffffUL; diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index a000c7c6ee96..798b9a5e3da9 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -51,13 +51,6 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); -/* - * Valid GPIO pins according to MPP setup, used by machine-setup. - * (/mach-orion/gpio.c). - */ -void orion5x_gpio_set_valid(unsigned pin, int valid); -void gpio_display(void); /* debug */ - struct machine_desc; struct meminfo; struct tag; diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 3e66098340a5..0722d6510df1 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -21,6 +21,7 @@ #include <linux/gpio_keys.h> #include <linux/input.h> #include <linux/i2c.h> +#include <linux/ata_platform.h> #include <asm/mach-types.h> #include <asm/gpio.h> #include <asm/mach/arch.h> @@ -64,9 +65,21 @@ static struct hw_pci dns323_pci __initdata = { .map_irq = dns323_pci_map_irq, }; +static int __init dns323_dev_id(void) +{ + u32 dev, rev; + + orion5x_pcie_id(&dev, &rev); + + return dev; +} + static int __init dns323_pci_init(void) { - if (machine_is_dns323()) + /* The 5182 doesn't really use it's PCI bus, and initialising PCI + * gets in the way of initialising the SATA controller. + */ + if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID) pci_common_init(&dns323_pci); return 0; @@ -75,14 +88,6 @@ static int __init dns323_pci_init(void) subsys_initcall(dns323_pci_init); /**************************************************************************** - * Ethernet - */ - -static struct mv643xx_eth_platform_data dns323_eth_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR(8), -}; - -/**************************************************************************** * 8MiB NOR flash (Spansion S29GL064M90TFIR4) * * Layout as used by D-Link: @@ -143,6 +148,90 @@ static struct platform_device dns323_nor_flash = { }; /**************************************************************************** + * Ethernet + */ + +static struct mv643xx_eth_platform_data dns323_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these + * functions be kept somewhere? + */ +static int __init dns323_parse_hex_nibble(char n) +{ + if (n >= '0' && n <= '9') + return n - '0'; + + if (n >= 'A' && n <= 'F') + return n - 'A' + 10; + + if (n >= 'a' && n <= 'f') + return n - 'a' + 10; + + return -1; +} + +static int __init dns323_parse_hex_byte(const char *b) +{ + int hi; + int lo; + + hi = dns323_parse_hex_nibble(b[0]); + lo = dns323_parse_hex_nibble(b[1]); + + if (hi < 0 || lo < 0) + return -1; + + return (hi << 4) | lo; +} + +static int __init dns323_read_mac_addr(void) +{ + u_int8_t addr[6]; + int i; + char *mac_page; + + /* MAC address is stored as a regular ol' string in /dev/mtdblock4 + * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80). + */ + mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024); + if (!mac_page) + return -ENOMEM; + + /* Sanity check the string we're looking at */ + for (i = 0; i < 5; i++) { + if (*(mac_page + (i * 3) + 2) != ':') { + goto error_fail; + } + } + + for (i = 0; i < 6; i++) { + int byte; + + byte = dns323_parse_hex_byte(mac_page + (i * 3)); + if (byte < 0) { + goto error_fail; + } + + addr[i] = byte; + } + + iounmap(mac_page); + printk("DNS323: Found ethernet MAC address: "); + for (i = 0; i < 6; i++) + printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); + + memcpy(dns323_eth_data.mac_addr, addr, 6); + + return 0; + +error_fail: + iounmap(mac_page); + return -EINVAL; +} + +/**************************************************************************** * GPIO LEDs (simple - doesn't use hardware blinking support) */ @@ -207,10 +296,17 @@ static struct platform_device dns323_button_device = { }, }; +/***************************************************************************** + * SATA + */ +static struct mv_sata_platform_data dns323_sata_data = { + .n_ports = 2, +}; + /**************************************************************************** * General Setup */ -static struct orion5x_mpp_mode dns323_mpp_modes[] __initdata = { +static struct orion5x_mpp_mode dns323_mv88f5181_mpp_modes[] __initdata = { { 0, MPP_PCIE_RST_OUTn }, { 1, MPP_GPIO }, /* right amber LED (sata ch0) */ { 2, MPP_GPIO }, /* left amber LED (sata ch1) */ @@ -234,6 +330,30 @@ static struct orion5x_mpp_mode dns323_mpp_modes[] __initdata = { { -1 }, }; +static struct orion5x_mpp_mode dns323_mv88f5182_mpp_modes[] __initdata = { + { 0, MPP_UNUSED }, + { 1, MPP_GPIO }, /* right amber LED (sata ch0) */ + { 2, MPP_GPIO }, /* left amber LED (sata ch1) */ + { 3, MPP_UNUSED }, + { 4, MPP_GPIO }, /* power button LED */ + { 5, MPP_GPIO }, /* power button LED */ + { 6, MPP_GPIO }, /* GMT G751-2f overtemp */ + { 7, MPP_GPIO }, /* M41T80 nIRQ/OUT/SQW */ + { 8, MPP_GPIO }, /* triggers power off */ + { 9, MPP_GPIO }, /* power button switch */ + { 10, MPP_GPIO }, /* reset button switch */ + { 11, MPP_UNUSED }, + { 12, MPP_SATA_LED }, + { 13, MPP_SATA_LED }, + { 14, MPP_SATA_LED }, + { 15, MPP_SATA_LED }, + { 16, MPP_UNUSED }, + { 17, MPP_UNUSED }, + { 18, MPP_UNUSED }, + { 19, MPP_UNUSED }, + { -1 }, +}; + /* * On the DNS-323 the following devices are attached via I2C: * @@ -264,16 +384,15 @@ static void __init dns323_init(void) /* Setup basic Orion functions. Need to be called early. */ orion5x_init(); - orion5x_mpp_conf(dns323_mpp_modes); - writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */ - - /* - * Configure peripherals. + /* Just to be tricky, the 5182 has a completely different + * set of MPP modes to the 5181. */ - orion5x_ehci0_init(); - orion5x_eth_init(&dns323_eth_data); - orion5x_i2c_init(); - orion5x_uart0_init(); + if (dns323_dev_id() == MV88F5182_DEV_ID) + orion5x_mpp_conf(dns323_mv88f5182_mpp_modes); + else { + orion5x_mpp_conf(dns323_mv88f5181_mpp_modes); + writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */ + } /* setup flash mapping * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 @@ -288,6 +407,23 @@ static void __init dns323_init(void) i2c_register_board_info(0, dns323_i2c_devices, ARRAY_SIZE(dns323_i2c_devices)); + /* + * Configure peripherals. + */ + if (dns323_read_mac_addr() < 0) + printk("DNS323: Failed to read MAC address\n"); + + orion5x_ehci0_init(); + orion5x_eth_init(&dns323_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + + /* The 5182 has it's SATA controller on-chip, and needs it's own little + * init routine. + */ + if (dns323_dev_id() == MV88F5182_DEV_ID) + orion5x_sata_init(&dns323_sata_data); + /* register dns323 specific power-off method */ if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) diff --git a/arch/arm/mach-orion5x/gpio.c b/arch/arm/mach-orion5x/gpio.c deleted file mode 100644 index f99d08811e5a..000000000000 --- a/arch/arm/mach-orion5x/gpio.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * arch/arm/mach-orion5x/gpio.c - * - * GPIO functions for Marvell Orion System On Chip - * - * Maintainer: Tzachi Perelstein <tzachi@marvell.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <asm/gpio.h> -#include <mach/orion5x.h> -#include "common.h" - -static DEFINE_SPINLOCK(gpio_lock); -static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; -static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ - -void __init orion5x_gpio_set_valid(unsigned pin, int valid) -{ - if (valid) - __set_bit(pin, gpio_valid); - else - __clear_bit(pin, gpio_valid); -} - -/* - * GENERIC_GPIO primitives - */ -int gpio_direction_input(unsigned pin) -{ - unsigned long flags; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - /* - * Some callers might have not used the gpio_request(), - * so flag this pin as requested now. - */ - if (!gpio_label[pin]) - gpio_label[pin] = "?"; - - orion5x_setbits(GPIO_IO_CONF, 1 << pin); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} -EXPORT_SYMBOL(gpio_direction_input); - -int gpio_direction_output(unsigned pin, int value) -{ - unsigned long flags; - int mask; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - /* - * Some callers might have not used the gpio_request(), - * so flag this pin as requested now. - */ - if (!gpio_label[pin]) - gpio_label[pin] = "?"; - - mask = 1 << pin; - orion5x_clrbits(GPIO_BLINK_EN, mask); - if (value) - orion5x_setbits(GPIO_OUT, mask); - else - orion5x_clrbits(GPIO_OUT, mask); - orion5x_clrbits(GPIO_IO_CONF, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} -EXPORT_SYMBOL(gpio_direction_output); - -int gpio_get_value(unsigned pin) -{ - int val, mask = 1 << pin; - - if (readl(GPIO_IO_CONF) & mask) - val = readl(GPIO_DATA_IN) ^ readl(GPIO_IN_POL); - else - val = readl(GPIO_OUT); - - return val & mask; -} -EXPORT_SYMBOL(gpio_get_value); - -void gpio_set_value(unsigned pin, int value) -{ - unsigned long flags; - int mask = 1 << pin; - - spin_lock_irqsave(&gpio_lock, flags); - - orion5x_clrbits(GPIO_BLINK_EN, mask); - if (value) - orion5x_setbits(GPIO_OUT, mask); - else - orion5x_clrbits(GPIO_OUT, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(gpio_set_value); - -void orion5x_gpio_set_blink(unsigned pin, int blink) -{ - unsigned long flags; - int mask = 1 << pin; - - spin_lock_irqsave(&gpio_lock, flags); - - orion5x_clrbits(GPIO_OUT, mask); - if (blink) - orion5x_setbits(GPIO_BLINK_EN, mask); - else - orion5x_clrbits(GPIO_BLINK_EN, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(orion5x_gpio_set_blink); - -int gpio_request(unsigned pin, const char *label) -{ - int ret = 0; - unsigned long flags; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - if (gpio_label[pin]) { - pr_debug("%s: GPIO %d already used as %s\n", - __func__, pin, gpio_label[pin]); - ret = -EBUSY; - } else - gpio_label[pin] = label ? label : "?"; - - spin_unlock_irqrestore(&gpio_lock, flags); - return ret; -} -EXPORT_SYMBOL(gpio_request); - -void gpio_free(unsigned pin) -{ - might_sleep(); - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return; - } - - if (!gpio_label[pin]) - pr_warning("%s: GPIO %d already freed\n", __func__, pin); - else - gpio_label[pin] = NULL; -} -EXPORT_SYMBOL(gpio_free); - -/* Debug helper */ -void gpio_display(void) -{ - int i; - - for (i = 0; i < GPIO_MAX; i++) { - printk(KERN_DEBUG "Pin-%d: ", i); - - if (!test_bit(i, gpio_valid)) { - printk("non-GPIO\n"); - } else if (!gpio_label[i]) { - printk("GPIO, free\n"); - } else { - printk("GPIO, used by %s, ", gpio_label[i]); - if (readl(GPIO_IO_CONF) & (1 << i)) { - printk("input, active %s, level %s, edge %s\n", - ((readl(GPIO_IN_POL) >> i) & 1) ? "low" : "high", - ((readl(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked", - ((readl(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked"); - } else { - printk("output, val=%d\n", (readl(GPIO_OUT) >> i) & 1); - } - } - } - - printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n", - MPP_0_7_CTRL, readl(MPP_0_7_CTRL)); - printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n", - MPP_8_15_CTRL, readl(MPP_8_15_CTRL)); - printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n", - MPP_16_19_CTRL, readl(MPP_16_19_CTRL)); - printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n", - MPP_DEV_CTRL, readl(MPP_DEV_CTRL)); - printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n", - GPIO_OUT, readl(GPIO_OUT)); - printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n", - GPIO_IO_CONF, readl(GPIO_IO_CONF)); - printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n", - GPIO_BLINK_EN, readl(GPIO_BLINK_EN)); - printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n", - GPIO_IN_POL, readl(GPIO_IN_POL)); - printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n", - GPIO_DATA_IN, readl(GPIO_DATA_IN)); - printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n", - GPIO_LEVEL_MASK, readl(GPIO_LEVEL_MASK)); - printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n", - GPIO_EDGE_CAUSE, readl(GPIO_EDGE_CAUSE)); - printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n", - GPIO_EDGE_MASK, readl(GPIO_EDGE_MASK)); -} diff --git a/arch/arm/mach-orion5x/include/mach/dma.h b/arch/arm/mach-orion5x/include/mach/dma.h deleted file mode 100644 index 40a8c178f10d..000000000000 --- a/arch/arm/mach-orion5x/include/mach/dma.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-orion5x/include/mach/gpio.h b/arch/arm/mach-orion5x/include/mach/gpio.h index 65dc136a86f7..d8182e87ac16 100644 --- a/arch/arm/mach-orion5x/include/mach/gpio.h +++ b/arch/arm/mach-orion5x/include/mach/gpio.h @@ -2,18 +2,26 @@ * arch/arm/mach-orion5x/include/mach/gpio.h * * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any + * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ -extern int gpio_request(unsigned pin, const char *label); -extern void gpio_free(unsigned pin); -extern int gpio_direction_input(unsigned pin); -extern int gpio_direction_output(unsigned pin, int value); -extern int gpio_get_value(unsigned pin); -extern void gpio_set_value(unsigned pin, int value); -extern void orion5x_gpio_set_blink(unsigned pin, int blink); -extern void gpio_display(void); /* debug */ +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include <mach/irqs.h> +#include <plat/gpio.h> +#include <asm-generic/gpio.h> /* cansleep wrappers */ + +#define GPIO_MAX 32 +#define GPIO_OUT(pin) ORION5X_DEV_BUS_REG(0x100) +#define GPIO_IO_CONF(pin) ORION5X_DEV_BUS_REG(0x104) +#define GPIO_BLINK_EN(pin) ORION5X_DEV_BUS_REG(0x108) +#define GPIO_IN_POL(pin) ORION5X_DEV_BUS_REG(0x10c) +#define GPIO_DATA_IN(pin) ORION5X_DEV_BUS_REG(0x110) +#define GPIO_EDGE_CAUSE(pin) ORION5X_DEV_BUS_REG(0x114) +#define GPIO_EDGE_MASK(pin) ORION5X_DEV_BUS_REG(0x118) +#define GPIO_LEVEL_MASK(pin) ORION5X_DEV_BUS_REG(0x11c) static inline int gpio_to_irq(int pin) { @@ -25,4 +33,5 @@ static inline int irq_to_gpio(int irq) return irq - IRQ_ORION5X_GPIO_START; } -#include <asm-generic/gpio.h> /* cansleep wrappers */ + +#endif diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h index f24b2513f7f3..c47b033bd999 100644 --- a/arch/arm/mach-orion5x/include/mach/io.h +++ b/arch/arm/mach-orion5x/include/mach/io.h @@ -38,14 +38,9 @@ __arch_iounmap(void __iomem *addr) __iounmap(addr); } -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} - #define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m) #define __arch_iounmap(a) __arch_iounmap(a) -#define __io(a) __io(a) +#define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) diff --git a/arch/arm/mach-orion5x/include/mach/irqs.h b/arch/arm/mach-orion5x/include/mach/irqs.h index d5b0fbf6b965..a6fa9d8f12d8 100644 --- a/arch/arm/mach-orion5x/include/mach/irqs.h +++ b/arch/arm/mach-orion5x/include/mach/irqs.h @@ -13,8 +13,6 @@ #ifndef __ASM_ARCH_IRQS_H #define __ASM_ARCH_IRQS_H -#include "orion5x.h" /* need GPIO_MAX */ - /* * Orion Main Interrupt Controller */ @@ -54,7 +52,7 @@ * Orion General Purpose Pins */ #define IRQ_ORION5X_GPIO_START 32 -#define NR_GPIO_IRQS GPIO_MAX +#define NR_GPIO_IRQS 32 #define NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS) diff --git a/arch/arm/mach-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h index 54dd76b013f2..52a2955d0f87 100644 --- a/arch/arm/mach-orion5x/include/mach/memory.h +++ b/arch/arm/mach-orion5x/include/mach/memory.h @@ -9,8 +9,4 @@ #define PHYS_OFFSET UL(0x00000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - - #endif diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 9f5ce1ce5840..67bda31406dd 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -134,14 +134,6 @@ #define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050) #define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008) #define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010) -#define GPIO_OUT ORION5X_DEV_BUS_REG(0x100) -#define GPIO_IO_CONF ORION5X_DEV_BUS_REG(0x104) -#define GPIO_BLINK_EN ORION5X_DEV_BUS_REG(0x108) -#define GPIO_IN_POL ORION5X_DEV_BUS_REG(0x10c) -#define GPIO_DATA_IN ORION5X_DEV_BUS_REG(0x110) -#define GPIO_EDGE_CAUSE ORION5X_DEV_BUS_REG(0x114) -#define GPIO_EDGE_MASK ORION5X_DEV_BUS_REG(0x118) -#define GPIO_LEVEL_MASK ORION5X_DEV_BUS_REG(0x11c) #define DEV_BANK_0_PARAM ORION5X_DEV_BUS_REG(0x45c) #define DEV_BANK_1_PARAM ORION5X_DEV_BUS_REG(0x460) #define DEV_BANK_2_PARAM ORION5X_DEV_BUS_REG(0x464) @@ -149,7 +141,6 @@ #define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0) #define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0) #define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4) -#define GPIO_MAX 32 /*************************************************************************** * Orion CPU Bridge Registers diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c index 632a36f5cf14..0caae43301e5 100644 --- a/arch/arm/mach-orion5x/irq.c +++ b/arch/arm/mach-orion5x/irq.c @@ -19,193 +19,38 @@ #include <plat/irq.h> #include "common.h" -/***************************************************************************** - * Orion GPIO IRQ - * - * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same - * value of the line or the opposite value. - * - * Level IRQ handlers: DATA_IN is used directly as cause register. - * Interrupt are masked by LEVEL_MASK registers. - * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. - * Interrupt are masked by EDGE_MASK registers. - * Both-edge handlers: Similar to regular Edge handlers, but also swaps - * the polarity to catch the next line transaction. - * This is a race condition that might not perfectly - * work on some use cases. - * - * Every eight GPIO lines are grouped (OR'ed) before going up to main - * cause register. - * - * EDGE cause mask - * data-in /--------| |-----| |----\ - * -----| |----- ---- to main cause reg - * X \----------------| |----/ - * polarity LEVEL mask - * - ****************************************************************************/ -static void orion5x_gpio_irq_ack(u32 irq) -{ - int pin = irq_to_gpio(irq); - if (irq_desc[irq].status & IRQ_LEVEL) - /* - * Mask bit for level interrupt - */ - orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin); - else - /* - * Clear casue bit for egde interrupt - */ - orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin); -} - -static void orion5x_gpio_irq_mask(u32 irq) -{ - int pin = irq_to_gpio(irq); - if (irq_desc[irq].status & IRQ_LEVEL) - orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin); - else - orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin); -} - -static void orion5x_gpio_irq_unmask(u32 irq) +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { - int pin = irq_to_gpio(irq); - if (irq_desc[irq].status & IRQ_LEVEL) - orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin); - else - orion5x_setbits(GPIO_EDGE_MASK, 1 << pin); -} - -static int orion5x_gpio_set_irq_type(u32 irq, u32 type) -{ - int pin = irq_to_gpio(irq); - struct irq_desc *desc; - - if ((readl(GPIO_IO_CONF) & (1 << pin)) == 0) { - printk(KERN_ERR "orion5x_gpio_set_irq_type failed " - "(irq %d, pin %d).\n", irq, pin); - return -EINVAL; - } - - desc = irq_desc + irq; - - switch (type) { - case IRQ_TYPE_LEVEL_HIGH: - desc->handle_irq = handle_level_irq; - desc->status |= IRQ_LEVEL; - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); - break; - case IRQ_TYPE_LEVEL_LOW: - desc->handle_irq = handle_level_irq; - desc->status |= IRQ_LEVEL; - orion5x_setbits(GPIO_IN_POL, (1 << pin)); - break; - case IRQ_TYPE_EDGE_RISING: - desc->handle_irq = handle_edge_irq; - desc->status &= ~IRQ_LEVEL; - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); - break; - case IRQ_TYPE_EDGE_FALLING: - desc->handle_irq = handle_edge_irq; - desc->status &= ~IRQ_LEVEL; - orion5x_setbits(GPIO_IN_POL, (1 << pin)); - break; - case IRQ_TYPE_EDGE_BOTH: - desc->handle_irq = handle_edge_irq; - desc->status &= ~IRQ_LEVEL; - /* - * set initial polarity based on current input level - */ - if ((readl(GPIO_IN_POL) ^ readl(GPIO_DATA_IN)) - & (1 << pin)) - orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */ - else - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */ - - break; - default: - printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type); - return -EINVAL; - } - - desc->status &= ~IRQ_TYPE_SENSE_MASK; - desc->status |= type & IRQ_TYPE_SENSE_MASK; - - return 0; -} - -static struct irq_chip orion5x_gpio_irq_chip = { - .name = "Orion-IRQ-GPIO", - .ack = orion5x_gpio_irq_ack, - .mask = orion5x_gpio_irq_mask, - .unmask = orion5x_gpio_irq_unmask, - .set_type = orion5x_gpio_set_irq_type, -}; - -static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - u32 cause, offs, pin; - BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31); - offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8; - cause = (readl(GPIO_DATA_IN) & readl(GPIO_LEVEL_MASK)) | - (readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK)); - for (pin = offs; pin < offs + 8; pin++) { - if (cause & (1 << pin)) { - irq = gpio_to_irq(pin); - desc = irq_desc + irq; - if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { - /* Swap polarity (race with GPIO line) */ - u32 polarity = readl(GPIO_IN_POL); - polarity ^= 1 << pin; - writel(polarity, GPIO_IN_POL); - } - generic_handle_irq(irq); - } - } + orion_gpio_irq_handler((irq - IRQ_ORION5X_GPIO_0_7) << 3); } -static void __init orion5x_init_gpio_irq(void) +void __init orion5x_init_irq(void) { int i; - struct irq_desc *desc; + + orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK); /* * Mask and clear GPIO IRQ interrupts */ - writel(0x0, GPIO_LEVEL_MASK); - writel(0x0, GPIO_EDGE_MASK); - writel(0x0, GPIO_EDGE_CAUSE); + writel(0x0, GPIO_LEVEL_MASK(0)); + writel(0x0, GPIO_EDGE_MASK(0)); + writel(0x0, GPIO_EDGE_CAUSE(0)); /* * Register chained level handlers for GPIO IRQs by default. * User can use set_type() if he wants to use edge types handlers. */ for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) { - set_irq_chip(i, &orion5x_gpio_irq_chip); + set_irq_chip(i, &orion_gpio_irq_level_chip); set_irq_handler(i, handle_level_irq); - desc = irq_desc + i; - desc->status |= IRQ_LEVEL; + irq_desc[i].status |= IRQ_LEVEL; set_irq_flags(i, IRQF_VALID); } - set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler); - set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler); - set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler); - set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler); -} - -/***************************************************************************** - * Orion Main IRQ - ****************************************************************************/ -static void __init orion5x_init_main_irq(void) -{ - orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK); -} - -void __init orion5x_init_irq(void) -{ - orion5x_init_main_irq(); - orion5x_init_gpio_irq(); + set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler); } diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c index 640ea2a3fc6c..e23a3f91d6c6 100644 --- a/arch/arm/mach-orion5x/mpp.c +++ b/arch/arm/mach-orion5x/mpp.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/mbus.h> #include <linux/io.h> +#include <asm/gpio.h> #include <mach/hardware.h> #include "common.h" #include "mpp.h" @@ -152,7 +153,10 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode) *reg &= ~(0xf << shift); *reg |= (num_type & 0xf) << shift; - orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO)); + if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182())) + orion_gpio_set_unused(mode->mpp); + + orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO)); mode++; } diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c index ac2f70eddb9e..425f7188505e 100644 --- a/arch/arm/mach-pnx4008/dma.c +++ b/arch/arm/mach-pnx4008/dma.c @@ -25,9 +25,8 @@ #include <asm/system.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <asm/dma-mapping.h> -#include <asm/mach/dma.h> #include <mach/clock.h> static struct dma_channel { diff --git a/arch/arm/mach-pnx4008/include/mach/dma.h b/arch/arm/mach-pnx4008/include/mach/dma.h index 5442d04fc575..f094bf8bfb18 100644 --- a/arch/arm/mach-pnx4008/include/mach/dma.h +++ b/arch/arm/mach-pnx4008/include/mach/dma.h @@ -16,8 +16,6 @@ #include "platform.h" -#define MAX_DMA_ADDRESS 0xffffffff - #define MAX_DMA_CHANNELS 8 #define DMAC_BASE IO_ADDRESS(PNX4008_DMA_CONFIG_BASE) diff --git a/arch/arm/mach-pnx4008/include/mach/io.h b/arch/arm/mach-pnx4008/include/mach/io.h index c6206f25839d..cbf0904540ea 100644 --- a/arch/arm/mach-pnx4008/include/mach/io.h +++ b/arch/arm/mach-pnx4008/include/mach/io.h @@ -15,7 +15,7 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-pnx4008/include/mach/memory.h b/arch/arm/mach-pnx4008/include/mach/memory.h index 5789a2d16f5a..0e8770081058 100644 --- a/arch/arm/mach-pnx4008/include/mach/memory.h +++ b/arch/arm/mach-pnx4008/include/mach/memory.h @@ -16,9 +16,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET (0x80000000) - -#define __virt_to_bus(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) -#define __bus_to_virt(x) ((x) + PAGE_OFFSET - PHYS_OFFSET) +#define PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index a062235e83a8..8eea7306f29b 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -19,20 +19,34 @@ config CPU_PXA320 config CPU_PXA930 bool "PXA930 (codename Tavor-P)" +config CPU_PXA935 + bool "PXA935 (codename Tavor-P65)" + endmenu endif config ARCH_GUMSTIX - bool "Gumstix XScale boards" + bool "Gumstix XScale 255 boards" + select PXA25x help - Say Y here if you intend to run this kernel on a - Gumstix Full Function Minature Computer. + Say Y here if you intend to run this kernel on + Basix, Connex, ws-200ax, ws-400ax systems -config MACH_GUMSTIX_F - bool "Basix, Connex, ws-200ax, ws-400ax systems" +choice + prompt "Gumstix Carrier/Expansion Board" depends on ARCH_GUMSTIX - select PXA25x + +config GUMSTIX_AM200EPD + bool "Enable AM200EPD board support" + +endchoice + +config MACH_INTELMOTE2 + bool "Intel Mote 2 Platform" + select PXA27x + select IWMMXT + select PXA_HAVE_BOARD_IRQS config ARCH_LUBBOCK bool "Intel DBPXA250 Development Platform" @@ -199,6 +213,10 @@ config MACH_E800 config TRIZEPS_PXA bool "PXA based Keith und Koep Trizeps DIMM-Modules" +config MACH_H5000 + bool "HP iPAQ h5000" + select PXA25x + config MACH_TRIZEPS4 bool "Keith und Koep Trizeps4 DIMM-Module" depends on TRIZEPS_PXA @@ -283,7 +301,6 @@ config MACH_MIOA701 bool "Mitac Mio A701 Support" select PXA27x select IWMMXT - select LEDS_GPIO select HAVE_PWM select GPIO_SYSFS help @@ -342,10 +359,6 @@ config PCM990_DISPLAY_NONE endchoice -config MACH_AM200EPD - depends on MACH_GUMSTIX_F - bool "Enable AM200EPD board support" - config PXA_EZX bool "Motorola EZX Platform" select PXA27x @@ -386,16 +399,25 @@ endmenu config PXA25x bool + select CPU_XSCALE help Select code specific to PXA21x/25x/26x variants config PXA27x bool + select CPU_XSCALE help Select code specific to PXA27x variants +config CPU_PXA26x + bool + select PXA25x + help + Select code specific to PXA26x (codename Dalhart) + config PXA3xx bool + select CPU_XSC3 help Select code specific to PXA3xx variants diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index d64c68b232e3..7b28bb561d63 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_CPU_PXA930) += pxa930.o # Specific board support obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o -obj-$(CONFIG_MACH_AM200EPD) += am200epd.o +obj-$(CONFIG_GUMSTIX_AM200EPD) += am200epd.o obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o @@ -35,6 +35,7 @@ obj-$(CONFIG_MACH_MP900C) += mp900.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o obj-$(CONFIG_MACH_COLIBRI) += colibri.o +obj-$(CONFIG_MACH_H5000) += h5000.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o obj-$(CONFIG_CORGI_SSP_DEPRECATED) += corgi_ssp.o corgi_lcd.o @@ -69,6 +70,8 @@ obj-$(CONFIG_MACH_ARMCORE) += cm-x2xx.o cm-x255.o cm-x270.o obj-$(CONFIG_MACH_CM_X300) += cm-x300.o obj-$(CONFIG_PXA_EZX) += ezx.o +obj-$(CONFIG_MACH_INTELMOTE2) += imote2.o + # Support for blinky lights led-y := leds.o led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c index b965085a37b9..77ee80e5e47b 100644 --- a/arch/arm/mach-pxa/am200epd.c +++ b/arch/arm/mach-pxa/am200epd.c @@ -30,8 +30,12 @@ #include <linux/irq.h> #include <linux/gpio.h> +#include <mach/gumstix.h> +#include <mach/mfp-pxa25x.h> #include <mach/pxafb.h> +#include "generic.h" + #include <video/metronomefb.h> static unsigned int panel_type = 6; @@ -331,7 +335,16 @@ static struct metronome_board am200_board = { .cleanup = am200_cleanup, }; -static int __init am200_init(void) +static unsigned long am200_pin_config[] __initdata = { + GPIO51_GPIO, + GPIO49_GPIO, + GPIO48_GPIO, + GPIO32_GPIO, + GPIO17_GPIO, + GPIO16_GPIO, +}; + +int __init am200_init(void) { int ret; @@ -339,6 +352,8 @@ static int __init am200_init(void) * creation events */ fb_register_client(&am200_fb_notif); + pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config)); + /* request our platform independent driver */ request_module("metronomefb"); @@ -367,8 +382,6 @@ static int __init am200_init(void) module_param(panel_type, uint, 0); MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97"); -module_init(am200_init); - MODULE_DESCRIPTION("board driver for am200 metronome epd kit"); MODULE_AUTHOR("Jaya Kumar"); MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index ca8e20538157..40b774084514 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -12,53 +12,16 @@ #include <linux/platform_device.h> #include <linux/delay.h> +#include <asm/clkdev.h> #include <mach/pxa2xx-regs.h> -#include <mach/pxa2xx-gpio.h> #include <mach/hardware.h> #include "devices.h" #include "generic.h" #include "clock.h" -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); static DEFINE_SPINLOCK(clocks_lock); -static struct clk *clk_lookup(struct device *dev, const char *id) -{ - struct clk *p; - - list_for_each_entry(p, &clocks, node) - if (strcmp(id, p->name) == 0 && p->dev == dev) - return p; - - return NULL; -} - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - p = clk_lookup(dev, id); - if (!p) - p = clk_lookup(NULL, id); - if (p) - clk = p; - mutex_unlock(&clocks_mutex); - - if (!IS_ERR(clk) && clk->ops == NULL) - clk = clk->other; - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - int clk_enable(struct clk *clk) { unsigned long flags; @@ -116,37 +79,27 @@ const struct clkops clk_cken_ops = { .disable = clk_cken_disable, }; -void clks_register(struct clk *clks, size_t num) +void clks_register(struct clk_lookup *clks, size_t num) { int i; - mutex_lock(&clocks_mutex); for (i = 0; i < num; i++) - list_add(&clks[i].node, &clocks); - mutex_unlock(&clocks_mutex); + clkdev_add(&clks[i]); } int clk_add_alias(char *alias, struct device *alias_dev, char *id, struct device *dev) { - struct clk *r = clk_lookup(dev, id); - struct clk *new; + struct clk *r = clk_get(dev, id); + struct clk_lookup *l; if (!r) return -ENODEV; - new = kzalloc(sizeof(struct clk), GFP_KERNEL); - - if (!new) - return -ENOMEM; - - new->name = alias; - new->dev = alias_dev; - new->other = r; - - mutex_lock(&clocks_mutex); - list_add(&new->node, &clocks); - mutex_unlock(&clocks_mutex); - + l = clkdev_alloc(r, alias, alias_dev ? dev_name(alias_dev) : NULL); + clk_put(r); + if (!l) + return -ENODEV; + clkdev_add(l); return 0; } diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index 73be795fe3bf..4e9c613c6767 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h @@ -1,6 +1,4 @@ -#include <linux/list.h> - -struct clk; +#include <asm/clkdev.h> struct clkops { void (*enable)(struct clk *); @@ -9,9 +7,6 @@ struct clkops { }; struct clk { - struct list_head node; - const char *name; - struct device *dev; const struct clkops *ops; unsigned long rate; unsigned int cken; @@ -20,41 +15,31 @@ struct clk { struct clk *other; }; -#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \ +#define INIT_CLKREG(_clk,_devname,_conname) \ { \ - .name = _name, \ - .dev = _dev, \ + .clk = _clk, \ + .dev_id = _devname, \ + .con_id = _conname, \ + } + +#define DEFINE_CKEN(_name, _cken, _rate, _delay) \ +struct clk clk_##_name = { \ .ops = &clk_cken_ops, \ .rate = _rate, \ .cken = CKEN_##_cken, \ .delay = _delay, \ } -#define INIT_CK(_name, _cken, _ops, _dev) \ - { \ - .name = _name, \ - .dev = _dev, \ +#define DEFINE_CK(_name, _cken, _ops) \ +struct clk clk_##_name = { \ .ops = _ops, \ .cken = CKEN_##_cken, \ } -/* - * This is a placeholder to alias one clock device+name pair - * to another struct clk. - */ -#define INIT_CKOTHER(_name, _other, _dev) \ - { \ - .name = _name, \ - .dev = _dev, \ - .other = _other, \ - } - -#define INIT_CLK(_name, _ops, _rate, _delay, _dev) \ - { \ - .name = _name, \ - .dev = _dev, \ - .ops = _ops, \ - .rate = _rate, \ +#define DEFINE_CLK(_name, _ops, _rate, _delay) \ +struct clk clk_##_name = { \ + .ops = _ops, \ + .rate = _rate, \ .delay = _delay, \ } @@ -64,20 +49,16 @@ void clk_cken_enable(struct clk *clk); void clk_cken_disable(struct clk *clk); #ifdef CONFIG_PXA3xx -#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \ - { \ - .name = _name, \ - .dev = _dev, \ +#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay) \ +struct clk clk_##_name = { \ .ops = &clk_pxa3xx_cken_ops, \ .rate = _rate, \ .cken = CKEN_##_cken, \ .delay = _delay, \ } -#define PXA3xx_CK(_name, _cken, _ops, _dev) \ - { \ - .name = _name, \ - .dev = _dev, \ +#define DEFINE_PXA3_CK(_name, _cken, _ops) \ +struct clk clk_##_name = { \ .ops = _ops, \ .cken = CKEN_##_cken, \ } @@ -87,7 +68,7 @@ extern void clk_pxa3xx_cken_enable(struct clk *); extern void clk_pxa3xx_cken_disable(struct clk *); #endif -void clks_register(struct clk *clks, size_t num); +void clks_register(struct clk_lookup *clks, size_t num); int clk_add_alias(char *alias, struct device *alias_dev, char *id, struct device *dev); diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c index 0b3ce3b6d896..d99fd9e4d888 100644 --- a/arch/arm/mach-pxa/cm-x2xx.c +++ b/arch/arm/mach-pxa/cm-x2xx.c @@ -210,10 +210,8 @@ static struct pxafb_mode_info generic_stn_320x240_mode = { static struct pxafb_mach_info generic_stn_320x240 = { .modes = &generic_stn_320x240_mode, .num_modes = 1, - .lccr0 = 0, - .lccr3 = (LCCR3_PixClkDiv(0x03) | - LCCR3_Acb(0xff) | - LCCR3_PCP), + .lcd_conn = LCD_COLOR_STN_8BPP | LCD_PCLK_EDGE_FALL |\ + LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; @@ -236,10 +234,8 @@ static struct pxafb_mode_info generic_tft_640x480_mode = { static struct pxafb_mach_info generic_tft_640x480 = { .modes = &generic_tft_640x480_mode, .num_modes = 1, - .lccr0 = (LCCR0_PAS), - .lccr3 = (LCCR3_PixClkDiv(0x01) | - LCCR3_Acb(0xff) | - LCCR3_PCP), + .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_PCLK_EDGE_FALL |\ + LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; @@ -263,9 +259,7 @@ static struct pxafb_mode_info generic_crt_640x480_mode = { static struct pxafb_mach_info generic_crt_640x480 = { .modes = &generic_crt_640x480_mode, .num_modes = 1, - .lccr0 = (LCCR0_PAS), - .lccr3 = (LCCR3_PixClkDiv(0x01) | - LCCR3_Acb(0xff)), + .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; @@ -289,9 +283,7 @@ static struct pxafb_mode_info generic_crt_800x600_mode = { static struct pxafb_mach_info generic_crt_800x600 = { .modes = &generic_crt_800x600_mode, .num_modes = 1, - .lccr0 = (LCCR0_PAS), - .lccr3 = (LCCR3_PixClkDiv(0x02) | - LCCR3_Acb(0xff)), + .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; @@ -314,10 +306,7 @@ static struct pxafb_mode_info generic_tft_320x240_mode = { static struct pxafb_mach_info generic_tft_320x240 = { .modes = &generic_tft_320x240_mode, .num_modes = 1, - .lccr0 = (LCCR0_PAS), - .lccr3 = (LCCR3_PixClkDiv(0x06) | - LCCR3_Acb(0xff) | - LCCR3_PCP), + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; @@ -341,9 +330,7 @@ static struct pxafb_mode_info generic_stn_640x480_mode = { static struct pxafb_mach_info generic_stn_640x480 = { .modes = &generic_stn_640x480_mode, .num_modes = 1, - .lccr0 = 0, - .lccr3 = (LCCR3_PixClkDiv(0x02) | - LCCR3_Acb(0xff)), + .lcd_conn = LCD_COLOR_STN_8BPP | LCD_AC_BIAS_FREQ(0xff), .cmap_inverse = 0, .cmap_static = 0, }; diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index deb46cd144bf..ff0c577cd1ac 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -31,7 +31,6 @@ #include <mach/mfp-pxa300.h> #include <mach/hardware.h> -#include <mach/gpio.h> #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/ohci.h> @@ -137,6 +136,10 @@ static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = { GPIO82_GPIO | MFP_PULL_HIGH, /* MMC CD */ GPIO85_GPIO, /* MMC WP */ GPIO99_GPIO, /* Ethernet IRQ */ + + /* Standard I2C */ + GPIO21_I2C_SCL, + GPIO22_I2C_SDA, }; #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 65558d6aa220..c5e28a46b292 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -19,6 +19,7 @@ #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/mmc/host.h> +#include <linux/mtd/physmap.h> #include <linux/pm.h> #include <linux/gpio.h> #include <linux/backlight.h> @@ -541,11 +542,42 @@ err_free_1: static inline void corgi_init_spi(void) {} #endif +static struct mtd_partition sharpsl_rom_parts[] = { + { + .name ="Boot PROM Filesystem", + .offset = 0x00120000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data sharpsl_rom_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(sharpsl_rom_parts), + .parts = sharpsl_rom_parts, +}; + +static struct resource sharpsl_rom_resources[] = { + { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sharpsl_rom_device = { + .name = "physmap-flash", + .id = -1, + .resource = sharpsl_rom_resources, + .num_resources = ARRAY_SIZE(sharpsl_rom_resources), + .dev.platform_data = &sharpsl_rom_data, +}; + static struct platform_device *devices[] __initdata = { &corgiscoop_device, &corgifb_device, &corgikbd_device, &corgiled_device, + &sharpsl_rom_device, }; static void corgi_poweroff(void) diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c index 1f272ea83f36..771dd4eac935 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c @@ -64,7 +64,7 @@ typedef struct { /* Define the refresh period in mSec for the SDRAM and the number of rows */ #define SDRAM_TREF 64 /* standard 64ms SDRAM */ -#define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ +static unsigned int sdram_rows; #define CCLKCFG_TURBO 0x1 #define CCLKCFG_FCS 0x2 @@ -73,6 +73,9 @@ typedef struct { #define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) #define MDREFR_DRI_MASK 0xFFF +#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3) +#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3) + /* * PXA255 definitions */ @@ -109,6 +112,10 @@ static struct cpufreq_frequency_table static struct cpufreq_frequency_table pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1]; +static unsigned int pxa255_turbo_table; +module_param(pxa255_turbo_table, uint, 0); +MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table, !0 = turbo table)"); + /* * PXA270 definitions * @@ -158,22 +165,16 @@ static struct cpufreq_frequency_table extern unsigned get_clk_frequency_khz(int info); -static void find_freq_tables(struct cpufreq_policy *policy, - struct cpufreq_frequency_table **freq_table, +static void find_freq_tables(struct cpufreq_frequency_table **freq_table, pxa_freqs_t **pxa_freqs) { if (cpu_is_pxa25x()) { - if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + if (!pxa255_turbo_table) { *pxa_freqs = pxa255_run_freqs; *freq_table = pxa255_run_freq_table; - } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { + } else { *pxa_freqs = pxa255_turbo_freqs; *freq_table = pxa255_turbo_freq_table; - } else { - printk("CPU PXA: Unknown policy found. " - "Using CPUFREQ_POLICY_PERFORMANCE\n"); - *pxa_freqs = pxa255_run_freqs; - *freq_table = pxa255_run_freq_table; } } if (cpu_is_pxa27x()) { @@ -194,14 +195,28 @@ static void pxa27x_guess_max_freq(void) } } +static void init_sdram_rows(void) +{ + uint32_t mdcnfg = MDCNFG; + unsigned int drac2 = 0, drac0 = 0; + + if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3)) + drac2 = MDCNFG_DRAC2(mdcnfg); + + if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1)) + drac0 = MDCNFG_DRAC0(mdcnfg); + + sdram_rows = 1 << (11 + max(drac0, drac2)); +} + static u32 mdrefr_dri(unsigned int freq) { u32 dri = 0; if (cpu_is_pxa25x()) - dri = ((freq * SDRAM_TREF) / (SDRAM_ROWS * 32)); + dri = ((freq * SDRAM_TREF) / (sdram_rows * 32)); if (cpu_is_pxa27x()) - dri = ((freq * SDRAM_TREF) / (SDRAM_ROWS - 31)) / 32; + dri = ((freq * SDRAM_TREF) / (sdram_rows - 31)) / 32; return dri; } @@ -212,7 +227,7 @@ static int pxa_verify_policy(struct cpufreq_policy *policy) pxa_freqs_t *pxa_freqs; int ret; - find_freq_tables(policy, &pxa_freqs_table, &pxa_freqs); + find_freq_tables(&pxa_freqs_table, &pxa_freqs); ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table); if (freq_debug) @@ -240,7 +255,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; /* Get the current policy */ - find_freq_tables(policy, &pxa_freqs_table, &pxa_freq_settings); + find_freq_tables(&pxa_freqs_table, &pxa_freq_settings); /* Lookup the next frequency */ if (cpufreq_frequency_table_target(policy, pxa_freqs_table, @@ -329,11 +344,15 @@ static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) { int i; unsigned int freq; + struct cpufreq_frequency_table *pxa255_freq_table; + pxa_freqs_t *pxa255_freqs; /* try to guess pxa27x cpu */ if (cpu_is_pxa27x()) pxa27x_guess_max_freq(); + init_sdram_rows(); + /* set default policy and cpuinfo */ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ policy->cur = get_clk_frequency_khz(0); /* current freq */ @@ -354,6 +373,8 @@ static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) } pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END; + pxa255_turbo_table = !!pxa255_turbo_table; + /* Generate the pxa27x cpufreq_frequency_table struct */ for (i = 0; i < NUM_PXA27x_FREQS; i++) { freq = pxa27x_freqs[i].khz; @@ -368,8 +389,12 @@ static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) * Set the policy's minimum and maximum frequencies from the tables * just constructed. This sets cpuinfo.mxx_freq, min and max. */ - if (cpu_is_pxa25x()) - cpufreq_frequency_table_cpuinfo(policy, pxa255_run_freq_table); + if (cpu_is_pxa25x()) { + find_freq_tables(&pxa255_freq_table, &pxa255_freqs); + pr_info("PXA255 cpufreq using %s frequency table\n", + pxa255_turbo_table ? "turbo" : "run"); + cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table); + } else if (cpu_is_pxa27x()) cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table); diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 35736fc08634..e16f8e3d58d3 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -4,13 +4,12 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <mach/gpio.h> +#include <mach/pxa-regs.h> #include <mach/udc.h> #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/irda.h> #include <mach/i2c.h> -#include <mach/mfp-pxa27x.h> #include <mach/ohci.h> #include <mach/pxa27x_keypad.h> #include <mach/pxa2xx_spi.h> @@ -156,8 +155,8 @@ void __init set_pxa_fb_parent(struct device *parent_dev) static struct resource pxa_resource_ffuart[] = { { - .start = __PREG(FFUART), - .end = __PREG(FFUART) + 35, + .start = 0x40100000, + .end = 0x40100023, .flags = IORESOURCE_MEM, }, { .start = IRQ_FFUART, @@ -175,8 +174,8 @@ struct platform_device pxa_device_ffuart= { static struct resource pxa_resource_btuart[] = { { - .start = __PREG(BTUART), - .end = __PREG(BTUART) + 35, + .start = 0x40200000, + .end = 0x40200023, .flags = IORESOURCE_MEM, }, { .start = IRQ_BTUART, @@ -194,8 +193,8 @@ struct platform_device pxa_device_btuart = { static struct resource pxa_resource_stuart[] = { { - .start = __PREG(STUART), - .end = __PREG(STUART) + 35, + .start = 0x40700000, + .end = 0x40700023, .flags = IORESOURCE_MEM, }, { .start = IRQ_STUART, @@ -213,8 +212,8 @@ struct platform_device pxa_device_stuart = { static struct resource pxa_resource_hwuart[] = { { - .start = __PREG(HWUART), - .end = __PREG(HWUART) + 47, + .start = 0x41600000, + .end = 0x4160002F, .flags = IORESOURCE_MEM, }, { .start = IRQ_HWUART, @@ -249,18 +248,53 @@ struct platform_device pxa_device_i2c = { .num_resources = ARRAY_SIZE(pxai2c_resources), }; -static unsigned long pxa27x_i2c_mfp_cfg[] = { - GPIO117_I2C_SCL, - GPIO118_I2C_SDA, -}; - void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) { - if (cpu_is_pxa27x()) - pxa2xx_mfp_config(ARRAY_AND_SIZE(pxa27x_i2c_mfp_cfg)); pxa_register_device(&pxa_device_i2c, info); } +#ifdef CONFIG_PXA27x +static struct resource pxa27x_resources_i2c_power[] = { + { + .start = 0x40f00180, + .end = 0x40f001a3, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PWRI2C, + .end = IRQ_PWRI2C, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa27x_device_i2c_power = { + .name = "pxa2xx-i2c", + .id = 1, + .resource = pxa27x_resources_i2c_power, + .num_resources = ARRAY_SIZE(pxa27x_resources_i2c_power), +}; +#endif + +#ifdef CONFIG_PXA3xx +static struct resource pxa3xx_resources_i2c_power[] = { + { + .start = 0x40f500c0, + .end = 0x40f500d3, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PWRI2C, + .end = IRQ_PWRI2C, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa3xx_device_i2c_power = { + .name = "pxa2xx-i2c", + .id = 1, + .resource = pxa3xx_resources_i2c_power, + .num_resources = ARRAY_SIZE(pxa3xx_resources_i2c_power), +}; +#endif + static struct resource pxai2s_resources[] = { { .start = 0x40400000, @@ -296,11 +330,36 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) pxa_register_device(&pxa_device_ficp, info); } -struct platform_device pxa_device_rtc = { +static struct resource pxa_rtc_resources[] = { + [0] = { + .start = 0x40900000, + .end = 0x40900000 + 0x3b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC1Hz, + .end = IRQ_RTC1Hz, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_RTCAlrm, + .end = IRQ_RTCAlrm, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device sa1100_device_rtc = { .name = "sa1100-rtc", .id = -1, }; +struct platform_device pxa_device_rtc = { + .name = "pxa-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(pxa_rtc_resources), + .resource = pxa_rtc_resources, +}; + static struct resource pxa_ac97_resources[] = { [0] = { .start = 0x40500000, diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index bb04af4b0aa3..ecc24a4dca6d 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -11,6 +11,7 @@ extern struct platform_device pxa_device_hwuart; extern struct platform_device pxa_device_i2c; extern struct platform_device pxa_device_i2s; extern struct platform_device pxa_device_ficp; +extern struct platform_device sa1100_device_rtc; extern struct platform_device pxa_device_rtc; extern struct platform_device pxa_device_ac97; diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index c0be17e0ab82..b1514fb20d3a 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -21,7 +21,7 @@ #include <asm/system.h> #include <asm/irq.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/pxa-regs.h> diff --git a/arch/arm/mach-pxa/e330.c b/arch/arm/mach-pxa/e330.c index d488eded2058..1bd7f740427c 100644 --- a/arch/arm/mach-pxa/e330.c +++ b/arch/arm/mach-pxa/e330.c @@ -1,5 +1,5 @@ /* - * Hardware definitions for the Toshiba eseries PDAs + * Hardware definitions for the Toshiba e330 PDAs * * Copyright (c) 2003 Ian Molton <spyro@f2s.com> * @@ -12,6 +12,9 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/mfd/tc6387xb.h> #include <asm/setup.h> #include <asm/mach/arch.h> @@ -19,13 +22,44 @@ #include <mach/mfp-pxa25x.h> #include <mach/hardware.h> +#include <mach/pxa-regs.h> +#include <mach/eseries-gpio.h> #include <mach/udc.h> #include "generic.h" #include "eseries.h" +#include "clock.h" + +/* -------------------- e330 tc6387xb parameters -------------------- */ + +static struct tc6387xb_platform_data e330_tc6387xb_info = { + .enable = &eseries_tmio_enable, + .disable = &eseries_tmio_disable, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, +}; + +static struct platform_device e330_tc6387xb_device = { + .name = "tc6387xb", + .id = -1, + .dev = { + .platform_data = &e330_tc6387xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + +/* --------------------------------------------------------------- */ + +static struct platform_device *devices[] __initdata = { + &e330_tc6387xb_device, +}; static void __init e330_init(void) { + eseries_register_clks(); + eseries_get_tmio_gpios(); + platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e7xx_udc_mach_info); } diff --git a/arch/arm/mach-pxa/e350.c b/arch/arm/mach-pxa/e350.c index 8ecbc5479828..251129391d7d 100644 --- a/arch/arm/mach-pxa/e350.c +++ b/arch/arm/mach-pxa/e350.c @@ -1,5 +1,5 @@ /* - * Hardware definitions for the Toshiba eseries PDAs + * Hardware definitions for the Toshiba e350 PDAs * * Copyright (c) 2003 Ian Molton <spyro@f2s.com> * @@ -12,20 +12,54 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/mfd/t7l66xb.h> #include <asm/setup.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/mfp-pxa25x.h> +#include <mach/pxa-regs.h> #include <mach/hardware.h> +#include <mach/eseries-gpio.h> #include <mach/udc.h> #include "generic.h" #include "eseries.h" +#include "clock.h" + +/* -------------------- e350 t7l66xb parameters -------------------- */ + +static struct t7l66xb_platform_data e350_t7l66xb_info = { + .irq_base = IRQ_BOARD_START, + .enable = &eseries_tmio_enable, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, +}; + +static struct platform_device e350_t7l66xb_device = { + .name = "t7l66xb", + .id = -1, + .dev = { + .platform_data = &e350_t7l66xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + +/* ---------------------------------------------------------- */ + +static struct platform_device *devices[] __initdata = { + &e350_t7l66xb_device, +}; static void __init e350_init(void) { + eseries_register_clks(); + eseries_get_tmio_gpios(); + platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e7xx_udc_mach_info); } diff --git a/arch/arm/mach-pxa/e400.c b/arch/arm/mach-pxa/e400.c index 544bbaa20621..bed0336aca3d 100644 --- a/arch/arm/mach-pxa/e400.c +++ b/arch/arm/mach-pxa/e400.c @@ -12,20 +12,26 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/mfd/t7l66xb.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> #include <asm/setup.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> -#include <mach/pxa-regs.h> #include <mach/mfp-pxa25x.h> +#include <mach/pxa-regs.h> #include <mach/hardware.h> - +#include <mach/eseries-gpio.h> #include <mach/pxafb.h> #include <mach/udc.h> #include "generic.h" #include "eseries.h" +#include "clock.h" /* ------------------------ E400 LCD definitions ------------------------ */ @@ -46,7 +52,7 @@ static struct pxafb_mode_info e400_pxafb_mode_info = { static struct pxafb_mach_info e400_pxafb_mach_info = { .modes = &e400_pxafb_mode_info, .num_modes = 1, - .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lcd_conn = LCD_COLOR_TFT_16BPP, .lccr3 = 0, .pxafb_backlight_power = NULL, }; @@ -65,7 +71,10 @@ static unsigned long e400_pin_config[] __initdata = { GPIO42_BTUART_RXD, GPIO43_BTUART_TXD, GPIO44_BTUART_CTS, - GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* TMIO controller */ + GPIO19_GPIO, /* t7l66xb #PCLR */ + GPIO45_GPIO, /* t7l66xb #SUSPEND (NOT BTUART!) */ /* wakeup */ GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, @@ -73,10 +82,60 @@ static unsigned long e400_pin_config[] __initdata = { /* ---------------------------------------------------------------------- */ +static struct mtd_partition partition_a = { + .name = "Internal NAND flash", + .offset = 0, + .size = MTDPART_SIZ_FULL, +}; + +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr e400_t7l66xb_nand_bbt = { + .options = 0, + .offs = 4, + .len = 2, + .pattern = scan_ff_pattern +}; + +static struct tmio_nand_data e400_t7l66xb_nand_config = { + .num_partitions = 1, + .partition = &partition_a, + .badblock_pattern = &e400_t7l66xb_nand_bbt, +}; + +static struct t7l66xb_platform_data e400_t7l66xb_info = { + .irq_base = IRQ_BOARD_START, + .enable = &eseries_tmio_enable, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, + + .nand_data = &e400_t7l66xb_nand_config, +}; + +static struct platform_device e400_t7l66xb_device = { + .name = "t7l66xb", + .id = -1, + .dev = { + .platform_data = &e400_t7l66xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + +/* ---------------------------------------------------------- */ + +static struct platform_device *devices[] __initdata = { + &e400_t7l66xb_device, +}; + static void __init e400_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(e400_pin_config)); + /* Fixme - e400 may have a switched clock */ + eseries_register_clks(); + eseries_get_tmio_gpios(); set_pxa_fb_info(&e400_pxafb_mach_info); + platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e7xx_udc_mach_info); } diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c index c57a15b37f0d..b00d670b2ea6 100644 --- a/arch/arm/mach-pxa/e740.c +++ b/arch/arm/mach-pxa/e740.c @@ -15,6 +15,8 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/fb.h> +#include <linux/clk.h> +#include <linux/mfd/t7l66xb.h> #include <video/w100fb.h> @@ -23,12 +25,16 @@ #include <asm/mach-types.h> #include <mach/mfp-pxa25x.h> +#include <mach/pxa-regs.h> #include <mach/hardware.h> +#include <mach/eseries-gpio.h> #include <mach/udc.h> +#include <mach/irda.h> #include "generic.h" #include "eseries.h" - +#include "clock.h" +#include "devices.h" /* ------------------------ e740 video support --------------------------- */ @@ -116,7 +122,17 @@ static unsigned long e740_pin_config[] __initdata = { GPIO42_BTUART_RXD, GPIO43_BTUART_TXD, GPIO44_BTUART_CTS, - GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* TMIO controller */ + GPIO19_GPIO, /* t7l66xb #PCLR */ + GPIO45_GPIO, /* t7l66xb #SUSPEND (NOT BTUART!) */ + + /* UDC */ + GPIO13_GPIO, + GPIO3_GPIO, + + /* IrDA */ + GPIO38_GPIO | MFP_LPM_DRIVE_HIGH, /* PC Card */ GPIO8_GPIO, /* CD0 */ @@ -142,17 +158,43 @@ static unsigned long e740_pin_config[] __initdata = { GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, }; +/* -------------------- e740 t7l66xb parameters -------------------- */ + +static struct t7l66xb_platform_data e740_t7l66xb_info = { + .irq_base = IRQ_BOARD_START, + .enable = &eseries_tmio_enable, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, +}; + +static struct platform_device e740_t7l66xb_device = { + .name = "t7l66xb", + .id = -1, + .dev = { + .platform_data = &e740_t7l66xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + /* ----------------------------------------------------------------------- */ static struct platform_device *devices[] __initdata = { &e740_fb_device, + &e740_t7l66xb_device, }; static void __init e740_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config)); + eseries_register_clks(); + clk_add_alias("CLK_CK48M", &e740_t7l66xb_device.dev, + "UDCCLK", &pxa25x_device_udc.dev), + eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e7xx_udc_mach_info); + e7xx_irda_init(); + pxa_set_ficp_info(&e7xx_ficp_platform_data); } MACHINE_START(E740, "Toshiba e740") diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c index 640e738b85df..84d7c1aac58d 100644 --- a/arch/arm/mach-pxa/e750.c +++ b/arch/arm/mach-pxa/e750.c @@ -15,6 +15,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/fb.h> +#include <linux/mfd/tc6393xb.h> #include <video/w100fb.h> @@ -23,11 +24,15 @@ #include <asm/mach-types.h> #include <mach/mfp-pxa25x.h> +#include <mach/pxa-regs.h> #include <mach/hardware.h> +#include <mach/eseries-gpio.h> #include <mach/udc.h> +#include <mach/irda.h> #include "generic.h" #include "eseries.h" +#include "clock.h" /* ---------------------- E750 LCD definitions -------------------- */ @@ -100,16 +105,45 @@ static struct platform_device e750_fb_device = { .resource = e750_fb_resources, }; -/* ----------------------------------------------------------------------- */ +/* ----------------- e750 tc6393xb parameters ------------------ */ + +static struct tc6393xb_platform_data e750_tc6393xb_info = { + .irq_base = IRQ_BOARD_START, + .scr_pll2cr = 0x0cc1, + .scr_gper = 0, + .gpio_base = -1, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, + .enable = &eseries_tmio_enable, + .disable = &eseries_tmio_disable, +}; + +static struct platform_device e750_tc6393xb_device = { + .name = "tc6393xb", + .id = -1, + .dev = { + .platform_data = &e750_tc6393xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + +/* ------------------------------------------------------------- */ static struct platform_device *devices[] __initdata = { &e750_fb_device, + &e750_tc6393xb_device, }; static void __init e750_init(void) { + clk_add_alias("CLK_CK3P6MI", &e750_tc6393xb_device.dev, + "GPIO11_CLK", NULL), + eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e7xx_udc_mach_info); + e7xx_irda_init(); + pxa_set_ficp_info(&e7xx_ficp_platform_data); } MACHINE_START(E750, "Toshiba e750") diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c index a293e09bfe25..9a86a426f924 100644 --- a/arch/arm/mach-pxa/e800.c +++ b/arch/arm/mach-pxa/e800.c @@ -15,6 +15,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/fb.h> +#include <linux/mfd/tc6393xb.h> #include <video/w100fb.h> @@ -23,12 +24,14 @@ #include <asm/mach-types.h> #include <mach/mfp-pxa25x.h> +#include <mach/pxa-regs.h> #include <mach/hardware.h> #include <mach/eseries-gpio.h> #include <mach/udc.h> #include "generic.h" #include "eseries.h" +#include "clock.h" /* ------------------------ e800 LCD definitions ------------------------- */ @@ -160,14 +163,41 @@ static struct pxa2xx_udc_mach_info e800_udc_mach_info = { .gpio_pullup_inverted = 1 }; +/* ----------------- e800 tc6393xb parameters ------------------ */ + +static struct tc6393xb_platform_data e800_tc6393xb_info = { + .irq_base = IRQ_BOARD_START, + .scr_pll2cr = 0x0cc1, + .scr_gper = 0, + .gpio_base = -1, + .suspend = &eseries_tmio_suspend, + .resume = &eseries_tmio_resume, + .enable = &eseries_tmio_enable, + .disable = &eseries_tmio_disable, +}; + +static struct platform_device e800_tc6393xb_device = { + .name = "tc6393xb", + .id = -1, + .dev = { + .platform_data = &e800_tc6393xb_info, + }, + .num_resources = 2, + .resource = eseries_tmio_resources, +}; + /* ----------------------------------------------------------------------- */ static struct platform_device *devices[] __initdata = { &e800_fb_device, + &e800_tc6393xb_device, }; static void __init e800_init(void) { + clk_add_alias("CLK_CK3P6MI", &e800_tc6393xb_device.dev, + "GPIO11_CLK", NULL), + eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_udc_info(&e800_udc_mach_info); } diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index d28849b50a14..dfce7d5b659e 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -12,6 +12,9 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/platform_device.h> #include <asm/setup.h> #include <asm/mach/arch.h> @@ -21,8 +24,10 @@ #include <mach/hardware.h> #include <mach/eseries-gpio.h> #include <mach/udc.h> +#include <mach/irda.h> #include "generic.h" +#include "clock.h" /* Only e800 has 128MB RAM */ void __init eseries_fixup(struct machine_desc *desc, @@ -43,3 +48,122 @@ struct pxa2xx_udc_mach_info e7xx_udc_mach_info = { .gpio_pullup_inverted = 1 }; +static void e7xx_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) { + gpio_set_value(GPIO_E7XX_IR_OFF, 1); + pxa2xx_transceiver_mode(dev, mode); + } else { + pxa2xx_transceiver_mode(dev, mode); + gpio_set_value(GPIO_E7XX_IR_OFF, 0); + } +} + +int e7xx_irda_init(void) +{ + int ret; + + ret = gpio_request(GPIO_E7XX_IR_OFF, "IrDA power"); + if (ret) + goto out; + + ret = gpio_direction_output(GPIO_E7XX_IR_OFF, 0); + if (ret) + goto out; + + e7xx_irda_transceiver_mode(NULL, IR_SIRMODE | IR_OFF); +out: + return ret; +} + +static void e7xx_irda_shutdown(struct device *dev) +{ + e7xx_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF); + gpio_free(GPIO_E7XX_IR_OFF); +} + +struct pxaficp_platform_data e7xx_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = e7xx_irda_transceiver_mode, + .shutdown = e7xx_irda_shutdown, +}; + +int eseries_tmio_enable(struct platform_device *dev) +{ + /* Reset - bring SUSPEND high before PCLR */ + gpio_set_value(GPIO_ESERIES_TMIO_SUSPEND, 0); + gpio_set_value(GPIO_ESERIES_TMIO_PCLR, 0); + msleep(1); + gpio_set_value(GPIO_ESERIES_TMIO_SUSPEND, 1); + msleep(1); + gpio_set_value(GPIO_ESERIES_TMIO_PCLR, 1); + msleep(1); + return 0; +} + +int eseries_tmio_disable(struct platform_device *dev) +{ + gpio_set_value(GPIO_ESERIES_TMIO_SUSPEND, 0); + gpio_set_value(GPIO_ESERIES_TMIO_PCLR, 0); + return 0; +} + +int eseries_tmio_suspend(struct platform_device *dev) +{ + gpio_set_value(GPIO_ESERIES_TMIO_SUSPEND, 0); + return 0; +} + +int eseries_tmio_resume(struct platform_device *dev) +{ + gpio_set_value(GPIO_ESERIES_TMIO_SUSPEND, 1); + msleep(1); + return 0; +} + +void eseries_get_tmio_gpios(void) +{ + gpio_request(GPIO_ESERIES_TMIO_SUSPEND, NULL); + gpio_request(GPIO_ESERIES_TMIO_PCLR, NULL); + gpio_direction_output(GPIO_ESERIES_TMIO_SUSPEND, 0); + gpio_direction_output(GPIO_ESERIES_TMIO_PCLR, 0); +} + +/* TMIO controller uses the same resources on all e-series machines. */ +struct resource eseries_tmio_resources[] = { + [0] = { + .start = PXA_CS4_PHYS, + .end = PXA_CS4_PHYS + 0x1fffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_GPIO(GPIO_ESERIES_TMIO_IRQ), + .end = IRQ_GPIO(GPIO_ESERIES_TMIO_IRQ), + .flags = IORESOURCE_IRQ, + }, +}; + +/* Some e-series hardware cannot control the 32K clock */ +static void clk_32k_dummy(struct clk *clk) +{ +} + +static const struct clkops clk_32k_dummy_ops = { + .enable = clk_32k_dummy, + .disable = clk_32k_dummy, +}; + +static struct clk tmio_dummy_clk = { + .ops = &clk_32k_dummy_ops, + .rate = 32768, +}; + +static struct clk_lookup eseries_clkregs[] = { + INIT_CLKREG(&tmio_dummy_clk, NULL, "CLK_CK32K"), +}; + +void eseries_register_clks(void) +{ + clks_register(eseries_clkregs, ARRAY_SIZE(eseries_clkregs)); +} + diff --git a/arch/arm/mach-pxa/eseries.h b/arch/arm/mach-pxa/eseries.h index a83f88d4b6ad..5930f5e2a123 100644 --- a/arch/arm/mach-pxa/eseries.h +++ b/arch/arm/mach-pxa/eseries.h @@ -2,3 +2,15 @@ void __init eseries_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi); extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info; +extern struct pxaficp_platform_data e7xx_ficp_platform_data; +extern int e7xx_irda_init(void); + +extern int eseries_tmio_enable(struct platform_device *dev); +extern int eseries_tmio_disable(struct platform_device *dev); +extern int eseries_tmio_suspend(struct platform_device *dev); +extern int eseries_tmio_resume(struct platform_device *dev); +extern void eseries_get_tmio_gpios(void); +extern struct resource eseries_tmio_resources[]; +extern struct platform_device e300_tc6387xb_device; +extern void eseries_register_clks(void); + diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index cc3d850cc0b6..df5f822f3b6c 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -16,11 +16,14 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/pwm_backlight.h> +#include <linux/input.h> #include <asm/setup.h> #include <mach/pxafb.h> #include <mach/ohci.h> #include <mach/i2c.h> +#include <mach/hardware.h> +#include <mach/pxa27x_keypad.h> #include <mach/mfp-pxa27x.h> #include <mach/pxa-regs.h> @@ -101,120 +104,732 @@ static unsigned long ezx_pin_config[] __initdata = { GPIO44_BTUART_CTS, GPIO45_BTUART_RTS, - /* STUART */ - GPIO46_STUART_RXD, - GPIO47_STUART_TXD, + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, - /* For A780 support (connected with Neptune GSM chip) */ - GPIO30_USB_P3_2, /* ICL_TXENB */ - GPIO31_USB_P3_6, /* ICL_VPOUT */ - GPIO90_USB_P3_5, /* ICL_VPIN */ - GPIO91_USB_P3_1, /* ICL_XRXD */ - GPIO56_USB_P3_4, /* ICL_VMOUT */ - GPIO113_USB_P3_3, /* /ICL_VMIN */ + /* PCAP SSP */ + GPIO29_SSP1_SCLK, + GPIO25_SSP1_TXD, + GPIO26_SSP1_RXD, + GPIO24_GPIO, /* pcap chip select */ + GPIO1_GPIO, /* pcap interrupt */ + GPIO4_GPIO, /* WDI_AP */ + GPIO55_GPIO, /* SYS_RESTART */ + + /* MMC */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + GPIO11_GPIO, /* mmc detect */ + + /* usb to external transceiver */ + GPIO34_USB_P2_2, + GPIO35_USB_P2_1, + GPIO36_USB_P2_4, + GPIO39_USB_P2_6, + GPIO40_USB_P2_5, + GPIO53_USB_P2_3, + + /* usb to Neptune GSM chip */ + GPIO30_USB_P3_2, + GPIO31_USB_P3_6, + GPIO90_USB_P3_5, + GPIO91_USB_P3_1, + GPIO56_USB_P3_4, + GPIO113_USB_P3_3, +}; + +#if defined(CONFIG_MACH_EZX_A780) || defined(CONFIG_MACH_EZX_E680) +static unsigned long gen1_pin_config[] __initdata = { + /* flip / lockswitch */ + GPIO12_GPIO, + + /* bluetooth (bcm2035) */ + GPIO14_GPIO | WAKEUP_ON_LEVEL_HIGH, /* HOSTWAKE */ + GPIO48_GPIO, /* RESET */ + GPIO28_GPIO, /* WAKEUP */ + + /* Neptune handshake */ + GPIO0_GPIO | WAKEUP_ON_LEVEL_HIGH, /* BP_RDY */ + GPIO57_GPIO, /* AP_RDY */ + GPIO13_GPIO | WAKEUP_ON_LEVEL_HIGH, /* WDI */ + GPIO3_GPIO | WAKEUP_ON_LEVEL_HIGH, /* WDI2 */ + GPIO82_GPIO, /* RESET */ + GPIO99_GPIO, /* TC_MM_EN */ + + /* sound */ + GPIO52_SSP3_SCLK, + GPIO83_SSP3_SFRM, + GPIO81_SSP3_TXD, + GPIO89_SSP3_RXD, + + /* ssp2 pins to in */ + GPIO22_GPIO, /* SSP2_SCLK */ + GPIO37_GPIO, /* SSP2_SFRM */ + GPIO38_GPIO, /* SSP2_TXD */ + GPIO88_GPIO, /* SSP2_RXD */ + + /* camera */ + GPIO23_CIF_MCLK, + GPIO54_CIF_PCLK, + GPIO85_CIF_LV, + GPIO84_CIF_FV, + GPIO27_CIF_DD_0, + GPIO114_CIF_DD_1, + GPIO51_CIF_DD_2, + GPIO115_CIF_DD_3, + GPIO95_CIF_DD_4, + GPIO94_CIF_DD_5, + GPIO17_CIF_DD_6, + GPIO108_CIF_DD_7, + GPIO50_GPIO, /* CAM_EN */ + GPIO19_GPIO, /* CAM_RST */ + + /* EMU */ + GPIO120_GPIO, /* EMU_MUX1 */ + GPIO119_GPIO, /* EMU_MUX2 */ + GPIO86_GPIO, /* SNP_INT_CTL */ + GPIO87_GPIO, /* SNP_INT_IN */ +}; +#endif + +#if defined(CONFIG_MACH_EZX_A1200) || defined(CONFIG_MACH_EZX_A910) || \ + defined(CONFIG_MACH_EZX_E2) || defined(CONFIG_MACH_EZX_E6) +static unsigned long gen2_pin_config[] __initdata = { + /* flip / lockswitch */ + GPIO15_GPIO, + + /* EOC */ + GPIO10_GPIO, + + /* bluetooth (bcm2045) */ + GPIO13_GPIO | WAKEUP_ON_LEVEL_HIGH, /* HOSTWAKE */ + GPIO37_GPIO, /* RESET */ + GPIO57_GPIO, /* WAKEUP */ + + /* Neptune handshake */ + GPIO0_GPIO | WAKEUP_ON_LEVEL_HIGH, /* BP_RDY */ + GPIO96_GPIO, /* AP_RDY */ + GPIO3_GPIO | WAKEUP_ON_LEVEL_HIGH, /* WDI */ + GPIO116_GPIO, /* RESET */ + GPIO41_GPIO, /* BP_FLASH */ + + /* sound */ + GPIO52_SSP3_SCLK, + GPIO83_SSP3_SFRM, + GPIO81_SSP3_TXD, + GPIO82_SSP3_RXD, + + /* ssp2 pins to in */ + GPIO22_GPIO, /* SSP2_SCLK */ + GPIO14_GPIO, /* SSP2_SFRM */ + GPIO38_GPIO, /* SSP2_TXD */ + GPIO88_GPIO, /* SSP2_RXD */ + + /* camera */ + GPIO23_CIF_MCLK, + GPIO54_CIF_PCLK, + GPIO85_CIF_LV, + GPIO84_CIF_FV, + GPIO27_CIF_DD_0, + GPIO114_CIF_DD_1, + GPIO51_CIF_DD_2, + GPIO115_CIF_DD_3, + GPIO95_CIF_DD_4, + GPIO48_CIF_DD_5, + GPIO93_CIF_DD_6, + GPIO12_CIF_DD_7, + GPIO50_GPIO, /* CAM_EN */ + GPIO28_GPIO, /* CAM_RST */ + GPIO17_GPIO, /* CAM_FLASH */ +}; +#endif + +#ifdef CONFIG_MACH_EZX_A780 +static unsigned long a780_pin_config[] __initdata = { + /* keypad */ + GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + + /* attenuate sound */ + GPIO96_GPIO, +}; +#endif + +#ifdef CONFIG_MACH_EZX_E680 +static unsigned long e680_pin_config[] __initdata = { + /* keypad */ + GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO96_KP_DKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_DKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_DKIN_5 | WAKEUP_ON_LEVEL_HIGH, + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + + /* MIDI */ + GPIO79_GPIO, /* VA_SEL_BUL */ + GPIO80_GPIO, /* FLT_SEL_BUL */ + GPIO78_GPIO, /* MIDI_RESET */ + GPIO33_GPIO, /* MIDI_CS */ + GPIO15_GPIO, /* MIDI_IRQ */ + GPIO49_GPIO, /* MIDI_NPWE */ + GPIO18_GPIO, /* MIDI_RDY */ + + /* leds */ + GPIO46_GPIO, + GPIO47_GPIO, +}; +#endif + +#ifdef CONFIG_MACH_EZX_A1200 +static unsigned long a1200_pin_config[] __initdata = { + /* keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, +}; +#endif + +#ifdef CONFIG_MACH_EZX_A910 +static unsigned long a910_pin_config[] __initdata = { + /* keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, + + /* WLAN */ + GPIO89_GPIO, /* RESET */ + GPIO33_GPIO, /* WAKEUP */ + GPIO94_GPIO | WAKEUP_ON_LEVEL_HIGH, /* HOSTWAKE */ + + /* MMC CS */ + GPIO20_GPIO, +}; +#endif + +#ifdef CONFIG_MACH_EZX_E2 +static unsigned long e2_pin_config[] __initdata = { + /* keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, }; +#endif + +#ifdef CONFIG_MACH_EZX_E6 +static unsigned long e6_pin_config[] __initdata = { + /* keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, +}; +#endif + +/* KEYPAD */ +#ifdef CONFIG_MACH_EZX_A780 +static unsigned int a780_key_map[] = { + KEY(0, 0, KEY_SEND), + KEY(0, 1, KEY_BACK), + KEY(0, 2, KEY_END), + KEY(0, 3, KEY_PAGEUP), + KEY(0, 4, KEY_UP), + + KEY(1, 0, KEY_NUMERIC_1), + KEY(1, 1, KEY_NUMERIC_2), + KEY(1, 2, KEY_NUMERIC_3), + KEY(1, 3, KEY_SELECT), + KEY(1, 4, KEY_KPENTER), + + KEY(2, 0, KEY_NUMERIC_4), + KEY(2, 1, KEY_NUMERIC_5), + KEY(2, 2, KEY_NUMERIC_6), + KEY(2, 3, KEY_RECORD), + KEY(2, 4, KEY_LEFT), + + KEY(3, 0, KEY_NUMERIC_7), + KEY(3, 1, KEY_NUMERIC_8), + KEY(3, 2, KEY_NUMERIC_9), + KEY(3, 3, KEY_HOME), + KEY(3, 4, KEY_RIGHT), + + KEY(4, 0, KEY_NUMERIC_STAR), + KEY(4, 1, KEY_NUMERIC_0), + KEY(4, 2, KEY_NUMERIC_POUND), + KEY(4, 3, KEY_PAGEDOWN), + KEY(4, 4, KEY_DOWN), +}; + +static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { + .matrix_key_rows = 5, + .matrix_key_cols = 5, + .matrix_key_map = a780_key_map, + .matrix_key_map_size = ARRAY_SIZE(a780_key_map), + + .direct_key_map = { KEY_CAMERA }, + .direct_key_num = 1, + + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_A780 */ + +#ifdef CONFIG_MACH_EZX_E680 +static unsigned int e680_key_map[] = { + KEY(0, 0, KEY_UP), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_RESERVED), + KEY(0, 3, KEY_SEND), + + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_LEFT), + KEY(1, 2, KEY_PAGEUP), + KEY(1, 3, KEY_PAGEDOWN), + + KEY(2, 0, KEY_RESERVED), + KEY(2, 1, KEY_RESERVED), + KEY(2, 2, KEY_RESERVED), + KEY(2, 3, KEY_KPENTER), +}; + +static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { + .matrix_key_rows = 3, + .matrix_key_cols = 4, + .matrix_key_map = e680_key_map, + .matrix_key_map_size = ARRAY_SIZE(e680_key_map), + + .direct_key_map = { + KEY_CAMERA, + KEY_RESERVED, + KEY_RESERVED, + KEY_F1, + KEY_CANCEL, + KEY_F2, + }, + .direct_key_num = 6, + + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_E680 */ + +#ifdef CONFIG_MACH_EZX_A1200 +static unsigned int a1200_key_map[] = { + KEY(0, 0, KEY_RESERVED), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_PAGEDOWN), + KEY(0, 3, KEY_RESERVED), + KEY(0, 4, KEY_RESERVED), + KEY(0, 5, KEY_RESERVED), + + KEY(1, 0, KEY_RESERVED), + KEY(1, 1, KEY_DOWN), + KEY(1, 2, KEY_CAMERA), + KEY(1, 3, KEY_RESERVED), + KEY(1, 4, KEY_RESERVED), + KEY(1, 5, KEY_RESERVED), + + KEY(2, 0, KEY_RESERVED), + KEY(2, 1, KEY_KPENTER), + KEY(2, 2, KEY_RECORD), + KEY(2, 3, KEY_RESERVED), + KEY(2, 4, KEY_RESERVED), + KEY(2, 5, KEY_SELECT), + + KEY(3, 0, KEY_RESERVED), + KEY(3, 1, KEY_UP), + KEY(3, 2, KEY_SEND), + KEY(3, 3, KEY_RESERVED), + KEY(3, 4, KEY_RESERVED), + KEY(3, 5, KEY_RESERVED), + + KEY(4, 0, KEY_RESERVED), + KEY(4, 1, KEY_LEFT), + KEY(4, 2, KEY_PAGEUP), + KEY(4, 3, KEY_RESERVED), + KEY(4, 4, KEY_RESERVED), + KEY(4, 5, KEY_RESERVED), +}; + +static struct pxa27x_keypad_platform_data a1200_keypad_platform_data = { + .matrix_key_rows = 5, + .matrix_key_cols = 6, + .matrix_key_map = a1200_key_map, + .matrix_key_map_size = ARRAY_SIZE(a1200_key_map), + + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_A1200 */ + +#ifdef CONFIG_MACH_EZX_E6 +static unsigned int e6_key_map[] = { + KEY(0, 0, KEY_RESERVED), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_PAGEDOWN), + KEY(0, 3, KEY_RESERVED), + KEY(0, 4, KEY_RESERVED), + KEY(0, 5, KEY_NEXTSONG), + + KEY(1, 0, KEY_RESERVED), + KEY(1, 1, KEY_DOWN), + KEY(1, 2, KEY_PROG1), + KEY(1, 3, KEY_RESERVED), + KEY(1, 4, KEY_RESERVED), + KEY(1, 5, KEY_RESERVED), + + KEY(2, 0, KEY_RESERVED), + KEY(2, 1, KEY_ENTER), + KEY(2, 2, KEY_CAMERA), + KEY(2, 3, KEY_RESERVED), + KEY(2, 4, KEY_RESERVED), + KEY(2, 5, KEY_WWW), + + KEY(3, 0, KEY_RESERVED), + KEY(3, 1, KEY_UP), + KEY(3, 2, KEY_SEND), + KEY(3, 3, KEY_RESERVED), + KEY(3, 4, KEY_RESERVED), + KEY(3, 5, KEY_PLAYPAUSE), + + KEY(4, 0, KEY_RESERVED), + KEY(4, 1, KEY_LEFT), + KEY(4, 2, KEY_PAGEUP), + KEY(4, 3, KEY_RESERVED), + KEY(4, 4, KEY_RESERVED), + KEY(4, 5, KEY_PREVIOUSSONG), +}; + +static struct pxa27x_keypad_platform_data e6_keypad_platform_data = { + .matrix_key_rows = 5, + .matrix_key_cols = 6, + .matrix_key_map = e6_key_map, + .matrix_key_map_size = ARRAY_SIZE(e6_key_map), -static void __init ezx_init(void) + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_E6 */ + +#ifdef CONFIG_MACH_EZX_A910 +static unsigned int a910_key_map[] = { + KEY(0, 0, KEY_NUMERIC_6), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_PAGEDOWN), + KEY(0, 3, KEY_KPENTER), + KEY(0, 4, KEY_NUMERIC_5), + KEY(0, 5, KEY_CAMERA), + + KEY(1, 0, KEY_NUMERIC_8), + KEY(1, 1, KEY_DOWN), + KEY(1, 2, KEY_RESERVED), + KEY(1, 3, KEY_F1), /* Left SoftKey */ + KEY(1, 4, KEY_NUMERIC_STAR), + KEY(1, 5, KEY_RESERVED), + + KEY(2, 0, KEY_NUMERIC_7), + KEY(2, 1, KEY_NUMERIC_9), + KEY(2, 2, KEY_RECORD), + KEY(2, 3, KEY_F2), /* Right SoftKey */ + KEY(2, 4, KEY_BACK), + KEY(2, 5, KEY_SELECT), + + KEY(3, 0, KEY_NUMERIC_2), + KEY(3, 1, KEY_UP), + KEY(3, 2, KEY_SEND), + KEY(3, 3, KEY_NUMERIC_0), + KEY(3, 4, KEY_NUMERIC_1), + KEY(3, 5, KEY_RECORD), + + KEY(4, 0, KEY_NUMERIC_4), + KEY(4, 1, KEY_LEFT), + KEY(4, 2, KEY_PAGEUP), + KEY(4, 3, KEY_NUMERIC_POUND), + KEY(4, 4, KEY_NUMERIC_3), + KEY(4, 5, KEY_RESERVED), +}; + +static struct pxa27x_keypad_platform_data a910_keypad_platform_data = { + .matrix_key_rows = 5, + .matrix_key_cols = 6, + .matrix_key_map = a910_key_map, + .matrix_key_map_size = ARRAY_SIZE(a910_key_map), + + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_A910 */ + +#ifdef CONFIG_MACH_EZX_E2 +static unsigned int e2_key_map[] = { + KEY(0, 0, KEY_NUMERIC_6), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_NUMERIC_9), + KEY(0, 3, KEY_NEXTSONG), + KEY(0, 4, KEY_NUMERIC_5), + KEY(0, 5, KEY_F1), /* Left SoftKey */ + + KEY(1, 0, KEY_NUMERIC_8), + KEY(1, 1, KEY_DOWN), + KEY(1, 2, KEY_RESERVED), + KEY(1, 3, KEY_PAGEUP), + KEY(1, 4, KEY_NUMERIC_STAR), + KEY(1, 5, KEY_F2), /* Right SoftKey */ + + KEY(2, 0, KEY_NUMERIC_7), + KEY(2, 1, KEY_KPENTER), + KEY(2, 2, KEY_RECORD), + KEY(2, 3, KEY_PAGEDOWN), + KEY(2, 4, KEY_BACK), + KEY(2, 5, KEY_NUMERIC_0), + + KEY(3, 0, KEY_NUMERIC_2), + KEY(3, 1, KEY_UP), + KEY(3, 2, KEY_SEND), + KEY(3, 3, KEY_PLAYPAUSE), + KEY(3, 4, KEY_NUMERIC_1), + KEY(3, 5, KEY_SOUND), /* Music SoftKey */ + + KEY(4, 0, KEY_NUMERIC_4), + KEY(4, 1, KEY_LEFT), + KEY(4, 2, KEY_NUMERIC_POUND), + KEY(4, 3, KEY_PREVIOUSSONG), + KEY(4, 4, KEY_NUMERIC_3), + KEY(4, 5, KEY_RESERVED), +}; + +static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { + .matrix_key_rows = 5, + .matrix_key_cols = 6, + .matrix_key_map = e2_key_map, + .matrix_key_map_size = ARRAY_SIZE(e2_key_map), + + .debounce_interval = 30, +}; +#endif /* CONFIG_MACH_EZX_E2 */ + +#ifdef CONFIG_MACH_EZX_A780 +static void __init a780_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen1_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(a780_pin_config)); + pxa_set_i2c_info(NULL); - if (machine_is_ezx_a780() || machine_is_ezx_e680()) - set_pxa_fb_info(&ezx_fb_info_1); - else - set_pxa_fb_info(&ezx_fb_info_2); - platform_add_devices(devices, ARRAY_SIZE(devices)); -} + set_pxa_fb_info(&ezx_fb_info_1); -static void __init ezx_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - /* We have two ram chips. First one with 32MB at 0xA0000000 and a second - * 16MB one at 0xAC000000 - */ - mi->nr_banks = 2; - mi->bank[0].start = 0xa0000000; - mi->bank[0].node = 0; - mi->bank[0].size = (32*1024*1024); - mi->bank[1].start = 0xac000000; - mi->bank[1].node = 1; - mi->bank[1].size = (16*1024*1024); + pxa_set_keypad_info(&a780_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); } -#ifdef CONFIG_MACH_EZX_A780 MACHINE_START(EZX_A780, "Motorola EZX A780") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = a780_init, MACHINE_END #endif #ifdef CONFIG_MACH_EZX_E680 +static struct i2c_board_info __initdata e680_i2c_board_info[] = { + { I2C_BOARD_INFO("tea5767", 0x81) }, +}; + +static void __init e680_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen1_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(e680_pin_config)); + + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(e680_i2c_board_info)); + + set_pxa_fb_info(&ezx_fb_info_1); + + pxa_set_keypad_info(&e680_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + MACHINE_START(EZX_E680, "Motorola EZX E680") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = e680_init, MACHINE_END #endif #ifdef CONFIG_MACH_EZX_A1200 +static struct i2c_board_info __initdata a1200_i2c_board_info[] = { + { I2C_BOARD_INFO("tea5767", 0x81) }, +}; + +static void __init a1200_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen2_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(a1200_pin_config)); + + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(a1200_i2c_board_info)); + + set_pxa_fb_info(&ezx_fb_info_2); + + pxa_set_keypad_info(&a1200_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + MACHINE_START(EZX_A1200, "Motorola EZX A1200") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = a1200_init, MACHINE_END #endif #ifdef CONFIG_MACH_EZX_A910 +static void __init a910_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen2_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(a910_pin_config)); + + pxa_set_i2c_info(NULL); + + set_pxa_fb_info(&ezx_fb_info_2); + + pxa_set_keypad_info(&a910_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + MACHINE_START(EZX_A910, "Motorola EZX A910") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = a910_init, MACHINE_END #endif #ifdef CONFIG_MACH_EZX_E6 +static struct i2c_board_info __initdata e6_i2c_board_info[] = { + { I2C_BOARD_INFO("tea5767", 0x81) }, +}; + +static void __init e6_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen2_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(e6_pin_config)); + + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(e6_i2c_board_info)); + + set_pxa_fb_info(&ezx_fb_info_2); + + pxa_set_keypad_info(&e6_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + MACHINE_START(EZX_E6, "Motorola EZX E6") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = e6_init, MACHINE_END #endif #ifdef CONFIG_MACH_EZX_E2 +static struct i2c_board_info __initdata e2_i2c_board_info[] = { + { I2C_BOARD_INFO("tea5767", 0x81) }, +}; + +static void __init e2_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(gen2_pin_config)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(e2_pin_config)); + + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(e2_i2c_board_info)); + + set_pxa_fb_info(&ezx_fb_info_2); + + pxa_set_keypad_info(&e2_keypad_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + MACHINE_START(EZX_E2, "Motorola EZX E2") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .fixup = ezx_fixup, .boot_params = 0xa0000100, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, - .init_machine = &ezx_init, + .init_machine = e2_init, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 85ed0b33331f..0ccc91c92c44 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -24,6 +24,7 @@ #include <asm/system.h> #include <asm/pgtable.h> #include <asm/mach/map.h> +#include <asm/mach-types.h> #include <mach/pxa-regs.h> #include <mach/reset.h> @@ -39,6 +40,21 @@ void clear_reset_status(unsigned int mask) pxa3xx_clear_reset_status(mask); } +unsigned long get_clock_tick_rate(void) +{ + unsigned long clock_tick_rate; + + if (cpu_is_pxa25x()) + clock_tick_rate = 3686400; + else if (machine_is_mainstone()) + clock_tick_rate = 3249600; + else + clock_tick_rate = 3250000; + + return clock_tick_rate; +} +EXPORT_SYMBOL(get_clock_tick_rate); + /* * Get the clock frequency as reflected by CCCR and the turbo flag. * We assume these values have been applied via a fcs. diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 14930cf8be7b..5fec1e479cb3 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c @@ -25,6 +25,18 @@ #include "generic.h" +#define GPIO0_BASE ((void __iomem *)io_p2v(0x40E00000)) +#define GPIO1_BASE ((void __iomem *)io_p2v(0x40E00004)) +#define GPIO2_BASE ((void __iomem *)io_p2v(0x40E00008)) +#define GPIO3_BASE ((void __iomem *)io_p2v(0x40E00100)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 struct pxa_gpio_chip { struct gpio_chip chip; @@ -33,6 +45,18 @@ struct pxa_gpio_chip { int pxa_last_gpio; +#ifdef CONFIG_CPU_PXA26x +/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static int __gpio_is_inverted(unsigned gpio) +{ + return cpu_is_pxa25x() && gpio > 85; +} +#else +#define __gpio_is_inverted(gpio) (0) +#endif + /* * Configure pins for GPIO or other functions */ @@ -75,7 +99,10 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) gpdr = pxa->regbase + GPDR_OFFSET; local_irq_save(flags); value = __raw_readl(gpdr); - value &= ~mask; + if (__gpio_is_inverted(chip->base + offset)) + value |= mask; + else + value &= ~mask; __raw_writel(value, gpdr); local_irq_restore(flags); @@ -97,7 +124,10 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, gpdr = pxa->regbase + GPDR_OFFSET; local_irq_save(flags); tmp = __raw_readl(gpdr); - tmp |= mask; + if (__gpio_is_inverted(chip->base + offset)) + tmp &= ~mask; + else + tmp |= mask; __raw_writel(tmp, gpdr); local_irq_restore(flags); @@ -173,10 +203,17 @@ static unsigned long GPIO_IRQ_mask[4]; */ static int __gpio_is_occupied(unsigned gpio) { - if (cpu_is_pxa25x() || cpu_is_pxa27x()) - return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2)); - else - return 0; + if (cpu_is_pxa27x() || cpu_is_pxa25x()) { + int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; + int dir = GPDR(gpio) & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + return af != 1 || dir == 0; + else + return af != 0 || dir != 0; + } + + return 0; } static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) @@ -190,9 +227,8 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) /* Don't mess with enabled GPIOs using preconfigured edges or * GPIOs set to alternate function or to output during probe */ - if ((GPIO_IRQ_rising_edge[idx] | - GPIO_IRQ_falling_edge[idx] | - GPDR(gpio)) & GPIO_bit(gpio)) + if ((GPIO_IRQ_rising_edge[idx] & GPIO_bit(gpio)) || + (GPIO_IRQ_falling_edge[idx] & GPIO_bit(gpio))) return 0; if (__gpio_is_occupied(gpio)) @@ -201,7 +237,10 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } - GPDR(gpio) &= ~GPIO_bit(gpio); + if (__gpio_is_inverted(gpio)) + GPDR(gpio) |= GPIO_bit(gpio); + else + GPDR(gpio) &= ~GPIO_bit(gpio); if (type & IRQ_TYPE_EDGE_RISING) __set_bit(gpio, GPIO_IRQ_rising_edge); diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index d8962a0fb98d..e296ce11658c 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -184,15 +184,22 @@ static unsigned long gumstix_pin_config[] __initdata = { GPIO6_MMC_CLK, GPIO53_MMC_CLK, GPIO8_MMC_CS0, - /* these are used by AM200EPD */ - GPIO51_GPIO, - GPIO49_GPIO, - GPIO48_GPIO, - GPIO32_GPIO, - GPIO17_GPIO, - GPIO16_GPIO, }; +int __attribute__((weak)) am200_init(void) +{ + return 0; +} + +static void __init carrier_board_init(void) +{ + /* + * put carrier/expansion board init here if + * they cannot be detected programatically + */ + am200_init(); +} + static void __init gumstix_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config)); @@ -201,6 +208,7 @@ static void __init gumstix_init(void) gumstix_udc_init(); gumstix_mmc_init(); (void) platform_add_devices(devices, ARRAY_SIZE(devices)); + carrier_board_init(); } MACHINE_START(GUMSTIX, "Gumstix") diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c new file mode 100644 index 000000000000..da6e4422c0f3 --- /dev/null +++ b/arch/arm/mach-pxa/h5000.c @@ -0,0 +1,200 @@ +/* + * Hardware definitions for HP iPAQ h5xxx Handheld Computers + * + * Copyright 2000-2003 Hewlett-Packard Company. + * Copyright 2002 Jamey Hicks <jamey.hicks@hp.com> + * Copyright 2004-2005 Phil Blundell <pb@handhelds.org> + * Copyright 2007-2008 Anton Vorontsov <cbouatmailru@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Author: Jamey Hicks. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <mach/h5000.h> +#include <mach/pxa-regs.h> +#include <mach/pxa2xx-regs.h> +#include <mach/mfp-pxa25x.h> +#include <mach/udc.h> +#include "generic.h" + +/* + * Flash + */ + +static struct mtd_partition h5000_flash0_partitions[] = { + { + .name = "bootldr", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "root", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + }, +}; + +static struct mtd_partition h5000_flash1_partitions[] = { + { + .name = "second root", + .size = SZ_16M - 0x00040000, + .offset = 0, + }, + { + .name = "asset", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data h5000_flash0_data = { + .width = 4, + .parts = h5000_flash0_partitions, + .nr_parts = ARRAY_SIZE(h5000_flash0_partitions), +}; + +static struct physmap_flash_data h5000_flash1_data = { + .width = 4, + .parts = h5000_flash1_partitions, + .nr_parts = ARRAY_SIZE(h5000_flash1_partitions), +}; + +static struct resource h5000_flash0_resources = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, +}; + +static struct resource h5000_flash1_resources = { + .start = PXA_CS0_PHYS + SZ_32M, + .end = PXA_CS0_PHYS + SZ_32M + SZ_16M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, +}; + +static struct platform_device h5000_flash[] = { + { + .name = "physmap-flash", + .id = 0, + .resource = &h5000_flash0_resources, + .num_resources = 1, + .dev = { + .platform_data = &h5000_flash0_data, + }, + }, + { + .name = "physmap-flash", + .id = 1, + .resource = &h5000_flash1_resources, + .num_resources = 1, + .dev = { + .platform_data = &h5000_flash1_data, + }, + }, +}; + +/* + * USB Device Controller + */ + +static struct pxa2xx_udc_mach_info h5000_udc_mach_info __initdata = { + .gpio_pullup = H5000_GPIO_USB_PULLUP, +}; + +/* + * GPIO setup + */ + +static unsigned long h5000_pin_config[] __initdata = { + /* Crystal and Clock Signals */ + GPIO12_32KHz, + + /* SDRAM and Static Memory I/O Signals */ + GPIO15_nCS_1, + GPIO78_nCS_2, + GPIO79_nCS_3, + GPIO80_nCS_4, + + /* FFUART */ + GPIO34_FFUART_RXD, + GPIO35_FFUART_CTS, + GPIO36_FFUART_DCD, + GPIO37_FFUART_DSR, + GPIO38_FFUART_RI, + GPIO39_FFUART_TXD, + GPIO40_FFUART_DTR, + GPIO41_FFUART_RTS, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + /* SSP1 */ + GPIO23_SSP1_SCLK, + GPIO25_SSP1_TXD, + GPIO26_SSP1_RXD, +}; + +/* + * Localbus setup: + * CS0: Flash; + * CS1: MediaQ chip, select 16-bit bus and vlio; + * CS5: SAMCOP. + */ + +static void fix_msc(void) +{ + MSC0 = 0x129c24f2; + MSC1 = 0x7ff424fa; + MSC2 = 0x7ff47ff4; + + MDREFR |= 0x02080000; +} + +/* + * Platform devices + */ + +static struct platform_device *devices[] __initdata = { + &h5000_flash[0], + &h5000_flash[1], +}; + +static void __init h5000_init(void) +{ + fix_msc(); + + pxa2xx_mfp_config(ARRAY_AND_SIZE(h5000_pin_config)); + pxa_set_udc_info(&h5000_udc_mach_info); + platform_add_devices(ARRAY_AND_SIZE(devices)); +} + +MACHINE_START(H5400, "HP iPAQ H5000") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .timer = &pxa_timer, + .init_machine = h5000_init, +MACHINE_END diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c new file mode 100644 index 000000000000..364c5e271330 --- /dev/null +++ b/arch/arm/mach-pxa/imote2.c @@ -0,0 +1,575 @@ +/* + * linux/arch/arm/mach-pxa/imote2.c + * + * Author: Ed C. Epp + * Created: Nov 05, 2002 + * Copyright: Intel Corp. + * + * Modified 2008: Jonathan Cameron + * + * The Imote2 is a wireless sensor node platform sold + * by Crossbow (www.xbow.com). + */ + +#include <linux/init.h> +#include <linux/device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/platform_device.h> +#include <linux/regulator/machine.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/mfd/da903x.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/flash.h> + +#include <mach/i2c.h> +#include <mach/pxa-regs.h> +#include <mach/pxa2xx-regs.h> +#include <mach/mfp-pxa27x.h> +#include <mach/regs-ssp.h> +#include <mach/udc.h> +#include <mach/mmc.h> +#include <mach/pxa2xx_spi.h> +#include <mach/pxa27x-udc.h> + +#include "devices.h" +#include "generic.h" + +static unsigned long imote2_pin_config[] __initdata = { + + /* Device Identification for wakeup*/ + GPIO102_GPIO, + + /* Button */ + GPIO91_GPIO, + + /* DA9030 */ + GPIO1_GPIO, + + /* MMC */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + + /* 802.15.4 radio - driver out of mainline */ + GPIO22_GPIO, /* CC_RSTN */ + GPIO114_GPIO, /* CC_FIFO */ + GPIO116_GPIO, /* CC_CCA */ + GPIO0_GPIO, /* CC_FIFOP */ + GPIO16_GPIO, /* CCSFD */ + GPIO39_GPIO, /* CSn */ + GPIO115_GPIO, /* Power enable */ + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* SSP 3 - 802.15.4 radio */ + GPIO39_GPIO, /* Chip Select */ + GPIO34_SSP3_SCLK, + GPIO35_SSP3_TXD, + GPIO41_SSP3_RXD, + + /* SSP 2 - to daughter boards */ + GPIO37_GPIO, /* Chip Select */ + GPIO36_SSP2_SCLK, + GPIO38_SSP2_TXD, + GPIO11_SSP2_RXD, + + /* SSP 1 - to daughter boards */ + GPIO24_GPIO, /* Chip Select */ + GPIO23_SSP1_SCLK, + GPIO25_SSP1_TXD, + GPIO26_SSP1_RXD, + + /* BTUART Basic Connector*/ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + /* STUART Serial console via debug board*/ + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, + + /* Basic sensor board */ + GPIO96_GPIO, /* accelerometer interrupt */ + GPIO99_GPIO, /* ADC interrupt */ + + /* Connector pins specified as gpios */ + GPIO94_GPIO, /* large basic connector pin 14 */ + GPIO10_GPIO, /* large basic connector pin 23 */ + + /* LEDS */ + GPIO103_GPIO, /* red led */ + GPIO104_GPIO, /* green led */ + GPIO105_GPIO, /* blue led */ +}; + +static struct gpio_led imote2_led_pins[] = { + { + .name = "imote2:red", + .gpio = 103, + .active_low = 1, + }, { + .name = "imote2:green", + .gpio = 104, + .active_low = 1, + }, { + .name = "imote2:blue", + .gpio = 105, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data imote2_led_data = { + .num_leds = ARRAY_SIZE(imote2_led_pins), + .leds = imote2_led_pins, +}; + +static struct platform_device imote2_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &imote2_led_data, + }, +}; + +/* Reverse engineered partly from Platformx drivers */ +enum imote2_ldos{ + vcc_vref, + vcc_cc2420, + vcc_mica, + vcc_bt, + /* The two voltages available to sensor boards */ + vcc_sensor_1_8, + vcc_sensor_3, + + vcc_sram_ext, /* directly connected to the pxa271 */ + vcc_pxa_pll, + vcc_pxa_usim, /* Reference voltage for certain gpios */ + vcc_pxa_mem, + vcc_pxa_flash, + vcc_pxa_core, /*Dc-Dc buck not yet supported */ + vcc_lcd, + vcc_bb, + vcc_bbio, + vcc_io, /* cc2420 802.15.4 radio and pxa vcc_io ?*/ +}; + +/* The values of the various regulator constraints are obviously dependent + * on exactly what is wired to each ldo. Unfortunately this information is + * not generally available. More information has been requested from Xbow + * but as of yet they haven't been forthcoming. + * + * Some of these are clearly Stargate 2 related (no way of plugging + * in an lcd on the IM2 for example!). + */ +static struct regulator_init_data imote2_ldo_init_data[] = { + [vcc_bbio] = { + .constraints = { /* board default 1.8V */ + .name = "vcc_bbio", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_bb] = { + .constraints = { /* board default 2.8V */ + .name = "vcc_bb", + .min_uV = 2700000, + .max_uV = 3000000, + }, + }, + [vcc_pxa_flash] = { + .constraints = {/* default is 1.8V */ + .name = "vcc_pxa_flash", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_cc2420] = { /* also vcc_io */ + .constraints = { + /* board default is 2.8V */ + .name = "vcc_cc2420", + .min_uV = 2700000, + .max_uV = 3300000, + }, + }, + [vcc_vref] = { /* Reference for what? */ + .constraints = { /* default 1.8V */ + .name = "vcc_vref", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_sram_ext] = { + .constraints = { /* default 2.8V */ + .name = "vcc_sram_ext", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_mica] = { + .constraints = { /* default 2.8V */ + .name = "vcc_mica", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_bt] = { + .constraints = { /* default 2.8V */ + .name = "vcc_bt", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_lcd] = { + .constraints = { /* default 2.8V */ + .name = "vcc_lcd", + .min_uV = 2700000, + .max_uV = 3300000, + }, + }, + [vcc_io] = { /* Same or higher than everything + * bar vccbat and vccusb */ + .constraints = { /* default 2.8V */ + .name = "vcc_io", + .min_uV = 2692000, + .max_uV = 3300000, + }, + }, + [vcc_sensor_1_8] = { + .constraints = { /* default 1.8V */ + .name = "vcc_sensor_1_8", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_sensor_3] = { /* curiously default 2.8V */ + .constraints = { + .name = "vcc_sensor_3", + .min_uV = 2800000, + .max_uV = 3000000, + }, + }, + [vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/ + .constraints = { + .name = "vcc_pxa_pll", + .min_uV = 1170000, + .max_uV = 1430000, + }, + }, + [vcc_pxa_usim] = { + .constraints = { /* default 1.8V */ + .name = "vcc_pxa_usim", + .min_uV = 1710000, + .max_uV = 2160000, + }, + }, + [vcc_pxa_mem] = { + .constraints = { /* default 1.8V */ + .name = "vcc_pxa_mem", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, +}; + +static struct da903x_subdev_info imote2_da9030_subdevs[] = { + { + .name = "da903x-regulator", + .id = DA9030_ID_LDO2, + .platform_data = &imote2_ldo_init_data[vcc_bbio], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO3, + .platform_data = &imote2_ldo_init_data[vcc_bb], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO4, + .platform_data = &imote2_ldo_init_data[vcc_pxa_flash], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO5, + .platform_data = &imote2_ldo_init_data[vcc_cc2420], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO6, + .platform_data = &imote2_ldo_init_data[vcc_vref], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO7, + .platform_data = &imote2_ldo_init_data[vcc_sram_ext], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO8, + .platform_data = &imote2_ldo_init_data[vcc_mica], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO9, + .platform_data = &imote2_ldo_init_data[vcc_bt], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO10, + .platform_data = &imote2_ldo_init_data[vcc_sensor_1_8], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO11, + .platform_data = &imote2_ldo_init_data[vcc_sensor_3], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO12, + .platform_data = &imote2_ldo_init_data[vcc_lcd], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO15, + .platform_data = &imote2_ldo_init_data[vcc_pxa_pll], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO17, + .platform_data = &imote2_ldo_init_data[vcc_pxa_usim], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO18, + .platform_data = &imote2_ldo_init_data[vcc_io], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO19, + .platform_data = &imote2_ldo_init_data[vcc_pxa_mem], + }, +}; + +static struct da903x_platform_data imote2_da9030_pdata = { + .num_subdevs = ARRAY_SIZE(imote2_da9030_subdevs), + .subdevs = imote2_da9030_subdevs, +}; + +/* As the the imote2 doesn't currently have a conventional SD slot + * there is no option to hotplug cards, making all this rather simple + */ +static int imote2_mci_get_ro(struct device *dev) +{ + return 0; +} + +/* Rather simple case as hotplugging not possible */ +static struct pxamci_platform_data imote2_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* default anyway */ + .get_ro = imote2_mci_get_ro, +}; + +static struct mtd_partition imote2flash_partitions[] = { + { + .name = "Bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "Kernel", + .size = 0x00200000, + .offset = 0x00040000, + .mask_flags = 0, + }, { + .name = "Filesystem", + .size = 0x01DC0000, + .offset = 0x00240000, + .mask_flags = 0, + }, +}; + +static struct resource flash_resources = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct flash_platform_data imote2_flash_data = { + .map_name = "cfi_probe", + .parts = imote2flash_partitions, + .nr_parts = ARRAY_SIZE(imote2flash_partitions), + .name = "PXA27xOnChipROM", + .width = 2, +}; + +static struct platform_device imote2_flash_device = { + .name = "pxa2xx-flash", + .id = 0, + .dev = { + .platform_data = &imote2_flash_data, + }, + .resource = &flash_resources, + .num_resources = 1, +}; + +/* Some of the drivers here are out of kernel at the moment (parts of IIO) + * and it may be a while before they are in the mainline. + */ +static struct i2c_board_info __initdata imote2_i2c_board_info[] = { + { /* UCAM sensor board */ + .type = "max1238", + .addr = 0x35, + }, { /* ITS400 Sensor board only */ + .type = "max1363", + .addr = 0x34, + /* Through a nand gate - Also beware, on V2 sensor board the + * pull up resistors are missing. + */ + .irq = IRQ_GPIO(99), + }, { /* ITS400 Sensor board only */ + .type = "tsl2561", + .addr = 0x49, + /* Through a nand gate - Also beware, on V2 sensor board the + * pull up resistors are missing. + */ + .irq = IRQ_GPIO(99), + }, { /* ITS400 Sensor board only */ + .type = "tmp175", + .addr = 0x4A, + .irq = IRQ_GPIO(96), + }, +}; + +static struct i2c_board_info __initdata imote2_pwr_i2c_board_info[] = { + { + .type = "da9030", + .addr = 0x49, + .platform_data = &imote2_da9030_pdata, + .irq = gpio_to_irq(1), + }, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_0_info = { + .num_chipselect = 1, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_1_info = { + .num_chipselect = 1, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_2_info = { + .num_chipselect = 1, +}; + +/* Patch posted by Eric Miao <eric.miao@marvell.com> will remove + * the need for these functions. + */ +static void spi1control(u32 command) +{ + gpio_set_value(24, command & PXA2XX_CS_ASSERT ? 0 : 1); +}; + +static void spi3control(u32 command) +{ + gpio_set_value(39, command & PXA2XX_CS_ASSERT ? 0 : 1); +}; + +static struct pxa2xx_spi_chip staccel_chip_info = { + .tx_threshold = 8, + .rx_threshold = 8, + .dma_burst_size = 8, + .timeout = 235, + .cs_control = spi1control, +}; + +static struct pxa2xx_spi_chip cc2420_info = { + .tx_threshold = 8, + .rx_threshold = 8, + .dma_burst_size = 8, + .timeout = 235, + .cs_control = spi3control, +}; + +static struct spi_board_info spi_board_info[] __initdata = { + { /* Driver in IIO */ + .modalias = "lis3l02dq", + .max_speed_hz = 8000000,/* 8MHz max spi frequency at 3V */ + .bus_num = 1, + .chip_select = 0, + .controller_data = &staccel_chip_info, + .irq = IRQ_GPIO(96), + }, { /* Driver out of kernel as it needs considerable rewriting */ + .modalias = "cc2420", + .max_speed_hz = 6500000, + .bus_num = 3, + .chip_select = 0, + .controller_data = &cc2420_info, + }, +}; + +static void im2_udc_command(int cmd) +{ + switch (cmd) { + case PXA2XX_UDC_CMD_CONNECT: + UP2OCR |= UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE; + break; + case PXA2XX_UDC_CMD_DISCONNECT: + UP2OCR &= ~(UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE); + break; + } +} + +static struct pxa2xx_udc_mach_info imote2_udc_info __initdata = { + .udc_command = im2_udc_command, +}; + +static struct platform_device *imote2_devices[] = { + &imote2_flash_device, + &imote2_leds, +}; + +static struct i2c_pxa_platform_data i2c_pwr_pdata = { + .fast_mode = 1, +}; + +static struct i2c_pxa_platform_data i2c_pdata = { + .fast_mode = 1, +}; + +static void __init imote2_init(void) +{ + + pxa2xx_mfp_config(ARRAY_AND_SIZE(imote2_pin_config)); + /* SPI chip select directions - all other directions should + * be handled by drivers.*/ + gpio_direction_output(37, 0); + gpio_direction_output(24, 0); + gpio_direction_output(39, 0); + + platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices)); + + pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info); + pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info); + pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info); + + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + + i2c_register_board_info(0, imote2_i2c_board_info, + ARRAY_SIZE(imote2_i2c_board_info)); + i2c_register_board_info(1, imote2_pwr_i2c_board_info, + ARRAY_SIZE(imote2_pwr_i2c_board_info)); + + pxa27x_set_i2c_power_info(&i2c_pwr_pdata); + pxa_set_i2c_info(&i2c_pdata); + + pxa_set_mci_info(&imote2_mci_platform_data); + pxa_set_udc_info(&imote2_udc_info); +} + +MACHINE_START(INTELMOTE2, "IMOTE 2") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = imote2_init, + .boot_params = 0xA0000100, +MACHINE_END diff --git a/arch/arm/mach-pxa/include/mach/clkdev.h b/arch/arm/mach-pxa/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h index 955bfe606067..7804637a6df3 100644 --- a/arch/arm/mach-pxa/include/mach/dma.h +++ b/arch/arm/mach-pxa/include/mach/dma.h @@ -30,10 +30,6 @@ typedef enum { DMA_PRIO_LOW = 2 } pxa_dma_prio; -#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) -#define HAVE_ARCH_PCI_SET_DMA_MASK 1 -#endif - /* * DMA registration */ diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h index 4c90b1310270..efbd2aa9ecec 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h +++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h @@ -43,8 +43,10 @@ #define GPIO_E800_PCMCIA_PWR1 73 /* e7xx IrDA power control */ -#define GPIO_E7XX_IR_ON 38 +#define GPIO_E7XX_IR_OFF 38 /* ASIC related GPIOs */ #define GPIO_ESERIES_TMIO_IRQ 5 +#define GPIO_ESERIES_TMIO_PCLR 19 +#define GPIO_ESERIES_TMIO_SUSPEND 45 #define GPIO_E800_ANGELX_IRQ 8 diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h index 42ee1956750e..099f54a41de4 100644 --- a/arch/arm/mach-pxa/include/mach/gumstix.h +++ b/arch/arm/mach-pxa/include/mach/gumstix.h @@ -94,3 +94,7 @@ has detected a cable insertion; driven low otherwise. */ #define GPIO26_PRDY_nBSY_MD (GPIO26_PRDY_nBSY | GPIO_IN) #define GPIO27_PRDY_nBSY_MD (GPIO27_PRDY_nBSY | GPIO_IN) #define GPIO36_nCD_MD (GPIO36_nCD | GPIO_IN) + +/* for expansion boards that can't be programatically detected */ +extern int am200_init(void); + diff --git a/arch/arm/mach-pxa/include/mach/h5000.h b/arch/arm/mach-pxa/include/mach/h5000.h new file mode 100644 index 000000000000..2a5ae3802787 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/h5000.h @@ -0,0 +1,113 @@ +/* + * Hardware definitions for HP iPAQ h5xxx Handheld Computers + * + * Copyright(20)02 Hewlett-Packard Company. + * + * 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. + * + * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Author: Jamey Hicks + */ + +#ifndef __ASM_ARCH_H5000_H +#define __ASM_ARCH_H5000_H + +#include <mach/mfp-pxa25x.h> + +/* + * CPU GPIOs + */ + +#define H5000_GPIO_POWER_BUTTON (0) +#define H5000_GPIO_RESET_BUTTON_N (1) +#define H5000_GPIO_OPT_INT (2) +#define H5000_GPIO_BACKUP_POWER (3) +#define H5000_GPIO_ACTION_BUTTON (4) +#define H5000_GPIO_COM_DCD_SOMETHING (5) /* what is this really ? */ +/* 6 not connected */ +#define H5000_GPIO_RESET_BUTTON_AGAIN_N (7) /* connected to gpio 1 as well */ +/* 8 not connected */ +#define H5000_GPIO_RSO_N (9) /* reset output from max1702 which regulates 3.3 and 2.5 */ +#define H5000_GPIO_ASIC_INT_N (10) /* from companion asic */ +#define H5000_GPIO_BT_ENV_0 (11) /* to LMX9814, set to 1 according to regdump */ +/*(12) not connected */ +#define H5000_GPIO_BT_ENV_1 (13) /* to LMX9814, set to 1 according to regdump */ +#define H5000_GPIO_BT_WU (14) /* from LMX9814, Defined as HOST_WAKEUP in the LMX9820 data sheet */ +/*(15) is CS1# */ +/*(16) not connected */ +/*(17) not connected */ +/*(18) is pcmcia ready */ +/*(19) is dreq1 */ +/*(20) is dreq0 */ +#define H5000_GPIO_OE_RD_NWR (21) /* output enable on rd/nwr signal to companion asic */ +/*(22) is not connected */ +#define H5000_GPIO_OPT_SPI_CLK (23) /* to extension pack */ +#define H5000_GPIO_OPT_SPI_CS_N (24) /* to extension pack */ +#define H5000_GPIO_OPT_SPI_DOUT (25) /* to extension pack */ +#define H5000_GPIO_OPT_SPI_DIN (26) /* to extension pack */ +/*(27) not connected */ +#define H5000_GPIO_I2S_BITCLK (28) /* connected to AC97 codec */ +#define H5000_GPIO_I2S_DATAOUT (29) /* connected to AC97 codec */ +#define H5000_GPIO_I2S_DATAIN (30) /* connected to AC97 codec */ +#define H5000_GPIO_I2S_LRCLK (31) /* connected to AC97 codec */ +#define H5000_GPIO_I2S_SYSCLK (32) /* connected to AC97 codec */ +/*(33) is CS5# */ +#define H5000_GPIO_COM_RXD (34) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_CTS (35) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_DCD (36) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_DSR (37) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_RI (38) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_TXD (39) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_DTR (40) /* connected to cradle/cable connector */ +#define H5000_GPIO_COM_RTS (41) /* connected to cradle/cable connector */ + +#define H5000_GPIO_BT_RXD (42) /* connected to BT (LMX9814) */ +#define H5000_GPIO_BT_TXD (43) /* connected to BT (LMX9814) */ +#define H5000_GPIO_BT_CTS (44) /* connected to BT (LMX9814) */ +#define H5000_GPIO_BT_RTS (45) /* connected to BT (LMX9814) */ + +#define H5000_GPIO_IRDA_RXD (46) +#define H5000_GPIO_IRDA_TXD (47) + +#define H5000_GPIO_POE_N (48) /* used for pcmcia */ +#define H5000_GPIO_PWE_N (49) /* used for pcmcia */ +#define H5000_GPIO_PIOR_N (50) /* used for pcmcia */ +#define H5000_GPIO_PIOW_N (51) /* used for pcmcia */ +#define H5000_GPIO_PCE1_N (52) /* used for pcmcia */ +#define H5000_GPIO_PCE2_N (53) /* used for pcmcia */ +#define H5000_GPIO_PSKTSEL (54) /* used for pcmcia */ +#define H5000_GPIO_PREG_N (55) /* used for pcmcia */ +#define H5000_GPIO_PWAIT_N (56) /* used for pcmcia */ +#define H5000_GPIO_IOIS16_N (57) /* used for pcmcia */ + +#define H5000_GPIO_IRDA_SD (58) /* to hsdl3002 sd */ +/*(59) not connected */ +#define H5000_GPIO_POWER_SD_N (60) /* controls power to SD */ +#define H5000_GPIO_POWER_RS232_N (61) /* inverted FORCEON to rs232 transceiver */ +#define H5000_GPIO_POWER_ACCEL_N (62) /* controls power to accel */ +/*(63) is not connected */ +#define H5000_GPIO_OPT_NVRAM (64) /* controls power to expansion pack */ +#define H5000_GPIO_CHG_EN (65) /* to sc801 en */ +#define H5000_GPIO_USB_PULLUP (66) /* USB d+ pullup via 1.5K resistor */ +#define H5000_GPIO_BT_2V8_N (67) /* 2.8V used by bluetooth */ +#define H5000_GPIO_EXT_CHG_RATE (68) /* enables external charging rate */ +/*(69) is not connected */ +#define H5000_GPIO_CIR_RESET (70) /* consumer IR reset */ +#define H5000_GPIO_POWER_LIGHT_SENSOR_N (71) +#define H5000_GPIO_BT_M_RESET (72) +#define H5000_GPIO_STD_CHG_RATE (73) +#define H5000_GPIO_SD_WP_N (74) +#define H5000_GPIO_MOTOR_ON_N (75) /* external pullup on this */ +#define H5000_GPIO_HEADPHONE_DETECT (76) +#define H5000_GPIO_USB_CHG_RATE (77) /* select rate for charging via usb */ +/*(78) is CS2# */ +/*(79) is CS3# */ +/*(80) is CS4# */ + +#endif /* __ASM_ARCH_H5000_H */ diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index a582a6d9b92b..16ab79547dae 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -102,6 +102,9 @@ * PXA930 B0 0x69056835 0x5E643013 * PXA930 B1 0x69056837 0x7E643013 * PXA930 B2 0x69056838 0x8E643013 + * + * PXA935 A0 0x56056931 0x1E653013 + * PXA935 B0 0x56056936 0x6E653013 */ #ifdef CONFIG_PXA25x #define __cpu_is_pxa210(id) \ @@ -178,12 +181,22 @@ #define __cpu_is_pxa930(id) \ ({ \ unsigned int _id = (id) >> 4 & 0xfff; \ - _id == 0x683; \ + _id == 0x683; \ }) #else #define __cpu_is_pxa930(id) (0) #endif +#ifdef CONFIG_CPU_PXA935 +#define __cpu_is_pxa935(id) \ + ({ \ + unsigned int _id = (id) >> 4 & 0xfff; \ + _id == 0x693; \ + }) +#else +#define __cpu_is_pxa935(id) (0) +#endif + #define cpu_is_pxa210() \ ({ \ __cpu_is_pxa210(read_cpuid_id()); \ @@ -204,8 +217,6 @@ __cpu_is_pxa25x(read_cpuid_id()); \ }) -extern int cpu_is_pxa26x(void); - #define cpu_is_pxa27x() \ ({ \ __cpu_is_pxa27x(read_cpuid_id()); \ @@ -232,6 +243,12 @@ extern int cpu_is_pxa26x(void); __cpu_is_pxa930(id); \ }) +#define cpu_is_pxa935() \ + ({ \ + unsigned int id = read_cpuid(CPUID_ID); \ + __cpu_is_pxa935(id); \ + }) + /* * CPUID Core Generation Bit * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x @@ -249,6 +266,12 @@ extern int cpu_is_pxa26x(void); _id == 0x3; \ }) +#define __cpu_is_pxa9xx(id) \ + ({ \ + unsigned int _id = (id) >> 4 & 0xfff; \ + _id == 0x683 || _id == 0x693; \ + }) + #define cpu_is_pxa2xx() \ ({ \ __cpu_is_pxa2xx(read_cpuid_id()); \ @@ -259,32 +282,25 @@ extern int cpu_is_pxa26x(void); __cpu_is_pxa3xx(read_cpuid_id()); \ }) -/* - * Handy routine to set GPIO alternate functions - */ -extern int pxa_gpio_mode( int gpio_mode ); - -/* - * Return GPIO level, nonzero means high, zero is low - */ -extern int pxa_gpio_get_value(unsigned gpio); - -/* - * Set output GPIO level - */ -extern void pxa_gpio_set_value(unsigned gpio, int value); - +#define cpu_is_pxa9xx() \ + ({ \ + __cpu_is_pxa9xx(read_cpuid_id()); \ + }) /* * return current memory and LCD clock frequency in units of 10kHz */ extern unsigned int get_memclk_frequency_10khz(void); +/* return the clock tick rate of the OS timer */ +extern unsigned long get_clock_tick_rate(void); #endif #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) #define PCIBIOS_MIN_IO 0 #define PCIBIOS_MIN_MEM 0 #define pcibios_assign_all_busses() 1 +#define HAVE_ARCH_PCI_SET_DMA_MASK 1 #endif + #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h index 600fd4f76603..262691fb97d8 100644 --- a/arch/arm/mach-pxa/include/mach/io.h +++ b/arch/arm/mach-pxa/include/mach/io.h @@ -6,15 +6,13 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> - #define IO_SPACE_LIMIT 0xffffffff /* * We don't actually have real ISA nor PCI buses, but there is so many * drivers out there that might just work if we fake them... */ -#define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h index 5c4e320c1437..6c9b21c51322 100644 --- a/arch/arm/mach-pxa/include/mach/littleton.h +++ b/arch/arm/mach-pxa/include/mach/littleton.h @@ -1,8 +1,13 @@ -#ifndef __ASM_ARCH_ZYLONITE_H -#define __ASM_ARCH_ZYLONITE_H +#ifndef __ASM_ARCH_LITTLETON_H +#define __ASM_ARCH_LITTLETON_H + +#include <mach/gpio.h> #define LITTLETON_ETH_PHYS 0x30000000 #define LITTLETON_GPIO_LCD_CS (17) -#endif /* __ASM_ARCH_ZYLONITE_H */ +#define EXT0_GPIO_BASE (NR_BUILTIN_GPIO) +#define EXT0_GPIO(x) (EXT0_GPIO_BASE + (x)) + +#endif /* __ASM_ARCH_LITTLETON_H */ diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h index 59aef89808d6..f626730ee42e 100644 --- a/arch/arm/mach-pxa/include/mach/memory.h +++ b/arch/arm/mach-pxa/include/mach/memory.h @@ -18,16 +18,6 @@ #define PHYS_OFFSET UL(0xa0000000) /* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -/* * The nodes are matched with the physical SDRAM banks as follows: * * node 0: 0xa0000000-0xa3ffffff --> 0xc0000000-0xc3ffffff @@ -47,6 +37,7 @@ void cmx2xx_pci_adjust_zones(int node, unsigned long *size, cmx2xx_pci_adjust_zones(node, size, holes) #define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_64M - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M) #endif #endif diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h index 617cab2cc8d0..a72869b73ee3 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h @@ -158,4 +158,35 @@ #define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW) #define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW) +#ifdef CONFIG_CPU_PXA26x +/* GPIO */ +#define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0) +#define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF1) +#define GPIO87_GPIO MFP_CFG_IN(GPIO87, AF1) +#define GPIO88_GPIO MFP_CFG_IN(GPIO88, AF1) +#define GPIO89_GPIO MFP_CFG_IN(GPIO89, AF1) + +/* SDRAM */ +#define GPIO86_nSDCS2 MFP_CFG_OUT(GPIO86, AF0, DRIVE_HIGH) +#define GPIO87_nSDCS3 MFP_CFG_OUT(GPIO87, AF0, DRIVE_HIGH) +#define GPIO88_RDnWR MFP_CFG_OUT(GPIO88, AF0, DRIVE_HIGH) +#define GPIO89_nACRESET MFP_CFG_OUT(GPIO89, AF0, DRIVE_HIGH) + +/* USB */ +#define GPIO9_USB_RCV MFP_CFG_IN(GPIO9, AF1) +#define GPIO32_USB_VP MFP_CFG_IN(GPIO32, AF2) +#define GPIO34_USB_VM MFP_CFG_IN(GPIO34, AF2) +#define GPIO39_USB_VPO MFP_CFG_OUT(GPIO39, AF3, DRIVE_LOW) +#define GPIO56_USB_VMO MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW) +#define GPIO57_USB_nOE MFP_CFG_OUT(GPIO57, AF1, DRIVE_HIGH) + +/* ASSP */ +#define GPIO28_ASSP_BITCLK_IN MFP_CFG_IN(GPIO28, AF3) +#define GPIO28_ASSP_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF3, DRIVE_LOW) +#define GPIO29_ASSP_RXD MFP_CFG_IN(GPIO29, AF3) +#define GPIO30_ASSP_TXD MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW) +#define GPIO31_ASSP_SFRM_IN MFP_CFG_IN(GPIO31, AF1) +#define GPIO31_ASSP_SFRM_OUT MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW) +#endif + #endif /* __ASM_ARCH_MFP_PXA25X_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index 122bdbd53182..da4f85a4f990 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -11,6 +11,12 @@ #include <mach/mfp.h> #include <mach/mfp-pxa2xx.h> +/* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN + * bit is set, regardless of the GPIO configuration + */ +#define GPIO3_GPIO MFP_CFG_IN(GPIO3, AF0) +#define GPIO4_GPIO MFP_CFG_IN(GPIO4, AF0) + /* GPIO */ #define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0) #define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF0) diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index fabd9b4df827..fa73f56a1372 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h @@ -421,6 +421,7 @@ #define GPIO20_PWM0 MFP_CFG_LPM(GPIO20, AF2, PULL_LOW) #define GPIO21_PWM2 MFP_CFG_LPM(GPIO21, AF3, PULL_LOW) #define GPIO22_PWM3 MFP_CFG_LPM(GPIO22, AF3, PULL_LOW) +#define GPIO32_PWM0 MFP_CFG_LPM(GPIO32, AF4, PULL_LOW) /* CIR */ #define GPIO46_CIR_OUT MFP_CFG(GPIO46, AF1) diff --git a/arch/arm/mach-pxa/include/mach/mioa701.h b/arch/arm/mach-pxa/include/mach/mioa701.h index 8483cb511831..02868447b0b1 100644 --- a/arch/arm/mach-pxa/include/mach/mioa701.h +++ b/arch/arm/mach-pxa/include/mach/mioa701.h @@ -10,12 +10,14 @@ (MFP_PIN(pin) | MFP_##af | MFP_DIR_OUT | MFP_LPM_##state)) /* Global GPIOs */ -#define GPIO9_CHARGE_nEN 9 +#define GPIO9_CHARGE_EN 9 #define GPIO18_POWEROFF 18 #define GPIO87_LCD_POWER 87 +#define GPIO96_AC_DETECT 96 +#define GPIO80_MAYBE_CHARGE_VDROP 80 /* Drop of 88mV */ /* USB */ -#define GPIO13_USB_DETECT 13 +#define GPIO13_nUSB_DETECT 13 #define GPIO22_USB_ENABLE 22 /* SDIO bits */ @@ -24,7 +26,10 @@ #define GPIO91_SDIO_EN 91 /* Bluetooth */ +#define GPIO14_BT_nACTIVITY 14 #define GPIO83_BT_ON 83 +#define GPIO77_BT_UNKNOWN1 77 +#define GPIO86_BT_MAYBE_nRESET 86 /* GPS */ #define GPIO23_GPS_UNKNOWN1 23 diff --git a/arch/arm/mach-pxa/include/mach/mtd-xip.h b/arch/arm/mach-pxa/include/mach/mtd-xip.h index 4d452fcb1508..cfca8155be72 100644 --- a/arch/arm/mach-pxa/include/mach/mtd-xip.h +++ b/arch/arm/mach-pxa/include/mach/mtd-xip.h @@ -15,6 +15,7 @@ #ifndef __ARCH_PXA_MTD_XIP_H__ #define __ARCH_PXA_MTD_XIP_H__ +#include <mach/hardware.h> #include <mach/pxa-regs.h> #define xip_irqpending() (ICIP & ICMR) diff --git a/arch/arm/mach-pxa/include/mach/pxa-regs.h b/arch/arm/mach-pxa/include/mach/pxa-regs.h index 15295d960000..31d615aa7723 100644 --- a/arch/arm/mach-pxa/include/mach/pxa-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa-regs.h @@ -13,6 +13,7 @@ #ifndef __PXA_REGS_H #define __PXA_REGS_H +#include <mach/hardware.h> /* * PXA Chip selects @@ -123,298 +124,6 @@ #define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ #define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ - -/* - * UARTs - */ - -/* Full Function UART (FFUART) */ -#define FFUART FFRBR -#define FFRBR __REG(0x40100000) /* Receive Buffer Register (read only) */ -#define FFTHR __REG(0x40100000) /* Transmit Holding Register (write only) */ -#define FFIER __REG(0x40100004) /* Interrupt Enable Register (read/write) */ -#define FFIIR __REG(0x40100008) /* Interrupt ID Register (read only) */ -#define FFFCR __REG(0x40100008) /* FIFO Control Register (write only) */ -#define FFLCR __REG(0x4010000C) /* Line Control Register (read/write) */ -#define FFMCR __REG(0x40100010) /* Modem Control Register (read/write) */ -#define FFLSR __REG(0x40100014) /* Line Status Register (read only) */ -#define FFMSR __REG(0x40100018) /* Modem Status Register (read only) */ -#define FFSPR __REG(0x4010001C) /* Scratch Pad Register (read/write) */ -#define FFISR __REG(0x40100020) /* Infrared Selection Register (read/write) */ -#define FFDLL __REG(0x40100000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ -#define FFDLH __REG(0x40100004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ - -/* Bluetooth UART (BTUART) */ -#define BTUART BTRBR -#define BTRBR __REG(0x40200000) /* Receive Buffer Register (read only) */ -#define BTTHR __REG(0x40200000) /* Transmit Holding Register (write only) */ -#define BTIER __REG(0x40200004) /* Interrupt Enable Register (read/write) */ -#define BTIIR __REG(0x40200008) /* Interrupt ID Register (read only) */ -#define BTFCR __REG(0x40200008) /* FIFO Control Register (write only) */ -#define BTLCR __REG(0x4020000C) /* Line Control Register (read/write) */ -#define BTMCR __REG(0x40200010) /* Modem Control Register (read/write) */ -#define BTLSR __REG(0x40200014) /* Line Status Register (read only) */ -#define BTMSR __REG(0x40200018) /* Modem Status Register (read only) */ -#define BTSPR __REG(0x4020001C) /* Scratch Pad Register (read/write) */ -#define BTISR __REG(0x40200020) /* Infrared Selection Register (read/write) */ -#define BTDLL __REG(0x40200000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ -#define BTDLH __REG(0x40200004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ - -/* Standard UART (STUART) */ -#define STUART STRBR -#define STRBR __REG(0x40700000) /* Receive Buffer Register (read only) */ -#define STTHR __REG(0x40700000) /* Transmit Holding Register (write only) */ -#define STIER __REG(0x40700004) /* Interrupt Enable Register (read/write) */ -#define STIIR __REG(0x40700008) /* Interrupt ID Register (read only) */ -#define STFCR __REG(0x40700008) /* FIFO Control Register (write only) */ -#define STLCR __REG(0x4070000C) /* Line Control Register (read/write) */ -#define STMCR __REG(0x40700010) /* Modem Control Register (read/write) */ -#define STLSR __REG(0x40700014) /* Line Status Register (read only) */ -#define STMSR __REG(0x40700018) /* Reserved */ -#define STSPR __REG(0x4070001C) /* Scratch Pad Register (read/write) */ -#define STISR __REG(0x40700020) /* Infrared Selection Register (read/write) */ -#define STDLL __REG(0x40700000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ -#define STDLH __REG(0x40700004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ - -/* Hardware UART (HWUART) */ -#define HWUART HWRBR -#define HWRBR __REG(0x41600000) /* Receive Buffer Register (read only) */ -#define HWTHR __REG(0x41600000) /* Transmit Holding Register (write only) */ -#define HWIER __REG(0x41600004) /* Interrupt Enable Register (read/write) */ -#define HWIIR __REG(0x41600008) /* Interrupt ID Register (read only) */ -#define HWFCR __REG(0x41600008) /* FIFO Control Register (write only) */ -#define HWLCR __REG(0x4160000C) /* Line Control Register (read/write) */ -#define HWMCR __REG(0x41600010) /* Modem Control Register (read/write) */ -#define HWLSR __REG(0x41600014) /* Line Status Register (read only) */ -#define HWMSR __REG(0x41600018) /* Modem Status Register (read only) */ -#define HWSPR __REG(0x4160001C) /* Scratch Pad Register (read/write) */ -#define HWISR __REG(0x41600020) /* Infrared Selection Register (read/write) */ -#define HWFOR __REG(0x41600024) /* Receive FIFO Occupancy Register (read only) */ -#define HWABR __REG(0x41600028) /* Auto-Baud Control Register (read/write) */ -#define HWACR __REG(0x4160002C) /* Auto-Baud Count Register (read only) */ -#define HWDLL __REG(0x41600000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ -#define HWDLH __REG(0x41600004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ - -#define IER_DMAE (1 << 7) /* DMA Requests Enable */ -#define IER_UUE (1 << 6) /* UART Unit Enable */ -#define IER_NRZE (1 << 5) /* NRZ coding Enable */ -#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */ -#define IER_MIE (1 << 3) /* Modem Interrupt Enable */ -#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */ -#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */ -#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */ - -#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */ -#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */ -#define IIR_TOD (1 << 3) /* Time Out Detected */ -#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */ -#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */ -#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */ - -#define FCR_ITL2 (1 << 7) /* Interrupt Trigger Level */ -#define FCR_ITL1 (1 << 6) /* Interrupt Trigger Level */ -#define FCR_RESETTF (1 << 2) /* Reset Transmitter FIFO */ -#define FCR_RESETRF (1 << 1) /* Reset Receiver FIFO */ -#define FCR_TRFIFOE (1 << 0) /* Transmit and Receive FIFO Enable */ -#define FCR_ITL_1 (0) -#define FCR_ITL_8 (FCR_ITL1) -#define FCR_ITL_16 (FCR_ITL2) -#define FCR_ITL_32 (FCR_ITL2|FCR_ITL1) - -#define LCR_DLAB (1 << 7) /* Divisor Latch Access Bit */ -#define LCR_SB (1 << 6) /* Set Break */ -#define LCR_STKYP (1 << 5) /* Sticky Parity */ -#define LCR_EPS (1 << 4) /* Even Parity Select */ -#define LCR_PEN (1 << 3) /* Parity Enable */ -#define LCR_STB (1 << 2) /* Stop Bit */ -#define LCR_WLS1 (1 << 1) /* Word Length Select */ -#define LCR_WLS0 (1 << 0) /* Word Length Select */ - -#define LSR_FIFOE (1 << 7) /* FIFO Error Status */ -#define LSR_TEMT (1 << 6) /* Transmitter Empty */ -#define LSR_TDRQ (1 << 5) /* Transmit Data Request */ -#define LSR_BI (1 << 4) /* Break Interrupt */ -#define LSR_FE (1 << 3) /* Framing Error */ -#define LSR_PE (1 << 2) /* Parity Error */ -#define LSR_OE (1 << 1) /* Overrun Error */ -#define LSR_DR (1 << 0) /* Data Ready */ - -#define MCR_LOOP (1 << 4) -#define MCR_OUT2 (1 << 3) /* force MSR_DCD in loopback mode */ -#define MCR_OUT1 (1 << 2) /* force MSR_RI in loopback mode */ -#define MCR_RTS (1 << 1) /* Request to Send */ -#define MCR_DTR (1 << 0) /* Data Terminal Ready */ - -#define MSR_DCD (1 << 7) /* Data Carrier Detect */ -#define MSR_RI (1 << 6) /* Ring Indicator */ -#define MSR_DSR (1 << 5) /* Data Set Ready */ -#define MSR_CTS (1 << 4) /* Clear To Send */ -#define MSR_DDCD (1 << 3) /* Delta Data Carrier Detect */ -#define MSR_TERI (1 << 2) /* Trailing Edge Ring Indicator */ -#define MSR_DDSR (1 << 1) /* Delta Data Set Ready */ -#define MSR_DCTS (1 << 0) /* Delta Clear To Send */ - -/* - * IrSR (Infrared Selection Register) - */ -#define STISR_RXPL (1 << 4) /* Receive Data Polarity */ -#define STISR_TXPL (1 << 3) /* Transmit Data Polarity */ -#define STISR_XMODE (1 << 2) /* Transmit Pulse Width Select */ -#define STISR_RCVEIR (1 << 1) /* Receiver SIR Enable */ -#define STISR_XMITIR (1 << 0) /* Transmitter SIR Enable */ - - -/* - * I2C registers - moved into drivers/i2c/busses/i2c-pxa.c - */ - -/* - * Serial Audio Controller - moved into sound/soc/pxa/pxa2xx-i2s.c - */ - -/* - * AC97 Controller registers - */ - -#define POCR __REG(0x40500000) /* PCM Out Control Register */ -#define POCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ -#define POCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ - -#define PICR __REG(0x40500004) /* PCM In Control Register */ -#define PICR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ -#define PICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ - -#define MCCR __REG(0x40500008) /* Mic In Control Register */ -#define MCCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ -#define MCCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ - -#define GCR __REG(0x4050000C) /* Global Control Register */ -#ifdef CONFIG_PXA3xx -#define GCR_CLKBPB (1 << 31) /* Internal clock enable */ -#endif -#define GCR_nDMAEN (1 << 24) /* non DMA Enable */ -#define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */ -#define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */ -#define GCR_SECRDY_IEN (1 << 9) /* Secondary Ready Interrupt Enable */ -#define GCR_PRIRDY_IEN (1 << 8) /* Primary Ready Interrupt Enable */ -#define GCR_SECRES_IEN (1 << 5) /* Secondary Resume Interrupt Enable */ -#define GCR_PRIRES_IEN (1 << 4) /* Primary Resume Interrupt Enable */ -#define GCR_ACLINK_OFF (1 << 3) /* AC-link Shut Off */ -#define GCR_WARM_RST (1 << 2) /* AC97 Warm Reset */ -#define GCR_COLD_RST (1 << 1) /* AC'97 Cold Reset (0 = active) */ -#define GCR_GIE (1 << 0) /* Codec GPI Interrupt Enable */ - -#define POSR __REG(0x40500010) /* PCM Out Status Register */ -#define POSR_FIFOE (1 << 4) /* FIFO error */ -#define POSR_FSR (1 << 2) /* FIFO Service Request */ - -#define PISR __REG(0x40500014) /* PCM In Status Register */ -#define PISR_FIFOE (1 << 4) /* FIFO error */ -#define PISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ -#define PISR_FSR (1 << 2) /* FIFO Service Request */ - -#define MCSR __REG(0x40500018) /* Mic In Status Register */ -#define MCSR_FIFOE (1 << 4) /* FIFO error */ -#define MCSR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ -#define MCSR_FSR (1 << 2) /* FIFO Service Request */ - -#define GSR __REG(0x4050001C) /* Global Status Register */ -#define GSR_CDONE (1 << 19) /* Command Done */ -#define GSR_SDONE (1 << 18) /* Status Done */ -#define GSR_RDCS (1 << 15) /* Read Completion Status */ -#define GSR_BIT3SLT12 (1 << 14) /* Bit 3 of slot 12 */ -#define GSR_BIT2SLT12 (1 << 13) /* Bit 2 of slot 12 */ -#define GSR_BIT1SLT12 (1 << 12) /* Bit 1 of slot 12 */ -#define GSR_SECRES (1 << 11) /* Secondary Resume Interrupt */ -#define GSR_PRIRES (1 << 10) /* Primary Resume Interrupt */ -#define GSR_SCR (1 << 9) /* Secondary Codec Ready */ -#define GSR_PCR (1 << 8) /* Primary Codec Ready */ -#define GSR_MCINT (1 << 7) /* Mic In Interrupt */ -#define GSR_POINT (1 << 6) /* PCM Out Interrupt */ -#define GSR_PIINT (1 << 5) /* PCM In Interrupt */ -#define GSR_ACOFFD (1 << 3) /* AC-link Shut Off Done */ -#define GSR_MOINT (1 << 2) /* Modem Out Interrupt */ -#define GSR_MIINT (1 << 1) /* Modem In Interrupt */ -#define GSR_GSCI (1 << 0) /* Codec GPI Status Change Interrupt */ - -#define CAR __REG(0x40500020) /* CODEC Access Register */ -#define CAR_CAIP (1 << 0) /* Codec Access In Progress */ - -#define PCDR __REG(0x40500040) /* PCM FIFO Data Register */ -#define MCDR __REG(0x40500060) /* Mic-in FIFO Data Register */ - -#define MOCR __REG(0x40500100) /* Modem Out Control Register */ -#define MOCR_FEIE (1 << 3) /* FIFO Error */ -#define MOCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ - -#define MICR __REG(0x40500108) /* Modem In Control Register */ -#define MICR_FEIE (1 << 3) /* FIFO Error */ -#define MICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ - -#define MOSR __REG(0x40500110) /* Modem Out Status Register */ -#define MOSR_FIFOE (1 << 4) /* FIFO error */ -#define MOSR_FSR (1 << 2) /* FIFO Service Request */ - -#define MISR __REG(0x40500118) /* Modem In Status Register */ -#define MISR_FIFOE (1 << 4) /* FIFO error */ -#define MISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ -#define MISR_FSR (1 << 2) /* FIFO Service Request */ - -#define MODR __REG(0x40500140) /* Modem FIFO Data Register */ - -#define PAC_REG_BASE __REG(0x40500200) /* Primary Audio Codec */ -#define SAC_REG_BASE __REG(0x40500300) /* Secondary Audio Codec */ -#define PMC_REG_BASE __REG(0x40500400) /* Primary Modem Codec */ -#define SMC_REG_BASE __REG(0x40500500) /* Secondary Modem Codec */ - - -/* - * Fast Infrared Communication Port - */ - -#define FICP __REG(0x40800000) /* Start of FICP area */ -#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */ -#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */ -#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */ -#define ICDR __REG(0x4080000c) /* ICP Data Register */ -#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */ -#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */ - -#define ICCR0_AME (1 << 7) /* Address match enable */ -#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */ -#define ICCR0_RIE (1 << 5) /* Recieve FIFO interrupt enable */ -#define ICCR0_RXE (1 << 4) /* Receive enable */ -#define ICCR0_TXE (1 << 3) /* Transmit enable */ -#define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */ -#define ICCR0_LBM (1 << 1) /* Loopback mode */ -#define ICCR0_ITR (1 << 0) /* IrDA transmission */ - -#define ICCR2_RXP (1 << 3) /* Receive Pin Polarity select */ -#define ICCR2_TXP (1 << 2) /* Transmit Pin Polarity select */ -#define ICCR2_TRIG (3 << 0) /* Receive FIFO Trigger threshold */ -#define ICCR2_TRIG_8 (0 << 0) /* >= 8 bytes */ -#define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */ -#define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */ - -#ifdef CONFIG_PXA27x -#define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */ -#endif -#define ICSR0_FRE (1 << 5) /* Framing error */ -#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */ -#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */ -#define ICSR0_RAB (1 << 2) /* Receiver abort */ -#define ICSR0_TUR (1 << 1) /* Trunsmit FIFO underun */ -#define ICSR0_EIF (1 << 0) /* End/Error in FIFO */ - -#define ICSR1_ROR (1 << 6) /* Receiver FIFO underrun */ -#define ICSR1_CRE (1 << 5) /* CRC error */ -#define ICSR1_EOF (1 << 4) /* End of frame */ -#define ICSR1_TNF (1 << 3) /* Transmit FIFO not full */ -#define ICSR1_RNE (1 << 2) /* Receive FIFO not empty */ -#define ICSR1_TBY (1 << 1) /* Tramsmiter busy flag */ -#define ICSR1_RSY (1 << 0) /* Recevier synchronized flag */ - - /* * Real Time Clock */ @@ -463,19 +172,6 @@ /* - * Pulse Width Modulator - */ - -#define PWM_CTRL0 __REG(0x40B00000) /* PWM 0 Control Register */ -#define PWM_PWDUTY0 __REG(0x40B00004) /* PWM 0 Duty Cycle Register */ -#define PWM_PERVAL0 __REG(0x40B00008) /* PWM 0 Period Control Register */ - -#define PWM_CTRL1 __REG(0x40C00000) /* PWM 1Control Register */ -#define PWM_PWDUTY1 __REG(0x40C00004) /* PWM 1 Duty Cycle Register */ -#define PWM_PERVAL1 __REG(0x40C00008) /* PWM 1 Period Control Register */ - - -/* * Interrupt Controller */ @@ -496,19 +192,6 @@ * General Purpose I/O */ -#define GPIO0_BASE ((void __iomem *)io_p2v(0x40E00000)) -#define GPIO1_BASE ((void __iomem *)io_p2v(0x40E00004)) -#define GPIO2_BASE ((void __iomem *)io_p2v(0x40E00008)) -#define GPIO3_BASE ((void __iomem *)io_p2v(0x40E00100)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 - #define GPLR0 __REG(0x40E00000) /* GPIO Pin-Level Register GPIO<31:0> */ #define GPLR1 __REG(0x40E00004) /* GPIO Pin-Level Register GPIO<63:32> */ #define GPLR2 __REG(0x40E00008) /* GPIO Pin-Level Register GPIO<80:64> */ @@ -558,10 +241,6 @@ #define GPIO_bit(x) (1 << ((x) & 0x1f)) -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) - -/* Interrupt Controller */ - #define _GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3) #define _GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3) #define _GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3) @@ -580,189 +259,5 @@ #define GEDR(x) (*((((x) & 0x7f) < 96) ? &_GEDR(x) : &GEDR3)) #define GAFR(x) (*((((x) & 0x7f) < 96) ? &_GAFR(x) : \ ((((x) & 0x7f) < 112) ? &GAFR3_L : &GAFR3_U))) -#else - -#define GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3) -#define GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3) -#define GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3) -#define GPCR(x) __REG2(0x40E00024, ((x) & 0x60) >> 3) -#define GRER(x) __REG2(0x40E00030, ((x) & 0x60) >> 3) -#define GFER(x) __REG2(0x40E0003C, ((x) & 0x60) >> 3) -#define GEDR(x) __REG2(0x40E00048, ((x) & 0x60) >> 3) -#define GAFR(x) __REG2(0x40E00054, ((x) & 0x70) >> 2) - -#endif - -/* - * Power Manager - see pxa2xx-regs.h - */ - -/* - * SSP Serial Port Registers - see arch/arm/mach-pxa/include/mach/regs-ssp.h - */ - -/* - * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h - */ - -/* - * Core Clock - see arch/arm/mach-pxa/include/mach/pxa2xx-regs.h - */ - -#ifdef CONFIG_PXA27x - -/* Camera Interface */ -#define CICR0 __REG(0x50000000) -#define CICR1 __REG(0x50000004) -#define CICR2 __REG(0x50000008) -#define CICR3 __REG(0x5000000C) -#define CICR4 __REG(0x50000010) -#define CISR __REG(0x50000014) -#define CIFR __REG(0x50000018) -#define CITOR __REG(0x5000001C) -#define CIBR0 __REG(0x50000028) -#define CIBR1 __REG(0x50000030) -#define CIBR2 __REG(0x50000038) - -#define CICR0_DMAEN (1 << 31) /* DMA request enable */ -#define CICR0_PAR_EN (1 << 30) /* Parity enable */ -#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ -#define CICR0_ENB (1 << 28) /* Camera interface enable */ -#define CICR0_DIS (1 << 27) /* Camera interface disable */ -#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ -#define CICR0_TOM (1 << 9) /* Time-out mask */ -#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ -#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ -#define CICR0_EOLM (1 << 6) /* End-of-line mask */ -#define CICR0_PERRM (1 << 5) /* Parity-error mask */ -#define CICR0_QDM (1 << 4) /* Quick-disable mask */ -#define CICR0_CDM (1 << 3) /* Disable-done mask */ -#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ -#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ -#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ - -#define CICR1_TBIT (1 << 31) /* Transparency bit */ -#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ -#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ -#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ -#define CICR1_RGB_F (1 << 11) /* RGB format */ -#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ -#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ -#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ -#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ -#define CICR1_DW (0x7 << 0) /* Data width mask */ - -#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock - wait count mask */ -#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock - wait count mask */ -#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ -#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR2_FSW (0x7 << 0) /* Frame stabilization - wait count mask */ - -#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock - wait count mask */ -#define CICR3_EFW (0xff << 16) /* End-of-frame line clock - wait count mask */ -#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ -#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ - -#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ -#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ -#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ -#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ -#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ -#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ -#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ -#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ - -#define CISR_FTO (1 << 15) /* FIFO time-out */ -#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ -#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ -#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ -#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ -#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ -#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ -#define CISR_EOL (1 << 8) /* End of line */ -#define CISR_PAR_ERR (1 << 7) /* Parity error */ -#define CISR_CQD (1 << 6) /* Camera interface quick disable */ -#define CISR_CDD (1 << 5) /* Camera interface disable done */ -#define CISR_SOF (1 << 4) /* Start of frame */ -#define CISR_EOF (1 << 3) /* End of frame */ -#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ -#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ -#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ - -#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ -#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ -#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ -#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ -#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ -#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ -#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ -#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ - -#define SRAM_SIZE 0x40000 /* 4x64K */ - -#define SRAM_MEM_PHYS 0x5C000000 - -#define IMPMCR __REG(0x58000000) /* IM Power Management Control Reg */ -#define IMPMSR __REG(0x58000008) /* IM Power Management Status Reg */ - -#define IMPMCR_PC3 (0x3 << 22) /* Bank 3 Power Control */ -#define IMPMCR_PC3_RUN_MODE (0x0 << 22) /* Run mode */ -#define IMPMCR_PC3_STANDBY_MODE (0x1 << 22) /* Standby mode */ -#define IMPMCR_PC3_AUTO_MODE (0x3 << 22) /* Automatically controlled */ - -#define IMPMCR_PC2 (0x3 << 20) /* Bank 2 Power Control */ -#define IMPMCR_PC2_RUN_MODE (0x0 << 20) /* Run mode */ -#define IMPMCR_PC2_STANDBY_MODE (0x1 << 20) /* Standby mode */ -#define IMPMCR_PC2_AUTO_MODE (0x3 << 20) /* Automatically controlled */ - -#define IMPMCR_PC1 (0x3 << 18) /* Bank 1 Power Control */ -#define IMPMCR_PC1_RUN_MODE (0x0 << 18) /* Run mode */ -#define IMPMCR_PC1_STANDBY_MODE (0x1 << 18) /* Standby mode */ -#define IMPMCR_PC1_AUTO_MODE (0x3 << 18) /* Automatically controlled */ - -#define IMPMCR_PC0 (0x3 << 16) /* Bank 0 Power Control */ -#define IMPMCR_PC0_RUN_MODE (0x0 << 16) /* Run mode */ -#define IMPMCR_PC0_STANDBY_MODE (0x1 << 16) /* Standby mode */ -#define IMPMCR_PC0_AUTO_MODE (0x3 << 16) /* Automatically controlled */ - -#define IMPMCR_AW3 (1 << 11) /* Bank 3 Automatic Wake-up enable */ -#define IMPMCR_AW2 (1 << 10) /* Bank 2 Automatic Wake-up enable */ -#define IMPMCR_AW1 (1 << 9) /* Bank 1 Automatic Wake-up enable */ -#define IMPMCR_AW0 (1 << 8) /* Bank 0 Automatic Wake-up enable */ - -#define IMPMCR_DST (0xFF << 0) /* Delay Standby Time, ms */ - -#define IMPMSR_PS3 (0x3 << 6) /* Bank 3 Power Status: */ -#define IMPMSR_PS3_RUN_MODE (0x0 << 6) /* Run mode */ -#define IMPMSR_PS3_STANDBY_MODE (0x1 << 6) /* Standby mode */ - -#define IMPMSR_PS2 (0x3 << 4) /* Bank 2 Power Status: */ -#define IMPMSR_PS2_RUN_MODE (0x0 << 4) /* Run mode */ -#define IMPMSR_PS2_STANDBY_MODE (0x1 << 4) /* Standby mode */ - -#define IMPMSR_PS1 (0x3 << 2) /* Bank 1 Power Status: */ -#define IMPMSR_PS1_RUN_MODE (0x0 << 2) /* Run mode */ -#define IMPMSR_PS1_STANDBY_MODE (0x1 << 2) /* Standby mode */ - -#define IMPMSR_PS0 (0x3 << 0) /* Bank 0 Power Status: */ -#define IMPMSR_PS0_RUN_MODE (0x0 << 0) /* Run mode */ -#define IMPMSR_PS0_STANDBY_MODE (0x1 << 0) /* Standby mode */ - -#endif - -/* PWRMODE register M field values */ - -#define PWRMODE_IDLE 0x1 -#define PWRMODE_STANDBY 0x2 -#define PWRMODE_SLEEP 0x3 -#define PWRMODE_DEEPSLEEP 0x7 #endif diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h b/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h index 6ef1dd09970b..d83393e25273 100644 --- a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h +++ b/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h @@ -365,4 +365,9 @@ #define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_IN) #define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN) +/* + * Handy routine to set GPIO alternate functions + */ +extern int pxa_gpio_mode( int gpio_mode ); + #endif /* __ASM_ARCH_PXA2XX_GPIO_H */ diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h index 806ecfea44bf..77102d695cc7 100644 --- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h @@ -49,6 +49,11 @@ #define MECR_NOS (1 << 0) /* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */ #define MECR_CIT (1 << 1) /* Card Is There: 0 -> no card, 1 -> card inserted */ +#define MDCNFG_DE0 (1 << 0) /* SDRAM Bank 0 Enable */ +#define MDCNFG_DE1 (1 << 1) /* SDRAM Bank 1 Enable */ +#define MDCNFG_DE2 (1 << 16) /* SDRAM Bank 2 Enable */ +#define MDCNFG_DE3 (1 << 17) /* SDRAM Bank 3 Enable */ + #define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */ #define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */ #define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */ @@ -243,4 +248,11 @@ #define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */ #define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */ +/* PWRMODE register M field values */ + +#define PWRMODE_IDLE 0x1 +#define PWRMODE_STANDBY 0x2 +#define PWRMODE_SLEEP 0x3 +#define PWRMODE_DEEPSLEEP 0x7 + #endif diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h index cbda4d35c421..6932720ba04e 100644 --- a/arch/arm/mach-pxa/include/mach/pxafb.h +++ b/arch/arm/mach-pxa/include/mach/pxafb.h @@ -48,6 +48,7 @@ #define LCD_MONO_DSTN_8BPP ((8 << 4) | LCD_TYPE_MONO_DSTN) #define LCD_COLOR_STN_8BPP ((8 << 4) | LCD_TYPE_COLOR_STN) #define LCD_COLOR_DSTN_16BPP ((16 << 4) | LCD_TYPE_COLOR_DSTN) +#define LCD_COLOR_TFT_8BPP ((8 << 4) | LCD_TYPE_COLOR_TFT) #define LCD_COLOR_TFT_16BPP ((16 << 4) | LCD_TYPE_COLOR_TFT) #define LCD_COLOR_TFT_18BPP ((18 << 4) | LCD_TYPE_COLOR_TFT) #define LCD_SMART_PANEL_8BPP ((8 << 4) | LCD_TYPE_SMART_PANEL) @@ -94,6 +95,10 @@ struct pxafb_mode_info { * in pxa27x and pxa3xx, initialize them to the same value or * the larger one will be used * 3. same to {rd,wr}_pulse_width + * + * 4. LCD_PCLK_EDGE_{RISE,FALL} controls the L_PCLK_WR polarity + * 5. sync & FB_SYNC_HOR_HIGH_ACT controls the L_LCLK_A0 + * 6. sync & FB_SYNC_VERT_HIGH_ACT controls the L_LCLK_RD */ unsigned a0csrd_set_hld; /* A0 and CS Setup/Hold Time before/after L_FCLK_RD */ unsigned a0cswr_set_hld; /* A0 and CS Setup/Hold Time before/after L_PCLK_WR */ @@ -108,6 +113,7 @@ struct pxafb_mach_info { unsigned int num_modes; unsigned int lcd_conn; + unsigned long video_mem_size; u_int fixed_modes:1, cmap_inverse:1, diff --git a/arch/arm/mach-pxa/include/mach/regs-ac97.h b/arch/arm/mach-pxa/include/mach/regs-ac97.h new file mode 100644 index 000000000000..e41b9d202b8c --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/regs-ac97.h @@ -0,0 +1,99 @@ +#ifndef __ASM_ARCH_REGS_AC97_H +#define __ASM_ARCH_REGS_AC97_H + +/* + * AC97 Controller registers + */ + +#define POCR __REG(0x40500000) /* PCM Out Control Register */ +#define POCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define POCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define PICR __REG(0x40500004) /* PCM In Control Register */ +#define PICR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define PICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MCCR __REG(0x40500008) /* Mic In Control Register */ +#define MCCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define MCCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define GCR __REG(0x4050000C) /* Global Control Register */ +#ifdef CONFIG_PXA3xx +#define GCR_CLKBPB (1 << 31) /* Internal clock enable */ +#endif +#define GCR_nDMAEN (1 << 24) /* non DMA Enable */ +#define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */ +#define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */ +#define GCR_SECRDY_IEN (1 << 9) /* Secondary Ready Interrupt Enable */ +#define GCR_PRIRDY_IEN (1 << 8) /* Primary Ready Interrupt Enable */ +#define GCR_SECRES_IEN (1 << 5) /* Secondary Resume Interrupt Enable */ +#define GCR_PRIRES_IEN (1 << 4) /* Primary Resume Interrupt Enable */ +#define GCR_ACLINK_OFF (1 << 3) /* AC-link Shut Off */ +#define GCR_WARM_RST (1 << 2) /* AC97 Warm Reset */ +#define GCR_COLD_RST (1 << 1) /* AC'97 Cold Reset (0 = active) */ +#define GCR_GIE (1 << 0) /* Codec GPI Interrupt Enable */ + +#define POSR __REG(0x40500010) /* PCM Out Status Register */ +#define POSR_FIFOE (1 << 4) /* FIFO error */ +#define POSR_FSR (1 << 2) /* FIFO Service Request */ + +#define PISR __REG(0x40500014) /* PCM In Status Register */ +#define PISR_FIFOE (1 << 4) /* FIFO error */ +#define PISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define PISR_FSR (1 << 2) /* FIFO Service Request */ + +#define MCSR __REG(0x40500018) /* Mic In Status Register */ +#define MCSR_FIFOE (1 << 4) /* FIFO error */ +#define MCSR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define MCSR_FSR (1 << 2) /* FIFO Service Request */ + +#define GSR __REG(0x4050001C) /* Global Status Register */ +#define GSR_CDONE (1 << 19) /* Command Done */ +#define GSR_SDONE (1 << 18) /* Status Done */ +#define GSR_RDCS (1 << 15) /* Read Completion Status */ +#define GSR_BIT3SLT12 (1 << 14) /* Bit 3 of slot 12 */ +#define GSR_BIT2SLT12 (1 << 13) /* Bit 2 of slot 12 */ +#define GSR_BIT1SLT12 (1 << 12) /* Bit 1 of slot 12 */ +#define GSR_SECRES (1 << 11) /* Secondary Resume Interrupt */ +#define GSR_PRIRES (1 << 10) /* Primary Resume Interrupt */ +#define GSR_SCR (1 << 9) /* Secondary Codec Ready */ +#define GSR_PCR (1 << 8) /* Primary Codec Ready */ +#define GSR_MCINT (1 << 7) /* Mic In Interrupt */ +#define GSR_POINT (1 << 6) /* PCM Out Interrupt */ +#define GSR_PIINT (1 << 5) /* PCM In Interrupt */ +#define GSR_ACOFFD (1 << 3) /* AC-link Shut Off Done */ +#define GSR_MOINT (1 << 2) /* Modem Out Interrupt */ +#define GSR_MIINT (1 << 1) /* Modem In Interrupt */ +#define GSR_GSCI (1 << 0) /* Codec GPI Status Change Interrupt */ + +#define CAR __REG(0x40500020) /* CODEC Access Register */ +#define CAR_CAIP (1 << 0) /* Codec Access In Progress */ + +#define PCDR __REG(0x40500040) /* PCM FIFO Data Register */ +#define MCDR __REG(0x40500060) /* Mic-in FIFO Data Register */ + +#define MOCR __REG(0x40500100) /* Modem Out Control Register */ +#define MOCR_FEIE (1 << 3) /* FIFO Error */ +#define MOCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MICR __REG(0x40500108) /* Modem In Control Register */ +#define MICR_FEIE (1 << 3) /* FIFO Error */ +#define MICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MOSR __REG(0x40500110) /* Modem Out Status Register */ +#define MOSR_FIFOE (1 << 4) /* FIFO error */ +#define MOSR_FSR (1 << 2) /* FIFO Service Request */ + +#define MISR __REG(0x40500118) /* Modem In Status Register */ +#define MISR_FIFOE (1 << 4) /* FIFO error */ +#define MISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define MISR_FSR (1 << 2) /* FIFO Service Request */ + +#define MODR __REG(0x40500140) /* Modem FIFO Data Register */ + +#define PAC_REG_BASE __REG(0x40500200) /* Primary Audio Codec */ +#define SAC_REG_BASE __REG(0x40500300) /* Secondary Audio Codec */ +#define PMC_REG_BASE __REG(0x40500400) /* Primary Modem Codec */ +#define SMC_REG_BASE __REG(0x40500500) /* Secondary Modem Codec */ + +#endif /* __ASM_ARCH_REGS_AC97_H */ diff --git a/arch/arm/mach-pxa/include/mach/regs-lcd.h b/arch/arm/mach-pxa/include/mach/regs-lcd.h index c689c4ea769c..f82dcea792d9 100644 --- a/arch/arm/mach-pxa/include/mach/regs-lcd.h +++ b/arch/arm/mach-pxa/include/mach/regs-lcd.h @@ -12,27 +12,29 @@ #define LCCR3 (0x00C) /* LCD Controller Control Register 3 */ #define LCCR4 (0x010) /* LCD Controller Control Register 4 */ #define LCCR5 (0x014) /* LCD Controller Control Register 5 */ -#define DFBR0 (0x020) /* DMA Channel 0 Frame Branch Register */ -#define DFBR1 (0x024) /* DMA Channel 1 Frame Branch Register */ -#define LCSR (0x038) /* LCD Controller Status Register */ +#define LCSR (0x038) /* LCD Controller Status Register 0 */ +#define LCSR1 (0x034) /* LCD Controller Status Register 1 */ #define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */ #define TMEDRGBR (0x040) /* TMED RGB Seed Register */ #define TMEDCR (0x044) /* TMED Control Register */ +#define FBR0 (0x020) /* DMA Channel 0 Frame Branch Register */ +#define FBR1 (0x024) /* DMA Channel 1 Frame Branch Register */ +#define FBR2 (0x028) /* DMA Channel 2 Frame Branch Register */ +#define FBR3 (0x02C) /* DMA Channel 2 Frame Branch Register */ +#define FBR4 (0x030) /* DMA Channel 2 Frame Branch Register */ +#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */ +#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */ + +#define OVL1C1 (0x050) /* Overlay 1 Control Register 1 */ +#define OVL1C2 (0x060) /* Overlay 1 Control Register 2 */ +#define OVL2C1 (0x070) /* Overlay 2 Control Register 1 */ +#define OVL2C2 (0x080) /* Overlay 2 Control Register 2 */ + #define CMDCR (0x100) /* Command Control Register */ #define PRSR (0x104) /* Panel Read Status Register */ -#define LCCR3_1BPP (0 << 24) -#define LCCR3_2BPP (1 << 24) -#define LCCR3_4BPP (2 << 24) -#define LCCR3_8BPP (3 << 24) -#define LCCR3_16BPP (4 << 24) -#define LCCR3_18BPP (5 << 24) -#define LCCR3_18BPP_P (6 << 24) -#define LCCR3_19BPP (7 << 24) -#define LCCR3_19BPP_P (1 << 29) -#define LCCR3_24BPP ((1 << 29) | (1 << 24)) -#define LCCR3_25BPP ((1 << 29) | (2 << 24)) +#define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0)) #define LCCR3_PDFOR_0 (0 << 30) #define LCCR3_PDFOR_1 (1 << 30) @@ -42,19 +44,16 @@ #define LCCR4_PAL_FOR_0 (0 << 15) #define LCCR4_PAL_FOR_1 (1 << 15) #define LCCR4_PAL_FOR_2 (2 << 15) +#define LCCR4_PAL_FOR_3 (3 << 15) #define LCCR4_PAL_FOR_MASK (3 << 15) #define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */ -#define FSADR0 (0x204) /* DMA Channel 0 Frame Source Address Register */ -#define FIDR0 (0x208) /* DMA Channel 0 Frame ID Register */ -#define LDCMD0 (0x20C) /* DMA Channel 0 Command Register */ #define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */ -#define FSADR1 (0x214) /* DMA Channel 1 Frame Source Address Register */ -#define FIDR1 (0x218) /* DMA Channel 1 Frame ID Register */ -#define LDCMD1 (0x21C) /* DMA Channel 1 Command Register */ +#define FDADR2 (0x220) /* DMA Channel 2 Frame Descriptor Address Register */ +#define FDADR3 (0x230) /* DMA Channel 3 Frame Descriptor Address Register */ +#define FDADR4 (0x240) /* DMA Channel 4 Frame Descriptor Address Register */ +#define FDADR5 (0x250) /* DMA Channel 5 Frame Descriptor Address Register */ #define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */ -#define FSADR6 (0x264) /* DMA Channel 6 Frame Source Address Register */ -#define FIDR6 (0x268) /* DMA Channel 6 Frame ID Register */ #define LCCR0_ENB (1 << 0) /* LCD Controller enable */ #define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */ @@ -126,9 +125,6 @@ #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ #define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD))) -#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ -#define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP))) - #define LCCR3_ACB Fld (8, 8) /* AC Bias */ #define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB))) @@ -157,8 +153,22 @@ #define LCSR_RD_ST (1 << 11) /* read status */ #define LCSR_CMD_INT (1 << 12) /* command interrupt */ +#define LCSR1_IU(x) (1 << ((x) + 23)) /* Input FIFO underrun */ +#define LCSR1_BS(x) (1 << ((x) + 15)) /* Branch Status */ +#define LCSR1_EOF(x) (1 << ((x) + 7)) /* End of Frame Status */ +#define LCSR1_SOF(x) (1 << ((x) - 1)) /* Start of Frame Status */ + #define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */ +/* overlay control registers */ +#define OVLxC1_PPL(x) ((((x) - 1) & 0x3ff) << 0) /* Pixels Per Line */ +#define OVLxC1_LPO(x) ((((x) - 1) & 0x3ff) << 10) /* Number of Lines */ +#define OVLxC1_BPP(x) (((x) & 0xf) << 20) /* Bits Per Pixel */ +#define OVLxC1_OEN (1 << 31) /* Enable bit for Overlay */ +#define OVLxC2_XPOS(x) (((x) & 0x3ff) << 0) /* Horizontal Position */ +#define OVLxC2_YPOS(x) (((x) & 0x3ff) << 10) /* Vertical Position */ +#define OVL2C2_PFOR(x) (((x) & 0x7) << 20) /* Pixel Format */ + /* smartpanel related */ #define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */ #define PRSR_A0 (1 << 8) /* Read Data Source */ @@ -177,4 +187,11 @@ #define SMART_CMD(x) (SMART_CMD_WRITE_COMMAND | ((x) & 0xff)) #define SMART_DAT(x) (SMART_CMD_WRITE_DATA | ((x) & 0xff)) + +/* SMART_DELAY() is introduced for software controlled delay primitive which + * can be inserted between command sequences, unused command 0x6 is used here + * and delay ranges from 0ms ~ 255ms + */ +#define SMART_CMD_DELAY (0x6 << 9) +#define SMART_DELAY(ms) (SMART_CMD_DELAY | ((ms) & 0xff)) #endif /* __ASM_ARCH_REGS_LCD_H */ diff --git a/arch/arm/mach-pxa/include/mach/regs-uart.h b/arch/arm/mach-pxa/include/mach/regs-uart.h new file mode 100644 index 000000000000..55aeb7fb72f6 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/regs-uart.h @@ -0,0 +1,143 @@ +#ifndef __ASM_ARCH_REGS_UART_H +#define __ASM_ARCH_REGS_UART_H + +/* + * UARTs + */ + +/* Full Function UART (FFUART) */ +#define FFUART FFRBR +#define FFRBR __REG(0x40100000) /* Receive Buffer Register (read only) */ +#define FFTHR __REG(0x40100000) /* Transmit Holding Register (write only) */ +#define FFIER __REG(0x40100004) /* Interrupt Enable Register (read/write) */ +#define FFIIR __REG(0x40100008) /* Interrupt ID Register (read only) */ +#define FFFCR __REG(0x40100008) /* FIFO Control Register (write only) */ +#define FFLCR __REG(0x4010000C) /* Line Control Register (read/write) */ +#define FFMCR __REG(0x40100010) /* Modem Control Register (read/write) */ +#define FFLSR __REG(0x40100014) /* Line Status Register (read only) */ +#define FFMSR __REG(0x40100018) /* Modem Status Register (read only) */ +#define FFSPR __REG(0x4010001C) /* Scratch Pad Register (read/write) */ +#define FFISR __REG(0x40100020) /* Infrared Selection Register (read/write) */ +#define FFDLL __REG(0x40100000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ +#define FFDLH __REG(0x40100004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ + +/* Bluetooth UART (BTUART) */ +#define BTUART BTRBR +#define BTRBR __REG(0x40200000) /* Receive Buffer Register (read only) */ +#define BTTHR __REG(0x40200000) /* Transmit Holding Register (write only) */ +#define BTIER __REG(0x40200004) /* Interrupt Enable Register (read/write) */ +#define BTIIR __REG(0x40200008) /* Interrupt ID Register (read only) */ +#define BTFCR __REG(0x40200008) /* FIFO Control Register (write only) */ +#define BTLCR __REG(0x4020000C) /* Line Control Register (read/write) */ +#define BTMCR __REG(0x40200010) /* Modem Control Register (read/write) */ +#define BTLSR __REG(0x40200014) /* Line Status Register (read only) */ +#define BTMSR __REG(0x40200018) /* Modem Status Register (read only) */ +#define BTSPR __REG(0x4020001C) /* Scratch Pad Register (read/write) */ +#define BTISR __REG(0x40200020) /* Infrared Selection Register (read/write) */ +#define BTDLL __REG(0x40200000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ +#define BTDLH __REG(0x40200004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ + +/* Standard UART (STUART) */ +#define STUART STRBR +#define STRBR __REG(0x40700000) /* Receive Buffer Register (read only) */ +#define STTHR __REG(0x40700000) /* Transmit Holding Register (write only) */ +#define STIER __REG(0x40700004) /* Interrupt Enable Register (read/write) */ +#define STIIR __REG(0x40700008) /* Interrupt ID Register (read only) */ +#define STFCR __REG(0x40700008) /* FIFO Control Register (write only) */ +#define STLCR __REG(0x4070000C) /* Line Control Register (read/write) */ +#define STMCR __REG(0x40700010) /* Modem Control Register (read/write) */ +#define STLSR __REG(0x40700014) /* Line Status Register (read only) */ +#define STMSR __REG(0x40700018) /* Reserved */ +#define STSPR __REG(0x4070001C) /* Scratch Pad Register (read/write) */ +#define STISR __REG(0x40700020) /* Infrared Selection Register (read/write) */ +#define STDLL __REG(0x40700000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ +#define STDLH __REG(0x40700004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ + +/* Hardware UART (HWUART) */ +#define HWUART HWRBR +#define HWRBR __REG(0x41600000) /* Receive Buffer Register (read only) */ +#define HWTHR __REG(0x41600000) /* Transmit Holding Register (write only) */ +#define HWIER __REG(0x41600004) /* Interrupt Enable Register (read/write) */ +#define HWIIR __REG(0x41600008) /* Interrupt ID Register (read only) */ +#define HWFCR __REG(0x41600008) /* FIFO Control Register (write only) */ +#define HWLCR __REG(0x4160000C) /* Line Control Register (read/write) */ +#define HWMCR __REG(0x41600010) /* Modem Control Register (read/write) */ +#define HWLSR __REG(0x41600014) /* Line Status Register (read only) */ +#define HWMSR __REG(0x41600018) /* Modem Status Register (read only) */ +#define HWSPR __REG(0x4160001C) /* Scratch Pad Register (read/write) */ +#define HWISR __REG(0x41600020) /* Infrared Selection Register (read/write) */ +#define HWFOR __REG(0x41600024) /* Receive FIFO Occupancy Register (read only) */ +#define HWABR __REG(0x41600028) /* Auto-Baud Control Register (read/write) */ +#define HWACR __REG(0x4160002C) /* Auto-Baud Count Register (read only) */ +#define HWDLL __REG(0x41600000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ +#define HWDLH __REG(0x41600004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ + +#define IER_DMAE (1 << 7) /* DMA Requests Enable */ +#define IER_UUE (1 << 6) /* UART Unit Enable */ +#define IER_NRZE (1 << 5) /* NRZ coding Enable */ +#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */ +#define IER_MIE (1 << 3) /* Modem Interrupt Enable */ +#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */ +#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */ +#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */ + +#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */ +#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */ +#define IIR_TOD (1 << 3) /* Time Out Detected */ +#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */ +#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */ +#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */ + +#define FCR_ITL2 (1 << 7) /* Interrupt Trigger Level */ +#define FCR_ITL1 (1 << 6) /* Interrupt Trigger Level */ +#define FCR_RESETTF (1 << 2) /* Reset Transmitter FIFO */ +#define FCR_RESETRF (1 << 1) /* Reset Receiver FIFO */ +#define FCR_TRFIFOE (1 << 0) /* Transmit and Receive FIFO Enable */ +#define FCR_ITL_1 (0) +#define FCR_ITL_8 (FCR_ITL1) +#define FCR_ITL_16 (FCR_ITL2) +#define FCR_ITL_32 (FCR_ITL2|FCR_ITL1) + +#define LCR_DLAB (1 << 7) /* Divisor Latch Access Bit */ +#define LCR_SB (1 << 6) /* Set Break */ +#define LCR_STKYP (1 << 5) /* Sticky Parity */ +#define LCR_EPS (1 << 4) /* Even Parity Select */ +#define LCR_PEN (1 << 3) /* Parity Enable */ +#define LCR_STB (1 << 2) /* Stop Bit */ +#define LCR_WLS1 (1 << 1) /* Word Length Select */ +#define LCR_WLS0 (1 << 0) /* Word Length Select */ + +#define LSR_FIFOE (1 << 7) /* FIFO Error Status */ +#define LSR_TEMT (1 << 6) /* Transmitter Empty */ +#define LSR_TDRQ (1 << 5) /* Transmit Data Request */ +#define LSR_BI (1 << 4) /* Break Interrupt */ +#define LSR_FE (1 << 3) /* Framing Error */ +#define LSR_PE (1 << 2) /* Parity Error */ +#define LSR_OE (1 << 1) /* Overrun Error */ +#define LSR_DR (1 << 0) /* Data Ready */ + +#define MCR_LOOP (1 << 4) +#define MCR_OUT2 (1 << 3) /* force MSR_DCD in loopback mode */ +#define MCR_OUT1 (1 << 2) /* force MSR_RI in loopback mode */ +#define MCR_RTS (1 << 1) /* Request to Send */ +#define MCR_DTR (1 << 0) /* Data Terminal Ready */ + +#define MSR_DCD (1 << 7) /* Data Carrier Detect */ +#define MSR_RI (1 << 6) /* Ring Indicator */ +#define MSR_DSR (1 << 5) /* Data Set Ready */ +#define MSR_CTS (1 << 4) /* Clear To Send */ +#define MSR_DDCD (1 << 3) /* Delta Data Carrier Detect */ +#define MSR_TERI (1 << 2) /* Trailing Edge Ring Indicator */ +#define MSR_DDSR (1 << 1) /* Delta Data Set Ready */ +#define MSR_DCTS (1 << 0) /* Delta Clear To Send */ + +/* + * IrSR (Infrared Selection Register) + */ +#define STISR_RXPL (1 << 4) /* Receive Data Polarity */ +#define STISR_TXPL (1 << 3) /* Transmit Data Polarity */ +#define STISR_XMODE (1 << 2) /* Transmit Pulse Width Select */ +#define STISR_RCVEIR (1 << 1) /* Receiver SIR Enable */ +#define STISR_XMITIR (1 << 0) /* Transmitter SIR Enable */ + +#endif /* __ASM_ARCH_REGS_UART_H */ diff --git a/arch/arm/mach-pxa/include/mach/timex.h b/arch/arm/mach-pxa/include/mach/timex.h index b05fc6683c47..af6760a50e1a 100644 --- a/arch/arm/mach-pxa/include/mach/timex.h +++ b/arch/arm/mach-pxa/include/mach/timex.h @@ -10,6 +10,14 @@ * published by the Free Software Foundation. */ +/* Various drivers are still using the constant of CLOCK_TICK_RATE, for + * those drivers to at least work, the definition is provided here. + * + * NOTE: this is no longer accurate when multiple processors and boards + * are selected, newer drivers should not depend on this any more. Use + * either the clocksource/clockevent or get this at run-time by calling + * get_clock_tick_rate() (as defined in generic.c). + */ #if defined(CONFIG_PXA25x) /* PXA250/210 timer base */ diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h index 21e3e890af98..f4b029c03957 100644 --- a/arch/arm/mach-pxa/include/mach/uncompress.h +++ b/arch/arm/mach-pxa/include/mach/uncompress.h @@ -10,7 +10,7 @@ */ #include <linux/serial_reg.h> -#include <mach/pxa-regs.h> +#include <mach/regs-uart.h> #include <asm/mach-types.h> #define __REG(x) ((volatile unsigned long *)x) @@ -35,7 +35,7 @@ static inline void flush(void) static inline void arch_decomp_setup(void) { - if (machine_is_littleton()) + if (machine_is_littleton() || machine_is_intelmote2()) UART = STUART; } diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index b4d00aba0e31..31da7f3c06f6 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -20,8 +20,13 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/smc91x.h> +#include <linux/i2c.h> +#include <linux/leds.h> +#include <linux/mfd/da903x.h> +#include <linux/i2c/max732x.h> #include <asm/types.h> #include <asm/setup.h> @@ -36,10 +41,10 @@ #include <mach/pxa-regs.h> #include <mach/mfp-pxa300.h> -#include <mach/gpio.h> #include <mach/pxafb.h> #include <mach/ssp.h> #include <mach/pxa2xx_spi.h> +#include <mach/i2c.h> #include <mach/pxa27x_keypad.h> #include <mach/pxa3xx_nand.h> #include <mach/littleton.h> @@ -314,6 +319,73 @@ static void __init littleton_init_nand(void) static inline void littleton_init_nand(void) {} #endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */ +#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE) +static struct led_info littleton_da9034_leds[] = { + [0] = { + .name = "littleton:keypad1", + .flags = DA9034_LED_RAMP, + }, + [1] = { + .name = "littleton:keypad2", + .flags = DA9034_LED_RAMP, + }, + [2] = { + .name = "littleton:vibra", + .flags = 0, + }, +}; + +static struct da903x_subdev_info littleton_da9034_subdevs[] = { + { + .name = "da903x-led", + .id = DA9034_ID_LED_1, + .platform_data = &littleton_da9034_leds[0], + }, { + .name = "da903x-led", + .id = DA9034_ID_LED_2, + .platform_data = &littleton_da9034_leds[1], + }, { + .name = "da903x-led", + .id = DA9034_ID_VIBRA, + .platform_data = &littleton_da9034_leds[2], + }, { + .name = "da903x-backlight", + .id = DA9034_ID_WLED, + }, +}; + +static struct da903x_platform_data littleton_da9034_info = { + .num_subdevs = ARRAY_SIZE(littleton_da9034_subdevs), + .subdevs = littleton_da9034_subdevs, +}; + +static struct max732x_platform_data littleton_max7320_info = { + .gpio_base = EXT0_GPIO_BASE, +}; + +static struct i2c_board_info littleton_i2c_info[] = { + [0] = { + .type = "da9034", + .addr = 0x34, + .platform_data = &littleton_da9034_info, + .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO18)), + }, + [1] = { + .type = "max7320", + .addr = 0x50, + .platform_data = &littleton_max7320_info, + }, +}; + +static void __init littleton_init_i2c(void) +{ + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(littleton_i2c_info)); +} +#else +static inline void littleton_init_i2c(void) {} +#endif /* CONFIG_I2C_PXA || CONFIG_I2C_PXA_MODULE */ + static void __init littleton_init(void) { /* initialize MFP configurations */ @@ -326,6 +398,7 @@ static void __init littleton_init(void) platform_device_register(&smc91x_device); littleton_init_spi(); + littleton_init_i2c(); littleton_init_lcd(); littleton_init_keypad(); littleton_init_nand(); diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 519138bc5f85..21b821e1a60d 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -123,6 +123,10 @@ static unsigned long magician_pin_config[] __initdata = { GPIO107_GPIO, /* DS1WM_IRQ */ GPIO108_GPIO, /* GSM_READY */ GPIO115_GPIO, /* nPEN_IRQ */ + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, }; /* @@ -332,8 +336,7 @@ static struct pxafb_mach_info toppoly_info = { .modes = toppoly_modes, .num_modes = 1, .fixed_modes = 1, - .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - .lccr3 = LCCR3_PixRsEdg, + .lcd_conn = LCD_COLOR_TFT_16BPP, .pxafb_lcd_power = toppoly_lcd_power, }; @@ -341,8 +344,8 @@ static struct pxafb_mach_info samsung_info = { .modes = samsung_modes, .num_modes = 1, .fixed_modes = 1, - .lccr0 = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - .lccr3 = LCCR3_PixFlEdg, + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL |\ + LCD_ALTERNATE_MAPPING, .pxafb_lcd_power = samsung_lcd_power, }; diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index f2c7ad8f2b6b..5f224968043c 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -128,6 +128,10 @@ static unsigned long mainstone_pin_config[] = { GPIO108_KP_MKOUT_5, GPIO96_KP_MKOUT_6, + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + /* GPIO */ GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, }; diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 2061c00c8ead..33626de8cbf6 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -38,12 +38,13 @@ struct gpio_desc { unsigned valid : 1; unsigned can_wakeup : 1; unsigned keypad_gpio : 1; + unsigned dir_inverted : 1; unsigned int mask; /* bit mask in PWER or PKWR */ + unsigned int mux_mask; /* bit mask of muxed gpio bits, 0 if no mux */ unsigned long config; }; static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1]; -static int gpio_nr; static unsigned long gpdr_lpm[4]; @@ -54,7 +55,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */ int shft = (gpio & 0xf) << 1; int fn = MFP_AF(c); - int dir = c & MFP_DIR_OUT; + int is_out = (c & MFP_DIR_OUT) ? 1 : 0; if (fn > 3) return -EINVAL; @@ -68,7 +69,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) else GAFR_U(bank) = gafr; - if (dir == MFP_DIR_OUT) + if (is_out ^ gpio_desc[gpio].dir_inverted) GPDR(gpio) |= mask; else GPDR(gpio) &= ~mask; @@ -77,11 +78,11 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) switch (c & MFP_LPM_STATE_MASK) { case MFP_LPM_DRIVE_HIGH: PGSR(bank) |= mask; - dir = MFP_DIR_OUT; + is_out = 1; break; case MFP_LPM_DRIVE_LOW: PGSR(bank) &= ~mask; - dir = MFP_DIR_OUT; + is_out = 1; break; case MFP_LPM_DEFAULT: break; @@ -92,7 +93,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) break; } - if (dir == MFP_DIR_OUT) + if (is_out ^ gpio_desc[gpio].dir_inverted) gpdr_lpm[bank] |= mask; else gpdr_lpm[bank] &= ~mask; @@ -106,7 +107,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) return -EINVAL; } - if ((c & MFP_LPM_CAN_WAKEUP) && (dir == MFP_DIR_OUT)) { + if ((c & MFP_LPM_CAN_WAKEUP) && is_out) { pr_warning("%s: output GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL; @@ -169,7 +170,7 @@ void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm) int gpio_set_wake(unsigned int gpio, unsigned int on) { struct gpio_desc *d; - unsigned long c; + unsigned long c, mux_taken; if (gpio > mfp_to_gpio(MFP_PIN_GPIO127)) return -EINVAL; @@ -183,9 +184,13 @@ int gpio_set_wake(unsigned int gpio, unsigned int on) if (d->keypad_gpio) return -EINVAL; + mux_taken = (PWER & d->mux_mask) & (~d->mask); + if (on && mux_taken) + return -EBUSY; + if (d->can_wakeup && (c & MFP_LPM_CAN_WAKEUP)) { if (on) { - PWER |= d->mask; + PWER = (PWER & ~d->mux_mask) | d->mask; if (c & MFP_LPM_EDGE_RISE) PRER |= d->mask; @@ -210,7 +215,7 @@ static void __init pxa25x_mfp_init(void) { int i; - for (i = 0; i <= 84; i++) + for (i = 0; i <= pxa_last_gpio; i++) gpio_desc[i].valid = 1; for (i = 0; i <= 15; i++) { @@ -218,7 +223,11 @@ static void __init pxa25x_mfp_init(void) gpio_desc[i].mask = GPIO_bit(i); } - gpio_nr = 85; + /* PXA26x has additional 4 GPIOs (86/87/88/89) which has the + * direction bit inverted in GPDR2. See PXA26x DM 4.1.1. + */ + for (i = 86; i <= pxa_last_gpio; i++) + gpio_desc[i].dir_inverted = 1; } #else static inline void pxa25x_mfp_init(void) {} @@ -251,11 +260,27 @@ int keypad_set_wake(unsigned int on) return 0; } +#define PWER_WEMUX2_GPIO38 (1 << 16) +#define PWER_WEMUX2_GPIO53 (2 << 16) +#define PWER_WEMUX2_GPIO40 (3 << 16) +#define PWER_WEMUX2_GPIO36 (4 << 16) +#define PWER_WEMUX2_MASK (7 << 16) +#define PWER_WEMUX3_GPIO31 (1 << 19) +#define PWER_WEMUX3_GPIO113 (2 << 19) +#define PWER_WEMUX3_MASK (3 << 19) + +#define INIT_GPIO_DESC_MUXED(mux, gpio) \ +do { \ + gpio_desc[(gpio)].can_wakeup = 1; \ + gpio_desc[(gpio)].mask = PWER_ ## mux ## _GPIO ##gpio; \ + gpio_desc[(gpio)].mux_mask = PWER_ ## mux ## _MASK; \ +} while (0) + static void __init pxa27x_mfp_init(void) { int i, gpio; - for (i = 0; i <= 120; i++) { + for (i = 0; i <= pxa_last_gpio; i++) { /* skip GPIO2, 5, 6, 7, 8, they are not * valid pins allow configuration */ @@ -286,7 +311,12 @@ static void __init pxa27x_mfp_init(void) gpio_desc[35].can_wakeup = 1; gpio_desc[35].mask = PWER_WE35; - gpio_nr = 121; + INIT_GPIO_DESC_MUXED(WEMUX3, 31); + INIT_GPIO_DESC_MUXED(WEMUX3, 113); + INIT_GPIO_DESC_MUXED(WEMUX2, 38); + INIT_GPIO_DESC_MUXED(WEMUX2, 53); + INIT_GPIO_DESC_MUXED(WEMUX2, 40); + INIT_GPIO_DESC_MUXED(WEMUX2, 36); } #else static inline void pxa27x_mfp_init(void) {} @@ -300,7 +330,7 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state) { int i; - for (i = 0; i <= gpio_to_bank(gpio_nr); i++) { + for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { saved_gafr[0][i] = GAFR_L(i); saved_gafr[1][i] = GAFR_U(i); @@ -315,7 +345,7 @@ static int pxa2xx_mfp_resume(struct sys_device *d) { int i; - for (i = 0; i <= gpio_to_bank(gpio_nr); i++) { + for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { GAFR_L(i) = saved_gafr[0][i]; GAFR_U(i) = saved_gafr[1][i]; GPDR(i * 32) = saved_gpdr[i]; @@ -348,7 +378,7 @@ static int __init pxa2xx_mfp_init(void) pxa27x_mfp_init(); /* initialize gafr_run[], pgsr_lpm[] from existing values */ - for (i = 0; i <= gpio_to_bank(gpio_nr); i++) + for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) gpdr_lpm[i] = GPDR(i * 32); return sysdev_class_register(&pxa2xx_mfp_sysclass); diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 782903fe9c6c..2b427e015b6f 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -34,7 +34,7 @@ #include <linux/irq.h> #include <linux/pda_power.h> #include <linux/power_supply.h> -#include <linux/wm97xx.h> +#include <linux/wm97xx_batt.h> #include <linux/mtd/physmap.h> #include <asm/mach-types.h> @@ -46,6 +46,9 @@ #include <mach/mmc.h> #include <mach/udc.h> #include <mach/pxa27x-udc.h> +#include <mach/i2c.h> +#include <mach/camera.h> +#include <media/soc_camera.h> #include <mach/mioa701.h> @@ -54,10 +57,11 @@ static unsigned long mioa701_pin_config[] = { /* Mio global */ - MIO_CFG_OUT(GPIO9_CHARGE_nEN, AF0, DRIVE_LOW), + MIO_CFG_OUT(GPIO9_CHARGE_EN, AF0, DRIVE_LOW), MIO_CFG_OUT(GPIO18_POWEROFF, AF0, DRIVE_LOW), MFP_CFG_OUT(GPIO3, AF0, DRIVE_HIGH), MFP_CFG_OUT(GPIO4, AF0, DRIVE_HIGH), + MIO_CFG_IN(GPIO80_MAYBE_CHARGE_VDROP, AF0), /* Backlight PWM 0 */ GPIO16_PWM0_OUT, @@ -74,7 +78,7 @@ static unsigned long mioa701_pin_config[] = { MIO_CFG_OUT(GPIO91_SDIO_EN, AF0, DRIVE_LOW), /* USB */ - MIO_CFG_IN(GPIO13_USB_DETECT, AF0), + MIO_CFG_IN(GPIO13_nUSB_DETECT, AF0), MIO_CFG_OUT(GPIO22_USB_ENABLE, AF0, DRIVE_LOW), /* LCD */ @@ -98,12 +102,29 @@ static unsigned long mioa701_pin_config[] = { GPIO75_LCD_LCLK, GPIO76_LCD_PCLK, + /* QCI */ + GPIO12_CIF_DD_7, + GPIO17_CIF_DD_6, + GPIO50_CIF_DD_3, + GPIO51_CIF_DD_2, + GPIO52_CIF_DD_4, + GPIO53_CIF_MCLK, + GPIO54_CIF_PCLK, + GPIO55_CIF_DD_1, + GPIO81_CIF_DD_0, + GPIO82_CIF_DD_5, + GPIO84_CIF_FV, + GPIO85_CIF_LV, + /* Bluetooth */ + MIO_CFG_IN(GPIO14_BT_nACTIVITY, AF0), GPIO44_BTUART_CTS, GPIO42_BTUART_RXD, GPIO45_BTUART_RTS, GPIO43_BTUART_TXD, MIO_CFG_OUT(GPIO83_BT_ON, AF0, DRIVE_LOW), + MIO_CFG_OUT(GPIO77_BT_UNKNOWN1, AF0, DRIVE_HIGH), + MIO_CFG_OUT(GPIO86_BT_MAYBE_nRESET, AF0, DRIVE_HIGH), /* GPS */ MIO_CFG_OUT(GPIO23_GPS_UNKNOWN1, AF0, DRIVE_LOW), @@ -151,16 +172,16 @@ static unsigned long mioa701_pin_config[] = { GPIO104_KP_MKOUT_1, GPIO105_KP_MKOUT_2, + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + /* Unknown */ - MFP_CFG_IN(GPIO14, AF0), MFP_CFG_IN(GPIO20, AF0), MFP_CFG_IN(GPIO21, AF0), MFP_CFG_IN(GPIO33, AF0), MFP_CFG_OUT(GPIO49, AF0, DRIVE_HIGH), MFP_CFG_OUT(GPIO57, AF0, DRIVE_HIGH), - MFP_CFG_OUT(GPIO77, AF0, DRIVE_HIGH), - MFP_CFG_IN(GPIO80, AF0), - MFP_CFG_OUT(GPIO86, AF0, DRIVE_HIGH), MFP_CFG_IN(GPIO96, AF0), MFP_CFG_OUT(GPIO116, AF0, DRIVE_HIGH), }; @@ -407,7 +428,7 @@ static void udc_power_command(int cmd) static int is_usb_connected(void) { - return !!gpio_get_value(GPIO13_USB_DETECT); + return !gpio_get_value(GPIO13_nUSB_DETECT); } static struct pxa2xx_udc_mach_info mioa701_udc_info = { @@ -659,13 +680,19 @@ static char *supplicants[] = { "mioa701_battery" }; +static int is_ac_connected(void) +{ + return gpio_get_value(GPIO96_AC_DETECT); +} + static void mioa701_set_charge(int flags) { - gpio_set_value(GPIO9_CHARGE_nEN, !flags); + gpio_set_value(GPIO9_CHARGE_EN, (flags == PDA_POWER_CHARGE_USB)); } static struct pda_power_pdata power_pdata = { - .is_ac_online = is_usb_connected, + .is_ac_online = is_ac_connected, + .is_usb_online = is_usb_connected, .set_charge = mioa701_set_charge, .supplied_to = supplicants, .num_supplicants = ARRAY_SIZE(supplicants), @@ -674,8 +701,15 @@ static struct pda_power_pdata power_pdata = { static struct resource power_resources[] = { [0] = { .name = "ac", - .start = gpio_to_irq(GPIO13_USB_DETECT), - .end = gpio_to_irq(GPIO13_USB_DETECT), + .start = gpio_to_irq(GPIO96_AC_DETECT), + .end = gpio_to_irq(GPIO96_AC_DETECT), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + }, + [1] = { + .name = "usb", + .start = gpio_to_irq(GPIO13_nUSB_DETECT), + .end = gpio_to_irq(GPIO13_nUSB_DETECT), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, }, @@ -691,120 +725,43 @@ static struct platform_device power_dev = { }, }; -#if defined(CONFIG_PDA_POWER) && defined(CONFIG_TOUCHSCREEN_WM97XX) -static struct wm97xx *battery_wm; - -static enum power_supply_property battery_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, /* Necessary for apm */ +static struct wm97xx_batt_info mioa701_battery_data = { + .batt_aux = WM97XX_AUX_ID1, + .temp_aux = -1, + .charge_gpio = -1, + .min_voltage = 0xc00, + .max_voltage = 0xfc0, + .batt_tech = POWER_SUPPLY_TECHNOLOGY_LION, + .batt_div = 1, + .batt_mult = 1, + .batt_name = "mioa701_battery", }; -static int get_battery_voltage(void) -{ - int adc = -1; - - if (battery_wm) - adc = wm97xx_read_aux_adc(battery_wm, WM97XX_AUX_ID1); - return adc; -} - -static int get_battery_status(struct power_supply *b) -{ - int status; - - if (is_usb_connected()) - status = POWER_SUPPLY_STATUS_CHARGING; - else - status = POWER_SUPPLY_STATUS_DISCHARGING; - - return status; -} - -static int get_property(struct power_supply *b, - enum power_supply_property psp, - union power_supply_propval *val) -{ - int rc = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = get_battery_status(b); - break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = 0xfd0; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = 0xc00; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = get_battery_voltage(); - break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - val->intval = 100; - break; - default: - val->intval = -1; - rc = -1; - } - - return rc; +/* + * Camera interface + */ +struct pxacamera_platform_data mioa701_pxacamera_platform_data = { + .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, + .mclk_10khz = 5000, }; -static struct power_supply battery_ps = { - .name = "mioa701_battery", - .type = POWER_SUPPLY_TYPE_BATTERY, - .get_property = get_property, - .properties = battery_props, - .num_properties = ARRAY_SIZE(battery_props), +static struct soc_camera_link iclink = { + .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */ }; -static int battery_probe(struct platform_device *pdev) -{ - struct wm97xx *wm = platform_get_drvdata(pdev); - int rc; - - battery_wm = wm; - - rc = power_supply_register(NULL, &battery_ps); - if (rc) - dev_err(&pdev->dev, - "Could not register mioa701 battery -> %d\n", rc); - return rc; -} - -static int battery_remove(struct platform_device *pdev) -{ - battery_wm = NULL; - return 0; -} - -static struct platform_driver mioa701_battery_driver = { - .driver = { - .name = "wm97xx-battery", +/* Board I2C devices. */ +static struct i2c_board_info __initdata mioa701_i2c_devices[] = { + { + /* Must initialize before the camera(s) */ + I2C_BOARD_INFO("mt9m111", 0x5d), + .platform_data = &iclink, }, - .probe = battery_probe, - .remove = battery_remove }; -static int __init mioa701_battery_init(void) -{ - int rc; - - rc = platform_driver_register(&mioa701_battery_driver); - if (rc) - printk(KERN_ERR "Could not register mioa701 battery driver\n"); - return rc; -} - -#else -static int __init mioa701_battery_init(void) -{ - return 0; -} -#endif +struct i2c_pxa_platform_data i2c_pdata = { + .fast_mode = 1, +}; /* * Mio global @@ -851,17 +808,17 @@ static void mioa701_machine_exit(void); static void mioa701_poweroff(void) { mioa701_machine_exit(); - gpio_set_value(GPIO18_POWEROFF, 1); + arm_machine_restart('s'); } static void mioa701_restart(char c) { mioa701_machine_exit(); - arm_machine_restart(c); + arm_machine_restart('s'); } struct gpio_ress global_gpios[] = { - MIO_GPIO_OUT(GPIO9_CHARGE_nEN, 1, "Charger enable"), + MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"), MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"), MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power") }; @@ -879,12 +836,16 @@ static void __init mioa701_machine_init(void) set_pxa_fb_info(&mioa701_pxafb_info); pxa_set_mci_info(&mioa701_mci_info); pxa_set_keypad_info(&mioa701_keypad_info); + wm97xx_bat_set_pdata(&mioa701_battery_data); udc_init(); pm_power_off = mioa701_poweroff; arm_pm_restart = mioa701_restart; platform_add_devices(devices, ARRAY_SIZE(devices)); gsm_init(); - mioa701_battery_init(); + + pxa_set_i2c_info(&i2c_pdata); + pxa_set_camera_info(&mioa701_pxacamera_platform_data); + i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices)); } static void mioa701_machine_exit(void) diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index b36cec5c9eed..34841c72815f 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -55,6 +55,10 @@ static unsigned long pcm990_pin_config[] __initdata = { GPIO89_USBH1_PEN, /* PWM0 */ GPIO16_PWM0_OUT, + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, }; /* @@ -100,8 +104,7 @@ static struct pxafb_mode_info fb_info_sharp_lq084v1dg21 = { static struct pxafb_mach_info pcm990_fbinfo __initdata = { .modes = &fb_info_sharp_lq084v1dg21, .num_modes = 1, - .lccr0 = LCCR0_PAS, - .lccr3 = LCCR3_PCP, + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, .pxafb_lcd_power = pcm990_lcd_power, }; #elif defined(CONFIG_PCM990_DISPLAY_NEC) @@ -123,8 +126,7 @@ struct pxafb_mode_info fb_info_nec_nl6448bc20_18d = { static struct pxafb_mach_info pcm990_fbinfo __initdata = { .modes = &fb_info_nec_nl6448bc20_18d, .num_modes = 1, - .lccr0 = LCCR0_Act, - .lccr3 = LCCR3_PixFlEdg, + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, .pxafb_lcd_power = pcm990_lcd_power, }; #endif diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 2e3bd8b1523b..ae88855bf974 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -20,6 +20,7 @@ #include <linux/fb.h> #include <linux/pm.h> #include <linux/delay.h> +#include <linux/mtd/physmap.h> #include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> @@ -413,9 +414,40 @@ static struct pxafb_mach_info poodle_fb_info = { .lcd_conn = LCD_COLOR_TFT_16BPP, }; +static struct mtd_partition sharpsl_rom_parts[] = { + { + .name ="Boot PROM Filesystem", + .offset = 0x00120000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data sharpsl_rom_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(sharpsl_rom_parts), + .parts = sharpsl_rom_parts, +}; + +static struct resource sharpsl_rom_resources[] = { + { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sharpsl_rom_device = { + .name = "physmap-flash", + .id = -1, + .resource = sharpsl_rom_resources, + .num_resources = ARRAY_SIZE(sharpsl_rom_resources), + .dev.platform_data = &sharpsl_rom_data, +}; + static struct platform_device *devices[] __initdata = { &poodle_locomo_device, &poodle_scoop_device, + &sharpsl_rom_device, }; static void poodle_poweroff(void) diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/mach-pxa/pwm.c index 74e2ead8cee8..3ca7ffc6904b 100644 --- a/arch/arm/mach-pxa/pwm.c +++ b/arch/arm/mach-pxa/pwm.c @@ -173,7 +173,7 @@ static struct pwm_device *pwm_probe(struct platform_device *pdev, return ERR_PTR(-ENOMEM); } - pwm->clk = clk_get(&pdev->dev, "PWMCLK"); + pwm->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(pwm->clk)) { ret = PTR_ERR(pwm->clk); goto err_free; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 25d17a1dab78..6c57522e2469 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -36,12 +36,6 @@ #include "devices.h" #include "clock.h" -int cpu_is_pxa26x(void) -{ - return cpu_is_pxa250() && ((BOOT_DEF & 0x8) == 0); -} -EXPORT_SYMBOL_GPL(cpu_is_pxa26x); - /* * Various clock factors driven by the CCCR register. */ @@ -167,36 +161,51 @@ static const struct clkops clk_pxa25x_gpio11_ops = { * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly) */ -static struct clk pxa25x_hwuart_clk = - INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev) -; +static DEFINE_CKEN(pxa25x_hwuart, HWUART, 14745600, 1); + +static struct clk_lookup pxa25x_hwuart_clkreg = + INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL); /* * PXA 2xx clock declarations. */ -static struct clk pxa25x_clks[] = { - INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev), - INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev), - INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev), - INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL), - INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa25x_device_udc.dev), - INIT_CLK("GPIO11_CLK", &clk_pxa25x_gpio11_ops, 3686400, 0, NULL), - INIT_CLK("GPIO12_CLK", &clk_pxa25x_gpio12_ops, 32768, 0, NULL), - INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev), - INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev), - - INIT_CKEN("SSPCLK", SSP, 3686400, 0, &pxa25x_device_ssp.dev), - INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev), - INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev), - INIT_CKEN("PWMCLK", PWM0, 3686400, 0, &pxa25x_device_pwm0.dev), - INIT_CKEN("PWMCLK", PWM1, 3686400, 0, &pxa25x_device_pwm1.dev), - - INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL), - - /* - INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL), - */ - INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), +static DEFINE_CK(pxa25x_lcd, LCD, &clk_pxa25x_lcd_ops); +static DEFINE_CKEN(pxa25x_ffuart, FFUART, 14745600, 1); +static DEFINE_CKEN(pxa25x_btuart, BTUART, 14745600, 1); +static DEFINE_CKEN(pxa25x_stuart, STUART, 14745600, 1); +static DEFINE_CKEN(pxa25x_usb, USB, 47923000, 5); +static DEFINE_CLK(pxa25x_gpio11, &clk_pxa25x_gpio11_ops, 3686400, 0); +static DEFINE_CLK(pxa25x_gpio12, &clk_pxa25x_gpio12_ops, 32768, 0); +static DEFINE_CKEN(pxa25x_mmc, MMC, 19169000, 0); +static DEFINE_CKEN(pxa25x_i2c, I2C, 31949000, 0); +static DEFINE_CKEN(pxa25x_ssp, SSP, 3686400, 0); +static DEFINE_CKEN(pxa25x_nssp, NSSP, 3686400, 0); +static DEFINE_CKEN(pxa25x_assp, ASSP, 3686400, 0); +static DEFINE_CKEN(pxa25x_pwm0, PWM0, 3686400, 0); +static DEFINE_CKEN(pxa25x_pwm1, PWM1, 3686400, 0); +static DEFINE_CKEN(pxa25x_ac97, AC97, 24576000, 0); +static DEFINE_CKEN(pxa25x_i2s, I2S, 14745600, 0); +static DEFINE_CKEN(pxa25x_ficp, FICP, 47923000, 0); + +static struct clk_lookup pxa25x_clkregs[] = { + INIT_CLKREG(&clk_pxa25x_lcd, "pxa2xx-fb", NULL), + INIT_CLKREG(&clk_pxa25x_ffuart, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_pxa25x_btuart, "pxa2xx-uart.1", NULL), + INIT_CLKREG(&clk_pxa25x_stuart, "pxa2xx-uart.2", NULL), + INIT_CLKREG(&clk_pxa25x_usb, "pxa25x-udc", NULL), + INIT_CLKREG(&clk_pxa25x_mmc, "pxa2xx-mci.0", NULL), + INIT_CLKREG(&clk_pxa25x_i2c, "pxa2xx-i2c.0", NULL), + INIT_CLKREG(&clk_pxa25x_ssp, "pxa25x-ssp.0", NULL), + INIT_CLKREG(&clk_pxa25x_nssp, "pxa25x-nssp.1", NULL), + INIT_CLKREG(&clk_pxa25x_assp, "pxa25x-nssp.2", NULL), + INIT_CLKREG(&clk_pxa25x_pwm0, "pxa25x-pwm.0", NULL), + INIT_CLKREG(&clk_pxa25x_pwm1, "pxa25x-pwm.1", NULL), + INIT_CLKREG(&clk_pxa25x_i2s, "pxa2xx-i2s", NULL), + INIT_CLKREG(&clk_pxa25x_stuart, "pxa2xx-ir", "UARTCLK"), + INIT_CLKREG(&clk_pxa25x_ficp, "pxa2xx-ir", "FICPCLK"), + INIT_CLKREG(&clk_pxa25x_ac97, NULL, "AC97CLK"), + INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"), + INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"), }; #ifdef CONFIG_PM @@ -304,13 +313,21 @@ void __init pxa25x_init_irq(void) pxa_init_gpio(85, pxa25x_set_wake); } +#ifdef CONFIG_CPU_PXA26x +void __init pxa26x_init_irq(void) +{ + pxa_init_irq(32, pxa25x_set_wake); + pxa_init_gpio(90, pxa25x_set_wake); +} +#endif + static struct platform_device *pxa25x_devices[] __initdata = { &pxa25x_device_udc, &pxa_device_ffuart, &pxa_device_btuart, &pxa_device_stuart, &pxa_device_i2s, - &pxa_device_rtc, + &sa1100_device_rtc, &pxa25x_device_ssp, &pxa25x_device_nssp, &pxa25x_device_assp, @@ -336,7 +353,7 @@ static int __init pxa25x_init(void) reset_status = RCSR; - clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks)); + clks_register(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs)); if ((ret = pxa_init_dma(16))) return ret; @@ -356,8 +373,8 @@ static int __init pxa25x_init(void) } /* Only add HWUART for PXA255/26x; PXA210/250 do not have it. */ - if (cpu_is_pxa255() || cpu_is_pxa26x()) { - clks_register(&pxa25x_hwuart_clk, 1); + if (cpu_is_pxa255()) { + clks_register(&pxa25x_hwuart_clkreg, 1); ret = platform_device_register(&pxa_device_hwuart); } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 3e4ab2279c99..411bec54fdc4 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -144,40 +144,59 @@ static const struct clkops clk_pxa27x_lcd_ops = { .getrate = clk_pxa27x_lcd_getrate, }; -static struct clk pxa27x_clks[] = { - INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev), - INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL), - - INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), - INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), - INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL), - - INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev), - INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), - INIT_CKEN("UDCCLK", USB, 48000000, 5, &pxa27x_device_udc.dev), - INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev), - INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev), - - INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev), - INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev), - INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev), - - INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev), - INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev), - INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev), - INIT_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev), - INIT_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev), - - INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL), - INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL), - - /* - INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL), - INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL), - INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL), - INIT_CKEN("IMCLK", IM, 0, 0, NULL), - INIT_CKEN("MEMCLK", MEMC, 0, 0, NULL), - */ +static DEFINE_CK(pxa27x_lcd, LCD, &clk_pxa27x_lcd_ops); +static DEFINE_CK(pxa27x_camera, CAMERA, &clk_pxa27x_lcd_ops); +static DEFINE_CKEN(pxa27x_ffuart, FFUART, 14857000, 1); +static DEFINE_CKEN(pxa27x_btuart, BTUART, 14857000, 1); +static DEFINE_CKEN(pxa27x_stuart, STUART, 14857000, 1); +static DEFINE_CKEN(pxa27x_i2s, I2S, 14682000, 0); +static DEFINE_CKEN(pxa27x_i2c, I2C, 32842000, 0); +static DEFINE_CKEN(pxa27x_usb, USB, 48000000, 5); +static DEFINE_CKEN(pxa27x_mmc, MMC, 19500000, 0); +static DEFINE_CKEN(pxa27x_ficp, FICP, 48000000, 0); +static DEFINE_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0); +static DEFINE_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0); +static DEFINE_CKEN(pxa27x_keypad, KEYPAD, 32768, 0); +static DEFINE_CKEN(pxa27x_ssp1, SSP1, 13000000, 0); +static DEFINE_CKEN(pxa27x_ssp2, SSP2, 13000000, 0); +static DEFINE_CKEN(pxa27x_ssp3, SSP3, 13000000, 0); +static DEFINE_CKEN(pxa27x_pwm0, PWM0, 13000000, 0); +static DEFINE_CKEN(pxa27x_pwm1, PWM1, 13000000, 0); +static DEFINE_CKEN(pxa27x_ac97, AC97, 24576000, 0); +static DEFINE_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0); +static DEFINE_CKEN(pxa27x_msl, MSL, 48000000, 0); +static DEFINE_CKEN(pxa27x_usim, USIM, 48000000, 0); +static DEFINE_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0); +static DEFINE_CKEN(pxa27x_im, IM, 0, 0); +static DEFINE_CKEN(pxa27x_memc, MEMC, 0, 0); + +static struct clk_lookup pxa27x_clkregs[] = { + INIT_CLKREG(&clk_pxa27x_lcd, "pxa2xx-fb", NULL), + INIT_CLKREG(&clk_pxa27x_camera, "pxa27x-camera.0", NULL), + INIT_CLKREG(&clk_pxa27x_ffuart, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_pxa27x_btuart, "pxa2xx-uart.1", NULL), + INIT_CLKREG(&clk_pxa27x_stuart, "pxa2xx-uart.2", NULL), + INIT_CLKREG(&clk_pxa27x_i2s, "pxa2xx-i2s", NULL), + INIT_CLKREG(&clk_pxa27x_i2c, "pxa2xx-i2c.0", NULL), + INIT_CLKREG(&clk_pxa27x_usb, "pxa27x-udc", NULL), + INIT_CLKREG(&clk_pxa27x_mmc, "pxa2xx-mci.0", NULL), + INIT_CLKREG(&clk_pxa27x_stuart, "pxa2xx-ir", "UARTCLK"), + INIT_CLKREG(&clk_pxa27x_ficp, "pxa2xx-ir", "FICPCLK"), + INIT_CLKREG(&clk_pxa27x_usbhost, "pxa27x-ohci", NULL), + INIT_CLKREG(&clk_pxa27x_pwri2c, "pxa2xx-i2c.1", NULL), + INIT_CLKREG(&clk_pxa27x_keypad, "pxa27x-keypad", NULL), + INIT_CLKREG(&clk_pxa27x_ssp1, "pxa27x-ssp.0", NULL), + INIT_CLKREG(&clk_pxa27x_ssp2, "pxa27x-ssp.1", NULL), + INIT_CLKREG(&clk_pxa27x_ssp3, "pxa27x-ssp.2", NULL), + INIT_CLKREG(&clk_pxa27x_pwm0, "pxa27x-pwm.0", NULL), + INIT_CLKREG(&clk_pxa27x_pwm1, "pxa27x-pwm.1", NULL), + INIT_CLKREG(&clk_pxa27x_ac97, NULL, "AC97CLK"), + INIT_CLKREG(&clk_pxa27x_ac97conf, NULL, "AC97CONFCLK"), + INIT_CLKREG(&clk_pxa27x_msl, NULL, "MSLCLK"), + INIT_CLKREG(&clk_pxa27x_usim, NULL, "USIMCLK"), + INIT_CLKREG(&clk_pxa27x_memstk, NULL, "MSTKCLK"), + INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"), + INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"), }; #ifdef CONFIG_PM @@ -313,38 +332,18 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on) void __init pxa27x_init_irq(void) { pxa_init_irq(34, pxa27x_set_wake); - pxa_init_gpio(128, pxa27x_set_wake); + pxa_init_gpio(121, pxa27x_set_wake); } /* * device registration specific to PXA27x. */ - -static struct resource i2c_power_resources[] = { - { - .start = 0x40f00180, - .end = 0x40f001a3, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_PWRI2C, - .end = IRQ_PWRI2C, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device pxa27x_device_i2c_power = { - .name = "pxa2xx-i2c", - .id = 1, - .resource = i2c_power_resources, - .num_resources = ARRAY_SIZE(i2c_power_resources), -}; - void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) { local_irq_disable(); PCFR |= PCFR_PI2CEN; local_irq_enable(); - pxa27x_device_i2c_power.dev.platform_data = info; + pxa_register_device(&pxa27x_device_i2c_power, info); } static struct platform_device *devices[] __initdata = { @@ -353,8 +352,8 @@ static struct platform_device *devices[] __initdata = { &pxa_device_btuart, &pxa_device_stuart, &pxa_device_i2s, + &sa1100_device_rtc, &pxa_device_rtc, - &pxa27x_device_i2c_power, &pxa27x_device_ssp1, &pxa27x_device_ssp2, &pxa27x_device_ssp3, @@ -380,7 +379,7 @@ static int __init pxa27x_init(void) reset_status = RCSR; - clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks)); + clks_register(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs)); if ((ret = pxa_init_dma(32))) return ret; diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 9adc7fc4618a..f735e58e6669 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -85,14 +85,16 @@ static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { MFP_ADDR_END, }; -static struct clk common_clks[] = { - PXA3xx_CKEN("NANDCLK", NAND, 156000000, 0, &pxa3xx_device_nand.dev), +static DEFINE_PXA3_CKEN(common_nand, NAND, 156000000, 0); + +static struct clk_lookup common_clkregs[] = { + INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", "NANDCLK"), }; -static struct clk pxa310_clks[] = { -#ifdef CONFIG_CPU_PXA310 - PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev), -#endif +static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0); + +static struct clk_lookup pxa310_clkregs[] = { + INIT_CLKREG(&clk_pxa310_mmc3, "pxa2xx-mci.2", "MMCCLK"), }; static int __init pxa300_init(void) @@ -100,12 +102,12 @@ static int __init pxa300_init(void) if (cpu_is_pxa300() || cpu_is_pxa310()) { pxa3xx_init_mfp(); pxa3xx_mfp_init_addr(pxa300_mfp_addr_map); - clks_register(ARRAY_AND_SIZE(common_clks)); + clks_register(ARRAY_AND_SIZE(common_clkregs)); } if (cpu_is_pxa310()) { pxa3xx_mfp_init_addr(pxa310_mfp_addr_map); - clks_register(ARRAY_AND_SIZE(pxa310_clks)); + clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); } return 0; diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index 016eb18f01a3..effe408c186f 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -80,8 +80,10 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_END, }; -static struct clk pxa320_clks[] = { - PXA3xx_CKEN("NANDCLK", NAND, 104000000, 0, &pxa3xx_device_nand.dev), +static DEFINE_PXA3_CKEN(pxa320_nand, NAND, 104000000, 0); + +static struct clk_lookup pxa320_clkregs[] = { + INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", "NANDCLK"), }; static int __init pxa320_init(void) @@ -89,7 +91,7 @@ static int __init pxa320_init(void) if (cpu_is_pxa320()) { pxa3xx_init_mfp(); pxa3xx_mfp_init_addr(pxa320_mfp_addr_map); - clks_register(ARRAY_AND_SIZE(pxa320_clks)); + clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); } return 0; diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index b3cd5d0b0f35..490893824e78 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -29,6 +29,7 @@ #include <mach/pm.h> #include <mach/dma.h> #include <mach/ssp.h> +#include <mach/i2c.h> #include "generic.h" #include "devices.h" @@ -216,43 +217,58 @@ static const struct clkops clk_dummy_ops = { .disable = clk_dummy_disable, }; -static struct clk pxa3xx_clks[] = { - { - .name = "CLK_POUT", - .ops = &clk_pout_ops, - .rate = 13000000, - .delay = 70, - }, - - /* Power I2C clock is always on */ - { - .name = "I2CCLK", - .ops = &clk_dummy_ops, - .dev = &pxa3xx_device_i2c_power.dev, - }, - - PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev), - PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL), - PXA3xx_CK("AC97CLK", AC97, &clk_pxa3xx_ac97_ops, NULL), - - PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), - PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), - PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL), - - PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), - PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa27x_device_udc.dev), - PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev), - PXA3xx_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev), +static struct clk clk_pxa3xx_pout = { + .ops = &clk_pout_ops, + .rate = 13000000, + .delay = 70, +}; - PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev), - PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev), - PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev), - PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev), - PXA3xx_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev), - PXA3xx_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev), +static struct clk clk_dummy = { + .ops = &clk_dummy_ops, +}; - PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev), - PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev), +static DEFINE_PXA3_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops); +static DEFINE_PXA3_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops); +static DEFINE_PXA3_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops); +static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1); +static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1); +static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1); +static DEFINE_PXA3_CKEN(pxa3xx_i2c, I2C, 32842000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_udc, UDC, 48000000, 5); +static DEFINE_PXA3_CKEN(pxa3xx_usbh, USBH, 48000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_keypad, KEYPAD, 32768, 0); +static DEFINE_PXA3_CKEN(pxa3xx_ssp1, SSP1, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_ssp2, SSP2, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_ssp3, SSP3, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_ssp4, SSP4, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_pwm0, PWM0, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM1, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0); + +static struct clk_lookup pxa3xx_clkregs[] = { + INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"), + /* Power I2C clock is always on */ + INIT_CLKREG(&clk_dummy, "pxa2xx-i2c.1", NULL), + INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL), + INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"), + INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"), + INIT_CLKREG(&clk_pxa3xx_ffuart, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_pxa3xx_btuart, "pxa2xx-uart.1", NULL), + INIT_CLKREG(&clk_pxa3xx_stuart, "pxa2xx-uart.2", NULL), + INIT_CLKREG(&clk_pxa3xx_stuart, "pxa2xx-ir", "UARTCLK"), + INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL), + INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL), + INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL), + INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL), + INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa27x-ssp.0", NULL), + INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa27x-ssp.1", NULL), + INIT_CLKREG(&clk_pxa3xx_ssp3, "pxa27x-ssp.2", NULL), + INIT_CLKREG(&clk_pxa3xx_ssp4, "pxa27x-ssp.3", NULL), + INIT_CLKREG(&clk_pxa3xx_pwm0, "pxa27x-pwm.0", NULL), + INIT_CLKREG(&clk_pxa3xx_pwm1, "pxa27x-pwm.1", NULL), + INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL), + INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL), }; #ifdef CONFIG_PM @@ -529,28 +545,9 @@ void __init pxa3xx_init_irq(void) * device registration specific to PXA3xx. */ -static struct resource i2c_power_resources[] = { - { - .start = 0x40f500c0, - .end = 0x40f500d3, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_PWRI2C, - .end = IRQ_PWRI2C, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device pxa3xx_device_i2c_power = { - .name = "pxa2xx-i2c", - .id = 1, - .resource = i2c_power_resources, - .num_resources = ARRAY_SIZE(i2c_power_resources), -}; - void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) { - pxa3xx_device_i2c_power.dev.platform_data = info; + pxa_register_device(&pxa3xx_device_i2c_power, info); } static struct platform_device *devices[] __initdata = { @@ -559,6 +556,7 @@ static struct platform_device *devices[] __initdata = { &pxa_device_btuart, &pxa_device_stuart, &pxa_device_i2s, + &sa1100_device_rtc, &pxa_device_rtc, &pxa27x_device_ssp1, &pxa27x_device_ssp2, @@ -566,7 +564,6 @@ static struct platform_device *devices[] __initdata = { &pxa3xx_device_ssp4, &pxa27x_device_pwm0, &pxa27x_device_pwm1, - &pxa3xx_device_i2c_power, }; static struct sys_device pxa3xx_sysdev[] = { @@ -595,7 +592,7 @@ static int __init pxa3xx_init(void) */ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); - clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks)); + clks_register(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs)); if ((ret = pxa_init_dma(32))) return ret; diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index e7ea91ce7f02..5d02a7325586 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -17,19 +17,44 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/i2c.h> #include <linux/smc91x.h> +#include <linux/mfd/da903x.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/hardware.h> #include <mach/pxa3xx-regs.h> #include <mach/mfp-pxa930.h> +#include <mach/i2c.h> +#include <mach/regs-lcd.h> +#include <mach/pxafb.h> #include "devices.h" #include "generic.h" +#define GPIO_LCD_RESET (16) + /* SAAR MFP configurations */ static mfp_cfg_t saar_mfp_cfg[] __initdata = { + /* LCD */ + GPIO23_LCD_DD0, + GPIO24_LCD_DD1, + GPIO25_LCD_DD2, + GPIO26_LCD_DD3, + GPIO27_LCD_DD4, + GPIO28_LCD_DD5, + GPIO29_LCD_DD6, + GPIO44_LCD_DD7, + GPIO21_LCD_CS, + GPIO22_LCD_VSYNC, + GPIO17_LCD_FCLK_RD, + GPIO18_LCD_LCLK_A0, + GPIO19_LCD_PCLK_WR, + GPIO16_GPIO, /* LCD reset */ + /* Ethernet */ DF_nCS1_nCS3, GPIO97_GPIO, @@ -64,12 +89,408 @@ static struct platform_device smc91x_device = { }, }; +#if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULE) +static uint16_t lcd_power_on[] = { + /* single frame */ + SMART_CMD_NOOP, + SMART_CMD(0x00), + SMART_DELAY(0), + + SMART_CMD_NOOP, + SMART_CMD(0x00), + SMART_DELAY(0), + + SMART_CMD_NOOP, + SMART_CMD(0x00), + SMART_DELAY(0), + + SMART_CMD_NOOP, + SMART_CMD(0x00), + SMART_DELAY(10), + + /* calibration control */ + SMART_CMD(0x00), + SMART_CMD(0xA4), + SMART_DAT(0x80), + SMART_DAT(0x01), + SMART_DELAY(150), + + /*Power-On Init sequence*/ + SMART_CMD(0x00), /* output ctrl */ + SMART_CMD(0x01), + SMART_DAT(0x01), + SMART_DAT(0x00), + SMART_CMD(0x00), /* wave ctrl */ + SMART_CMD(0x02), + SMART_DAT(0x07), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x03), /* entry mode */ + SMART_DAT(0xD0), + SMART_DAT(0x30), + SMART_CMD(0x00), + SMART_CMD(0x08), /* display ctrl 2 */ + SMART_DAT(0x08), + SMART_DAT(0x08), + SMART_CMD(0x00), + SMART_CMD(0x09), /* display ctrl 3 */ + SMART_DAT(0x04), + SMART_DAT(0x2F), + SMART_CMD(0x00), + SMART_CMD(0x0A), /* display ctrl 4 */ + SMART_DAT(0x00), + SMART_DAT(0x08), + SMART_CMD(0x00), + SMART_CMD(0x0D), /* Frame Marker position */ + SMART_DAT(0x00), + SMART_DAT(0x08), + SMART_CMD(0x00), + SMART_CMD(0x60), /* Driver output control */ + SMART_DAT(0x27), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x61), /* Base image display control */ + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_CMD(0x00), + SMART_CMD(0x30), /* Y settings 30h-3Dh */ + SMART_DAT(0x07), + SMART_DAT(0x07), + SMART_CMD(0x00), + SMART_CMD(0x31), + SMART_DAT(0x00), + SMART_DAT(0x07), + SMART_CMD(0x00), + SMART_CMD(0x32), /* Timing(3), ASW HOLD=0.5CLK */ + SMART_DAT(0x04), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x33), /* Timing(4), CKV ST=0CLK, CKV ED=1CLK */ + SMART_DAT(0x03), + SMART_DAT(0x03), + SMART_CMD(0x00), + SMART_CMD(0x34), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x35), + SMART_DAT(0x02), + SMART_DAT(0x05), + SMART_CMD(0x00), + SMART_CMD(0x36), + SMART_DAT(0x1F), + SMART_DAT(0x1F), + SMART_CMD(0x00), + SMART_CMD(0x37), + SMART_DAT(0x07), + SMART_DAT(0x07), + SMART_CMD(0x00), + SMART_CMD(0x38), + SMART_DAT(0x00), + SMART_DAT(0x07), + SMART_CMD(0x00), + SMART_CMD(0x39), + SMART_DAT(0x04), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x3A), + SMART_DAT(0x03), + SMART_DAT(0x03), + SMART_CMD(0x00), + SMART_CMD(0x3B), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x3C), + SMART_DAT(0x02), + SMART_DAT(0x05), + SMART_CMD(0x00), + SMART_CMD(0x3D), + SMART_DAT(0x1F), + SMART_DAT(0x1F), + SMART_CMD(0x00), /* Display control 1 */ + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_CMD(0x00), /* Power control 5 */ + SMART_CMD(0x17), + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_CMD(0x00), /* Power control 1 */ + SMART_CMD(0x10), + SMART_DAT(0x10), + SMART_DAT(0xB0), + SMART_CMD(0x00), /* Power control 2 */ + SMART_CMD(0x11), + SMART_DAT(0x01), + SMART_DAT(0x30), + SMART_CMD(0x00), /* Power control 3 */ + SMART_CMD(0x12), + SMART_DAT(0x01), + SMART_DAT(0x9E), + SMART_CMD(0x00), /* Power control 4 */ + SMART_CMD(0x13), + SMART_DAT(0x17), + SMART_DAT(0x00), + SMART_CMD(0x00), /* Power control 3 */ + SMART_CMD(0x12), + SMART_DAT(0x01), + SMART_DAT(0xBE), + SMART_DELAY(100), + + /* display mode : 240*320 */ + SMART_CMD(0x00), /* RAM address set(H) 0*/ + SMART_CMD(0x20), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* RAM address set(V) 4*/ + SMART_CMD(0x21), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* Start of Window RAM address set(H) 8*/ + SMART_CMD(0x50), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* End of Window RAM address set(H) 12*/ + SMART_CMD(0x51), + SMART_DAT(0x00), + SMART_DAT(0xEF), + SMART_CMD(0x00), /* Start of Window RAM address set(V) 16*/ + SMART_CMD(0x52), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* End of Window RAM address set(V) 20*/ + SMART_CMD(0x53), + SMART_DAT(0x01), + SMART_DAT(0x3F), + SMART_CMD(0x00), /* Panel interface control 1 */ + SMART_CMD(0x90), + SMART_DAT(0x00), + SMART_DAT(0x1A), + SMART_CMD(0x00), /* Panel interface control 2 */ + SMART_CMD(0x92), + SMART_DAT(0x04), + SMART_DAT(0x00), + SMART_CMD(0x00), /* Panel interface control 3 */ + SMART_CMD(0x93), + SMART_DAT(0x00), + SMART_DAT(0x05), + SMART_DELAY(20), +}; + +static uint16_t lcd_panel_on[] = { + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x21), + SMART_DELAY(1), + + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x61), + SMART_DELAY(100), + + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x01), + SMART_DAT(0x73), + SMART_DELAY(1), +}; + +static uint16_t lcd_panel_off[] = { + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x72), + SMART_DELAY(40), + + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_DELAY(1), + + SMART_CMD(0x00), + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_DELAY(1), +}; + +static uint16_t lcd_power_off[] = { + SMART_CMD(0x00), + SMART_CMD(0x10), + SMART_DAT(0x00), + SMART_DAT(0x80), + + SMART_CMD(0x00), + SMART_CMD(0x11), + SMART_DAT(0x01), + SMART_DAT(0x60), + + SMART_CMD(0x00), + SMART_CMD(0x12), + SMART_DAT(0x01), + SMART_DAT(0xAE), + SMART_DELAY(40), + + SMART_CMD(0x00), + SMART_CMD(0x10), + SMART_DAT(0x00), + SMART_DAT(0x00), +}; + +static uint16_t update_framedata[] = { + /* set display ram: 240*320 */ + SMART_CMD(0x00), /* RAM address set(H) 0*/ + SMART_CMD(0x20), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* RAM address set(V) 4*/ + SMART_CMD(0x21), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* Start of Window RAM address set(H) 8 */ + SMART_CMD(0x50), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* End of Window RAM address set(H) 12 */ + SMART_CMD(0x51), + SMART_DAT(0x00), + SMART_DAT(0xEF), + SMART_CMD(0x00), /* Start of Window RAM address set(V) 16 */ + SMART_CMD(0x52), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), /* End of Window RAM address set(V) 20 */ + SMART_CMD(0x53), + SMART_DAT(0x01), + SMART_DAT(0x3F), + + /* wait for vsync cmd before transferring frame data */ + SMART_CMD_WAIT_FOR_VSYNC, + + /* write ram */ + SMART_CMD(0x00), + SMART_CMD(0x22), + + /* write frame data */ + SMART_CMD_WRITE_FRAME, +}; + +static void ltm022a97a_lcd_power(int on, struct fb_var_screeninfo *var) +{ + static int pin_requested = 0; + struct fb_info *info = container_of(var, struct fb_info, var); + int err; + + if (!pin_requested) { + err = gpio_request(GPIO_LCD_RESET, "lcd reset"); + if (err) { + pr_err("failed to request gpio for LCD reset\n"); + return; + } + + gpio_direction_output(GPIO_LCD_RESET, 0); + pin_requested = 1; + } + + if (on) { + gpio_set_value(GPIO_LCD_RESET, 0); msleep(100); + gpio_set_value(GPIO_LCD_RESET, 1); msleep(10); + + pxafb_smart_queue(info, ARRAY_AND_SIZE(lcd_power_on)); + pxafb_smart_queue(info, ARRAY_AND_SIZE(lcd_panel_on)); + } else { + pxafb_smart_queue(info, ARRAY_AND_SIZE(lcd_panel_off)); + pxafb_smart_queue(info, ARRAY_AND_SIZE(lcd_power_off)); + } + + err = pxafb_smart_flush(info); + if (err) + pr_err("%s: timed out\n", __func__); +} + +static void ltm022a97a_update(struct fb_info *info) +{ + pxafb_smart_queue(info, ARRAY_AND_SIZE(update_framedata)); + pxafb_smart_flush(info); +} + +static struct pxafb_mode_info toshiba_ltm022a97a_modes[] = { + [0] = { + .xres = 240, + .yres = 320, + .bpp = 16, + .a0csrd_set_hld = 30, + .a0cswr_set_hld = 30, + .wr_pulse_width = 30, + .rd_pulse_width = 30, + .op_hold_time = 30, + .cmd_inh_time = 60, + + /* L_LCLK_A0 and L_LCLK_RD active low */ + .sync = FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT, + }, +}; + +static struct pxafb_mach_info saar_lcd_info = { + .modes = toshiba_ltm022a97a_modes, + .num_modes = 1, + .lcd_conn = LCD_SMART_PANEL_8BPP | LCD_PCLK_EDGE_FALL, + .pxafb_lcd_power = ltm022a97a_lcd_power, + .smart_update = ltm022a97a_update, +}; + +static void __init saar_init_lcd(void) +{ + set_pxa_fb_info(&saar_lcd_info); +} +#else +static inline void saar_init_lcd(void) {} +#endif + +#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE) +static struct da903x_subdev_info saar_da9034_subdevs[] = { + [0] = { + .name = "da903x-backlight", + .id = DA9034_ID_WLED, + }, +}; + +static struct da903x_platform_data saar_da9034_info = { + .num_subdevs = ARRAY_SIZE(saar_da9034_subdevs), + .subdevs = saar_da9034_subdevs, +}; + +static struct i2c_board_info saar_i2c_info[] = { + [0] = { + .type = "da9034", + .addr = 0x34, + .platform_data = &saar_da9034_info, + .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + }, +}; + +static void __init saar_init_i2c(void) +{ + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(saar_i2c_info)); +} +#else +static inline void saar_init_i2c(void) {} +#endif static void __init saar_init(void) { /* initialize MFP configurations */ pxa3xx_mfp_config(ARRAY_AND_SIZE(saar_mfp_cfg)); platform_device_register(&smc91x_device); + + saar_init_i2c(); + saar_init_lcd(); } MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)") diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c index ad346addc028..d6f6904132a6 100644 --- a/arch/arm/mach-pxa/smemc.c +++ b/arch/arm/mach-pxa/smemc.c @@ -8,6 +8,8 @@ #include <linux/io.h> #include <linux/sysdev.h> +#include <mach/hardware.h> + #define SMEMC_PHYS_BASE (0x4A000000) #define SMEMC_PHYS_SIZE (0x90) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 3be76ee2bdbf..7299d87a1cb3 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -22,6 +22,7 @@ #include <linux/gpio.h> #include <linux/leds.h> #include <linux/mmc/host.h> +#include <linux/mtd/physmap.h> #include <linux/pm.h> #include <linux/backlight.h> #include <linux/io.h> @@ -122,6 +123,10 @@ static unsigned long spitz_pin_config[] __initdata = { GPIO105_GPIO, /* SPITZ_GPIO_CF_IRQ */ GPIO106_GPIO, /* SPITZ_GPIO_CF2_IRQ */ + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, }; @@ -609,10 +614,41 @@ static struct pxafb_mach_info spitz_pxafb_info = { }; +static struct mtd_partition sharpsl_rom_parts[] = { + { + .name ="Boot PROM Filesystem", + .offset = 0x00140000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data sharpsl_rom_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(sharpsl_rom_parts), + .parts = sharpsl_rom_parts, +}; + +static struct resource sharpsl_rom_resources[] = { + { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sharpsl_rom_device = { + .name = "physmap-flash", + .id = -1, + .resource = sharpsl_rom_resources, + .num_resources = ARRAY_SIZE(sharpsl_rom_resources), + .dev.platform_data = &sharpsl_rom_data, +}; + static struct platform_device *devices[] __initdata = { &spitzscoop_device, &spitzkbd_device, &spitzled_device, + &sharpsl_rom_device, }; static void spitz_poweroff(void) diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 2c31ec725688..6f42004db3ed 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -356,7 +356,7 @@ static int __devinit ssp_probe(struct platform_device *pdev, int type) } ssp->pdev = pdev; - ssp->clk = clk_get(&pdev->dev, "SSPCLK"); + ssp->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(ssp->clk)) { ret = PTR_ERR(ssp->clk); goto err_free; diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index 589d32b4fc46..58ef08a5224b 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -18,12 +18,15 @@ #include <linux/clk.h> #include <linux/gpio.h> #include <linux/smc91x.h> +#include <linux/pwm_backlight.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/hardware.h> #include <mach/pxa3xx-regs.h> #include <mach/mfp-pxa930.h> +#include <mach/pxafb.h> +#include <mach/pxa27x_keypad.h> #include "devices.h" #include "generic.h" @@ -33,6 +36,45 @@ static mfp_cfg_t tavorevb_mfp_cfg[] __initdata = { /* Ethernet */ DF_nCS1_nCS3, GPIO47_GPIO, + + /* LCD */ + GPIO23_LCD_DD0, + GPIO24_LCD_DD1, + GPIO25_LCD_DD2, + GPIO26_LCD_DD3, + GPIO27_LCD_DD4, + GPIO28_LCD_DD5, + GPIO29_LCD_DD6, + GPIO44_LCD_DD7, + GPIO21_LCD_CS, + GPIO22_LCD_CS2, + + GPIO17_LCD_FCLK_RD, + GPIO18_LCD_LCLK_A0, + GPIO19_LCD_PCLK_WR, + + /* LCD Backlight */ + GPIO43_PWM3, /* primary backlight */ + GPIO32_PWM0, /* secondary backlight */ + + /* Keypad */ + GPIO0_KP_MKIN_0, + GPIO2_KP_MKIN_1, + GPIO4_KP_MKIN_2, + GPIO6_KP_MKIN_3, + GPIO8_KP_MKIN_4, + GPIO10_KP_MKIN_5, + GPIO12_KP_MKIN_6, + GPIO1_KP_MKOUT_0, + GPIO3_KP_MKOUT_1, + GPIO5_KP_MKOUT_2, + GPIO7_KP_MKOUT_3, + GPIO9_KP_MKOUT_4, + GPIO11_KP_MKOUT_5, + GPIO13_KP_MKOUT_6, + + GPIO14_KP_DKIN_2, + GPIO15_KP_DKIN_3, }; #define TAVOREVB_ETH_PHYS (0x14000000) @@ -64,12 +106,382 @@ static struct platform_device smc91x_device = { }, }; +#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) +static unsigned int tavorevb_matrix_key_map[] = { + /* KEY(row, col, key_code) */ + KEY(0, 4, KEY_A), KEY(0, 5, KEY_B), KEY(0, 6, KEY_C), + KEY(1, 4, KEY_E), KEY(1, 5, KEY_F), KEY(1, 6, KEY_G), + KEY(2, 4, KEY_I), KEY(2, 5, KEY_J), KEY(2, 6, KEY_K), + KEY(3, 4, KEY_M), KEY(3, 5, KEY_N), KEY(3, 6, KEY_O), + KEY(4, 5, KEY_R), KEY(4, 6, KEY_S), + KEY(5, 4, KEY_U), KEY(5, 4, KEY_V), KEY(5, 6, KEY_W), + + KEY(6, 4, KEY_Y), KEY(6, 5, KEY_Z), + + KEY(0, 3, KEY_0), KEY(2, 0, KEY_1), KEY(2, 1, KEY_2), KEY(2, 2, KEY_3), + KEY(2, 3, KEY_4), KEY(1, 0, KEY_5), KEY(1, 1, KEY_6), KEY(1, 2, KEY_7), + KEY(1, 3, KEY_8), KEY(0, 2, KEY_9), + + KEY(6, 6, KEY_SPACE), + KEY(0, 0, KEY_KPASTERISK), /* * */ + KEY(0, 1, KEY_KPDOT), /* # */ + + KEY(4, 1, KEY_UP), + KEY(4, 3, KEY_DOWN), + KEY(4, 0, KEY_LEFT), + KEY(4, 2, KEY_RIGHT), + KEY(6, 0, KEY_HOME), + KEY(3, 2, KEY_END), + KEY(6, 1, KEY_DELETE), + KEY(5, 2, KEY_BACK), + KEY(6, 3, KEY_CAPSLOCK), /* KEY_LEFTSHIFT), */ + + KEY(4, 4, KEY_ENTER), /* scroll push */ + KEY(6, 2, KEY_ENTER), /* keypad action */ + + KEY(3, 1, KEY_SEND), + KEY(5, 3, KEY_RECORD), + KEY(5, 0, KEY_VOLUMEUP), + KEY(5, 1, KEY_VOLUMEDOWN), + + KEY(3, 0, KEY_F22), /* soft1 */ + KEY(3, 3, KEY_F23), /* soft2 */ +}; + +static struct pxa27x_keypad_platform_data tavorevb_keypad_info = { + .matrix_key_rows = 7, + .matrix_key_cols = 7, + .matrix_key_map = tavorevb_matrix_key_map, + .matrix_key_map_size = ARRAY_SIZE(tavorevb_matrix_key_map), + .debounce_interval = 30, +}; + +static void __init tavorevb_init_keypad(void) +{ + pxa_set_keypad_info(&tavorevb_keypad_info); +} +#else +static inline void tavorevb_init_keypad(void) {} +#endif /* CONFIG_KEYBOARD_PXA27x || CONFIG_KEYBOARD_PXA27x_MODULE */ + +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static struct platform_pwm_backlight_data tavorevb_backlight_data[] = { + [0] = { + /* primary backlight */ + .pwm_id = 2, + .max_brightness = 100, + .dft_brightness = 100, + .pwm_period_ns = 100000, + }, + [1] = { + /* secondary backlight */ + .pwm_id = 0, + .max_brightness = 100, + .dft_brightness = 100, + .pwm_period_ns = 100000, + }, +}; + +static struct platform_device tavorevb_backlight_devices[] = { + [0] = { + .name = "pwm-backlight", + .id = 0, + .dev = { + .platform_data = &tavorevb_backlight_data[0], + }, + }, + [1] = { + .name = "pwm-backlight", + .id = 1, + .dev = { + .platform_data = &tavorevb_backlight_data[1], + }, + }, +}; + +static uint16_t panel_init[] = { + /* DSTB OUT */ + SMART_CMD(0x00), + SMART_CMD_NOOP, + SMART_DELAY(1), + + SMART_CMD(0x00), + SMART_CMD_NOOP, + SMART_DELAY(1), + + SMART_CMD(0x00), + SMART_CMD_NOOP, + SMART_DELAY(1), + + /* STB OUT */ + SMART_CMD(0x00), + SMART_CMD(0x1D), + SMART_DAT(0x00), + SMART_DAT(0x05), + SMART_DELAY(1), + + /* P-ON Init sequence */ + SMART_CMD(0x00), /* OSC ON */ + SMART_CMD(0x00), + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_CMD(0x00), + SMART_CMD(0x01), /* SOURCE DRIVER SHIFT DIRECTION and display RAM setting */ + SMART_DAT(0x01), + SMART_DAT(0x27), + SMART_CMD(0x00), + SMART_CMD(0x02), /* LINE INV */ + SMART_DAT(0x02), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x03), /* IF mode(1) */ + SMART_DAT(0x01), /* 8bit smart mode(8-8),high speed write mode */ + SMART_DAT(0x30), + SMART_CMD(0x07), + SMART_CMD(0x00), /* RAM Write Mode */ + SMART_DAT(0x00), + SMART_DAT(0x03), + SMART_CMD(0x00), + + /* DISPLAY Setting, 262K, fixed(NO scroll), no split screen */ + SMART_CMD(0x07), + SMART_DAT(0x40), /* 16/18/19 BPP */ + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x08), /* BP, FP Seting, BP=2H, FP=3H */ + SMART_DAT(0x03), + SMART_DAT(0x02), + SMART_CMD(0x00), + SMART_CMD(0x0C), /* IF mode(2), using internal clock & MPU */ + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x0D), /* Frame setting, 1Min. Frequence, 16CLK */ + SMART_DAT(0x00), + SMART_DAT(0x10), + SMART_CMD(0x00), + SMART_CMD(0x12), /* Timing(1),ASW W=4CLK, ASW ST=1CLK */ + SMART_DAT(0x03), + SMART_DAT(0x02), + SMART_CMD(0x00), + SMART_CMD(0x13), /* Timing(2),OEV ST=0.5CLK, OEV ED=1CLK */ + SMART_DAT(0x01), + SMART_DAT(0x02), + SMART_CMD(0x00), + SMART_CMD(0x14), /* Timing(3), ASW HOLD=0.5CLK */ + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x15), /* Timing(4), CKV ST=0CLK, CKV ED=1CLK */ + SMART_DAT(0x20), + SMART_DAT(0x00), + SMART_CMD(0x00), + SMART_CMD(0x1C), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x03), + SMART_CMD(0x00), + SMART_DAT(0x04), + SMART_DAT(0x03), + SMART_CMD(0x03), + SMART_CMD(0x01), + SMART_DAT(0x03), + SMART_DAT(0x04), + SMART_CMD(0x03), + SMART_CMD(0x02), + SMART_DAT(0x04), + SMART_DAT(0x03), + SMART_CMD(0x03), + SMART_CMD(0x03), + SMART_DAT(0x03), + SMART_DAT(0x03), + SMART_CMD(0x03), + SMART_CMD(0x04), + SMART_DAT(0x01), + SMART_DAT(0x01), + SMART_CMD(0x03), + SMART_CMD(0x05), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x04), + SMART_CMD(0x02), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x04), + SMART_CMD(0x03), + SMART_DAT(0x01), + SMART_DAT(0x3F), + SMART_DELAY(0), + + /* DISP RAM setting: 240*320 */ + SMART_CMD(0x04), /* HADDR, START 0 */ + SMART_CMD(0x06), + SMART_DAT(0x00), + SMART_DAT(0x00), /* x1,3 */ + SMART_CMD(0x04), /* HADDR, END 4 */ + SMART_CMD(0x07), + SMART_DAT(0x00), + SMART_DAT(0xEF), /* x2, 7 */ + SMART_CMD(0x04), /* VADDR, START 8 */ + SMART_CMD(0x08), + SMART_DAT(0x00), /* y1, 10 */ + SMART_DAT(0x00), /* y1, 11 */ + SMART_CMD(0x04), /* VADDR, END 12 */ + SMART_CMD(0x09), + SMART_DAT(0x01), /* y2, 14 */ + SMART_DAT(0x3F), /* y2, 15 */ + SMART_CMD(0x02), /* RAM ADDR SETTING 16 */ + SMART_CMD(0x00), + SMART_DAT(0x00), + SMART_DAT(0x00), /* x1, 19 */ + SMART_CMD(0x02), /* RAM ADDR SETTING 20 */ + SMART_CMD(0x01), + SMART_DAT(0x00), /* y1, 22 */ + SMART_DAT(0x00), /* y1, 23 */ +}; + +static uint16_t panel_on[] = { + /* Power-IC ON */ + SMART_CMD(0x01), + SMART_CMD(0x02), + SMART_DAT(0x07), + SMART_DAT(0x7D), + SMART_CMD(0x01), + SMART_CMD(0x03), + SMART_DAT(0x00), + SMART_DAT(0x05), + SMART_CMD(0x01), + SMART_CMD(0x04), + SMART_DAT(0x00), + SMART_DAT(0x00), + SMART_CMD(0x01), + SMART_CMD(0x05), + SMART_DAT(0x00), + SMART_DAT(0x15), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xC0), + SMART_DAT(0x10), + SMART_DELAY(30), + + /* DISP ON */ + SMART_CMD(0x01), + SMART_CMD(0x01), + SMART_DAT(0x00), + SMART_DAT(0x01), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xFF), + SMART_DAT(0xFE), + SMART_DELAY(150), +}; + +static uint16_t panel_off[] = { + SMART_CMD(0x00), + SMART_CMD(0x1E), + SMART_DAT(0x00), + SMART_DAT(0x0A), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xFF), + SMART_DAT(0xEE), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xF8), + SMART_DAT(0x12), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xE8), + SMART_DAT(0x11), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0xC0), + SMART_DAT(0x11), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0x40), + SMART_DAT(0x11), + SMART_CMD(0x01), + SMART_CMD(0x00), + SMART_DAT(0x00), + SMART_DAT(0x10), +}; + +static uint16_t update_framedata[] = { + /* write ram */ + SMART_CMD(0x02), + SMART_CMD(0x02), + + /* write frame data */ + SMART_CMD_WRITE_FRAME, +}; + +static void ltm020d550_lcd_power(int on, struct fb_var_screeninfo *var) +{ + struct fb_info *info = container_of(var, struct fb_info, var); + + if (on) { + pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_init)); + pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_on)); + } else { + pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_off)); + } + + if (pxafb_smart_flush(info)) + pr_err("%s: timed out\n", __func__); +} + +static void ltm020d550_update(struct fb_info *info) +{ + pxafb_smart_queue(info, ARRAY_AND_SIZE(update_framedata)); + pxafb_smart_flush(info); +} + +static struct pxafb_mode_info toshiba_ltm020d550_modes[] = { + [0] = { + .xres = 240, + .yres = 320, + .bpp = 16, + .a0csrd_set_hld = 30, + .a0cswr_set_hld = 30, + .wr_pulse_width = 30, + .rd_pulse_width = 170, + .op_hold_time = 30, + .cmd_inh_time = 60, + + /* L_LCLK_A0 and L_LCLK_RD active low */ + .sync = FB_SYNC_HOR_HIGH_ACT | + FB_SYNC_VERT_HIGH_ACT, + }, +}; + +static struct pxafb_mach_info tavorevb_lcd_info = { + .modes = toshiba_ltm020d550_modes, + .num_modes = 1, + .lcd_conn = LCD_SMART_PANEL_8BPP | LCD_PCLK_EDGE_FALL, + .pxafb_lcd_power = ltm020d550_lcd_power, + .smart_update = ltm020d550_update, +}; + +static void __init tavorevb_init_lcd(void) +{ + platform_device_register(&tavorevb_backlight_devices[0]); + platform_device_register(&tavorevb_backlight_devices[1]); + set_pxa_fb_info(&tavorevb_lcd_info); +} +#else +static inline void tavorevb_init_lcd(void) {} +#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */ + static void __init tavorevb_init(void) { /* initialize MFP configurations */ pxa3xx_mfp_config(ARRAY_AND_SIZE(tavorevb_mfp_cfg)); platform_device_register(&smc91x_device); + + tavorevb_init_lcd(); + tavorevb_init_keypad(); } MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)") diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index f8a9a62959e5..001624158519 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -22,8 +22,8 @@ #include <asm/div64.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> +#include <mach/hardware.h> #include <mach/pxa-regs.h> -#include <asm/mach-types.h> /* * This is PXA's sched_clock implementation. This has a resolution @@ -150,18 +150,11 @@ static struct irqaction pxa_ost0_irq = { static void __init pxa_timer_init(void) { - unsigned long clock_tick_rate; + unsigned long clock_tick_rate = get_clock_tick_rate(); OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; - if (cpu_is_pxa25x()) - clock_tick_rate = 3686400; - else if (machine_is_mainstone()) - clock_tick_rate = 3249600; - else - clock_tick_rate = 3250000; - set_oscr2ns_scale(clock_tick_rate); ckevt_pxa_osmr0.mult = diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 224897a67d15..3332e5d0356c 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -25,6 +25,7 @@ #include <linux/mfd/tmio.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> #include <linux/pm.h> #include <linux/gpio_keys.h> #include <linux/input.h> @@ -733,6 +734,45 @@ static void tosa_tc6393xb_teardown(struct platform_device *dev) gpio_free(TOSA_GPIO_CARD_VCC_ON); } +#ifdef CONFIG_MFD_TC6393XB +static struct fb_videomode tosa_tc6393xb_lcd_mode[] = { + { + .xres = 480, + .yres = 640, + .pixclock = 0x002cdf00,/* PLL divisor */ + .left_margin = 0x004c, + .right_margin = 0x005b, + .upper_margin = 0x0001, + .lower_margin = 0x000d, + .hsync_len = 0x0002, + .vsync_len = 0x0001, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + },{ + .xres = 240, + .yres = 320, + .pixclock = 0x00e7f203,/* PLL divisor */ + .left_margin = 0x0024, + .right_margin = 0x002f, + .upper_margin = 0x0001, + .lower_margin = 0x000d, + .hsync_len = 0x0002, + .vsync_len = 0x0001, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + } +}; + +static struct tmio_fb_data tosa_tc6393xb_fb_config = { + .lcd_set_power = tc6393xb_lcd_set_power, + .lcd_mode = tc6393xb_lcd_mode, + .num_modes = ARRAY_SIZE(tosa_tc6393xb_lcd_mode), + .modes = &tosa_tc6393xb_lcd_mode[0], + .height = 82, + .width = 60, +}; +#endif + static struct tc6393xb_platform_data tosa_tc6393xb_data = { .scr_pll2cr = 0x0cc1, .scr_gper = 0x3300, @@ -748,6 +788,9 @@ static struct tc6393xb_platform_data tosa_tc6393xb_data = { .resume = tosa_tc6393xb_resume, .nand_data = &tosa_tc6393xb_nand_config, +#ifdef CONFIG_MFD_TC6393XB + .fb_data = &tosa_tc6393xb_fb_config, +#endif .resume_restore = 1, }; @@ -789,6 +832,36 @@ static struct spi_board_info spi_board_info[] __initdata = { }, }; +static struct mtd_partition sharpsl_rom_parts[] = { + { + .name ="Boot PROM Filesystem", + .offset = 0x00160000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data sharpsl_rom_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(sharpsl_rom_parts), + .parts = sharpsl_rom_parts, +}; + +static struct resource sharpsl_rom_resources[] = { + { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sharpsl_rom_device = { + .name = "physmap-flash", + .id = -1, + .resource = sharpsl_rom_resources, + .num_resources = ARRAY_SIZE(sharpsl_rom_resources), + .dev.platform_data = &sharpsl_rom_data, +}; + static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, @@ -798,6 +871,7 @@ static struct platform_device *devices[] __initdata = { &tosa_gpio_keys_device, &tosaled_device, &tosa_bt_device, + &sharpsl_rom_device, }; static void tosa_poweroff(void) diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 813804433466..218d2001f1df 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <linux/pwm_backlight.h> #include <linux/smc91x.h> @@ -25,7 +26,6 @@ #include <asm/mach/arch.h> #include <mach/hardware.h> #include <mach/audio.h> -#include <mach/gpio.h> #include <mach/pxafb.h> #include <mach/zylonite.h> #include <mach/mmc.h> diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c index 0f244744daae..28e4e623780b 100644 --- a/arch/arm/mach-pxa/zylonite_pxa320.c +++ b/arch/arm/mach-pxa/zylonite_pxa320.c @@ -16,8 +16,8 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/gpio.h> -#include <mach/gpio.h> #include <mach/mfp-pxa320.h> #include <mach/zylonite.h> diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 5ccde7cf39e8..ad911854eb4c 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -7,9 +7,17 @@ config MACH_REALVIEW_EB help Include support for the ARM(R) RealView Emulation Baseboard platform. +config REALVIEW_EB_A9MP + bool "Support Multicore Cortex-A9" + depends on MACH_REALVIEW_EB + select CPU_V7 + help + Enable support for the Cortex-A9MPCore tile on the Realview platform. + config REALVIEW_EB_ARM11MP bool "Support ARM11MPCore tile" depends on MACH_REALVIEW_EB + select CPU_V6 help Enable support for the ARM11MPCore tile on the Realview platform. @@ -25,6 +33,7 @@ config REALVIEW_EB_ARM11MP_REVB config MACH_REALVIEW_PB11MP bool "Support RealView/PB11MPCore platform" + select CPU_V6 select ARM_GIC help Include support for the ARM(R) RealView MPCore Platform Baseboard. @@ -33,8 +42,29 @@ config MACH_REALVIEW_PB11MP config MACH_REALVIEW_PB1176 bool "Support RealView/PB1176 platform" + select CPU_V6 select ARM_GIC help Include support for the ARM(R) RealView ARM1176 Platform Baseboard. +config MACH_REALVIEW_PBA8 + bool "Support RealView/PB-A8 platform" + select CPU_V7 + select ARM_GIC + help + Include support for the ARM(R) RealView Cortex-A8 Platform Baseboard. + PB-A8 is a platform with an on-board Cortex-A8 and has support for + PCI-E and Compact Flash. + +config REALVIEW_HIGH_PHYS_OFFSET + bool "High physical base address for the RealView platform" + depends on !MACH_REALVIEW_PB1176 + default y + help + RealView boards other than PB1176 have the RAM available at + 0x70000000, 256MB of which being mirrored at 0x00000000. If + the board supports 512MB of RAM, this option allows the + memory to be accessed contiguously at the high physical + offset. + endmenu diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index d2ae077431dd..7bea8ffc4b59 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -6,5 +6,6 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o +obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-realview/Makefile.boot b/arch/arm/mach-realview/Makefile.boot index c7e75acfe6c9..d97e003d3df4 100644 --- a/arch/arm/mach-realview/Makefile.boot +++ b/arch/arm/mach-realview/Makefile.boot @@ -1,4 +1,9 @@ +ifeq ($(CONFIG_REALVIEW_HIGH_PHYS_OFFSET),y) + zreladdr-y := 0x70008000 +params_phys-y := 0x70000100 +initrd_phys-y := 0x70800000 +else zreladdr-y := 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 - +endif diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c index 3347c4236a60..a7043115de72 100644 --- a/arch/arm/mach-realview/clock.c +++ b/arch/arm/mach-realview/clock.c @@ -10,9 +10,11 @@ */ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/device.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> +#include <linux/string.h> #include <linux/clk.h> #include <linux/mutex.h> @@ -20,32 +22,6 @@ #include "clock.h" -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); - int clk_enable(struct clk *clk) { return 0; @@ -65,7 +41,9 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - return rate; + struct icst307_vco vco; + vco = icst307_khz_to_vco(clk->params, rate / 1000); + return icst307_khz(clk->params, vco) * 1000; } EXPORT_SYMBOL(clk_round_rate); @@ -78,57 +56,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) vco = icst307_khz_to_vco(clk->params, rate / 1000); clk->rate = icst307_khz(clk->params, vco) * 1000; - - printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", - clk->name, vco.s, vco.r, vco.v); - clk->setvco(clk, vco); ret = 0; } return ret; } EXPORT_SYMBOL(clk_set_rate); - -/* - * These are fixed clocks. - */ -static struct clk kmi_clk = { - .name = "KMIREFCLK", - .rate = 24000000, -}; - -static struct clk uart_clk = { - .name = "UARTCLK", - .rate = 24000000, -}; - -static struct clk mmci_clk = { - .name = "MCLK", - .rate = 24000000, -}; - -int clk_register(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init(void) -{ - clk_register(&kmi_clk); - clk_register(&uart_clk); - clk_register(&mmci_clk); - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-realview/clock.h b/arch/arm/mach-realview/clock.h index dadba695e181..ebbb0f06b600 100644 --- a/arch/arm/mach-realview/clock.h +++ b/arch/arm/mach-realview/clock.h @@ -12,14 +12,8 @@ struct module; struct icst307_params; struct clk { - struct list_head node; unsigned long rate; - struct module *owner; - const char *name; const struct icst307_params *params; void *data; void (*setvco)(struct clk *, struct icst307_vco vco); }; - -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 2f04d54711e7..5f1d55963ced 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -28,11 +28,14 @@ #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/io.h> +#include <linux/smc911x.h> +#include <asm/clkdev.h> #include <asm/system.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/leds.h> +#include <asm/mach-types.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/icst307.h> @@ -49,7 +52,7 @@ #define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) -/* used by entry-macro.S */ +/* used by entry-macro.S and platsmp.c */ void __iomem *gic_cpu_base_addr; /* @@ -124,6 +127,29 @@ int realview_flash_register(struct resource *res, u32 num) return platform_device_register(&realview_flash_device); } +static struct smc911x_platdata realview_smc911x_platdata = { + .flags = SMC911X_USE_32BIT, + .irq_flags = IRQF_SHARED, + .irq_polarity = 1, +}; + +static struct platform_device realview_eth_device = { + .name = "smc911x", + .id = 0, + .num_resources = 2, +}; + +int realview_eth_register(const char *name, struct resource *res) +{ + if (name) + realview_eth_device.name = name; + realview_eth_device.resource = res; + if (strcmp(realview_eth_device.name, "smc911x") == 0) + realview_eth_device.dev.platform_data = &realview_smc911x_platdata; + + return platform_device_register(&realview_eth_device); +} + static struct resource realview_i2c_resource = { .start = REALVIEW_I2C_BASE, .end = REALVIEW_I2C_BASE + SZ_4K - 1, @@ -177,9 +203,14 @@ static const struct icst307_params realview_oscvco_params = { static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco) { void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET; - void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; + void __iomem *sys_osc; u32 val; + if (machine_is_realview_pb1176()) + sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET; + else + sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; + val = readl(sys_osc) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); @@ -188,13 +219,60 @@ static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco) writel(0, sys_lock); } -struct clk realview_clcd_clk = { - .name = "CLCDCLK", +static struct clk oscvco_clk = { .params = &realview_oscvco_params, .setvco = realview_oscvco_set, }; /* + * These are fixed clocks. + */ +static struct clk ref24_clk = { + .rate = 24000000, +}; + +static struct clk_lookup lookups[] = { + { /* UART0 */ + .dev_id = "dev:f1", + .clk = &ref24_clk, + }, { /* UART1 */ + .dev_id = "dev:f2", + .clk = &ref24_clk, + }, { /* UART2 */ + .dev_id = "dev:f3", + .clk = &ref24_clk, + }, { /* UART3 */ + .dev_id = "fpga:09", + .clk = &ref24_clk, + }, { /* KMI0 */ + .dev_id = "fpga:06", + .clk = &ref24_clk, + }, { /* KMI1 */ + .dev_id = "fpga:07", + .clk = &ref24_clk, + }, { /* MMC0 */ + .dev_id = "fpga:05", + .clk = &ref24_clk, + }, { /* EB:CLCD */ + .dev_id = "dev:20", + .clk = &oscvco_clk, + }, { /* PB:CLCD */ + .dev_id = "issp:20", + .clk = &oscvco_clk, + } +}; + +static int __init clk_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + return 0; +} +arch_initcall(clk_init); + +/* * CLCD support. */ #define SYS_CLCD_NLCDIOON (1 << 2) @@ -226,7 +304,30 @@ static struct clcd_panel vga = { .width = -1, .height = -1, .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +static struct clcd_panel xvga = { + .mode = { + .name = "XVGA", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = 15748, + .left_margin = 152, + .right_margin = 48, + .upper_margin = 23, + .lower_margin = 3, + .hsync_len = 104, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), .bpp = 16, }; @@ -249,7 +350,7 @@ static struct clcd_panel sanyo_3_8_in = { .width = -1, .height = -1, .tim2 = TIM2_BCD, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), .bpp = 16, }; @@ -272,7 +373,7 @@ static struct clcd_panel sanyo_2_5_in = { .width = -1, .height = -1, .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), .bpp = 16, }; @@ -295,7 +396,7 @@ static struct clcd_panel epson_2_2_in = { .width = -1, .height = -1, .tim2 = TIM2_BCD | TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), .bpp = 16, }; @@ -308,9 +409,15 @@ static struct clcd_panel epson_2_2_in = { static struct clcd_panel *realview_clcd_panel(void) { void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; - struct clcd_panel *panel = &vga; + struct clcd_panel *vga_panel; + struct clcd_panel *panel; u32 val; + if (machine_is_realview_eb()) + vga_panel = &vga; + else + vga_panel = &xvga; + val = readl(sys_clcd) & SYS_CLCD_ID_MASK; if (val == SYS_CLCD_ID_SANYO_3_8) panel = &sanyo_3_8_in; @@ -319,11 +426,11 @@ static struct clcd_panel *realview_clcd_panel(void) else if (val == SYS_CLCD_ID_EPSON_2_2) panel = &epson_2_2_in; else if (val == SYS_CLCD_ID_VGA) - panel = &vga; + panel = vga_panel; else { printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); - panel = &vga; + panel = vga_panel; } return panel; @@ -358,12 +465,18 @@ static void realview_clcd_enable(struct clcd_fb *fb) writel(val, sys_clcd); } -static unsigned long framesize = SZ_1M; - static int realview_clcd_setup(struct clcd_fb *fb) { + unsigned long framesize; dma_addr_t dma; + if (machine_is_realview_eb()) + /* VGA, 16bpp */ + framesize = 640 * 480 * 2; + else + /* XVGA, 16bpp */ + framesize = 1024 * 768 * 2; + fb->panel = realview_clcd_panel(); fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, @@ -588,7 +701,7 @@ void __init realview_timer_init(unsigned int timer_irq) * The dummy clock device has to be registered before the main device * so that the latter will broadcast the clock events */ - local_timer_setup(smp_processor_id()); + local_timer_setup(); #endif /* diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 3cea92c70d8f..63be2abdc19c 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -48,12 +48,10 @@ extern struct platform_device realview_flash_device; extern struct platform_device realview_i2c_device; extern struct mmc_platform_data realview_mmc0_plat_data; extern struct mmc_platform_data realview_mmc1_plat_data; -extern struct clk realview_clcd_clk; extern struct clcd_board clcd_plat_data; extern void __iomem *gic_cpu_base_addr; #ifdef CONFIG_LOCAL_TIMERS -extern void __iomem *twd_base_addr; -extern unsigned int twd_size; +extern void __iomem *twd_base; #endif extern void __iomem *timer0_va_base; extern void __iomem *timer1_va_base; @@ -63,5 +61,6 @@ extern void __iomem *timer3_va_base; extern void realview_leds_event(led_event_t ledevt); extern void realview_timer_init(unsigned int timer_irq); extern int realview_flash_register(struct resource *res, u32 num); +extern int realview_eth_register(const char *name, struct resource *res); #endif diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index 09748cbcd10e..be048e3e8799 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c @@ -13,6 +13,8 @@ #include <linux/smp.h> #include <linux/completion.h> +#include <asm/cacheflush.h> + extern volatile int pen_release; static DECLARE_COMPLETION(cpu_killed); @@ -21,7 +23,8 @@ static inline void cpu_enter_lowpower(void) { unsigned int v; - asm volatile( "mcr p15, 0, %1, c7, c14, 0\n" + flush_cache_all(); + asm volatile( " mcr p15, 0, %1, c7, c5, 0\n" " mcr p15, 0, %1, c7, c10, 4\n" /* diff --git a/arch/arm/mach-realview/include/mach/board-eb.h b/arch/arm/mach-realview/include/mach/board-eb.h index 8d699fd324d0..268d7701fa9b 100644 --- a/arch/arm/mach-realview/include/mach/board-eb.h +++ b/arch/arm/mach-realview/include/mach/board-eb.h @@ -49,16 +49,14 @@ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB #define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_EB11MP_TWD_BASE 0x10100700 -#define REALVIEW_EB11MP_TWD_SIZE 0x00000100 +#define REALVIEW_EB11MP_TWD_BASE 0x10100600 #define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ #define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ #else #define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */ #define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_EB11MP_TWD_BASE 0x1F000700 -#define REALVIEW_EB11MP_TWD_SIZE 0x00000100 +#define REALVIEW_EB11MP_TWD_BASE 0x1F000600 #define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ #define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ @@ -163,7 +161,7 @@ #define NR_IRQS NR_IRQS_EB #endif -#if defined(CONFIG_REALVIEW_EB_ARM11MP) \ +#if defined(CONFIG_REALVIEW_EB_ARM11MP) || defined(CONFIG_REALVIEW_EB_A9MP) \ && (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP)) #undef MAX_GIC_NR #define MAX_GIC_NR NR_GIC_EB11MP @@ -177,6 +175,7 @@ #define REALVIEW_EB_PROC_ARM9 0x02000000 #define REALVIEW_EB_PROC_ARM11 0x04000000 #define REALVIEW_EB_PROC_ARM11MP 0x06000000 +#define REALVIEW_EB_PROC_A9MP 0x0C000000 #define check_eb_proc(proc_type) \ ((readl(__io_address(REALVIEW_SYS_PROCID)) & REALVIEW_EB_PROC_MASK) \ @@ -188,4 +187,13 @@ #define core_tile_eb11mp() 0 #endif +#ifdef CONFIG_REALVIEW_EB_A9MP +#define core_tile_a9mp() check_eb_proc(REALVIEW_EB_PROC_A9MP) +#else +#define core_tile_a9mp() 0 +#endif + +#define machine_is_realview_eb_mp() \ + (machine_is_realview_eb() && (core_tile_eb11mp() || core_tile_a9mp())) + #endif /* __ASM_ARCH_BOARD_EB_H */ diff --git a/arch/arm/mach-realview/include/mach/board-pb11mp.h b/arch/arm/mach-realview/include/mach/board-pb11mp.h index ecd80e58631e..53ea0e7a1267 100644 --- a/arch/arm/mach-realview/include/mach/board-pb11mp.h +++ b/arch/arm/mach-realview/include/mach/board-pb11mp.h @@ -77,8 +77,7 @@ */ #define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */ #define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */ -#define REALVIEW_TC11MP_TWD_BASE 0x1F000700 -#define REALVIEW_TC11MP_TWD_SIZE 0x00000100 +#define REALVIEW_TC11MP_TWD_BASE 0x1F000600 #define REALVIEW_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */ #define REALVIEW_TC11MP_L220_BASE 0x1F002000 /* L220 registers */ diff --git a/arch/arm/mach-realview/include/mach/board-pba8.h b/arch/arm/mach-realview/include/mach/board-pba8.h new file mode 100644 index 000000000000..c8bed8f58bab --- /dev/null +++ b/arch/arm/mach-realview/include/mach/board-pba8.h @@ -0,0 +1,152 @@ +/* + * include/asm-arm/arch-realview/board-pba8.h + * + * Copyright (C) 2008 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_BOARD_PBA8_H +#define __ASM_ARCH_BOARD_PBA8_H + +#include <mach/platform.h> + +/* + * Peripheral addresses + */ +#define REALVIEW_PBA8_UART0_BASE 0x10009000 /* UART 0 */ +#define REALVIEW_PBA8_UART1_BASE 0x1000A000 /* UART 1 */ +#define REALVIEW_PBA8_UART2_BASE 0x1000B000 /* UART 2 */ +#define REALVIEW_PBA8_UART3_BASE 0x1000C000 /* UART 3 */ +#define REALVIEW_PBA8_SSP_BASE 0x1000D000 /* Synchronous Serial Port */ +#define REALVIEW_PBA8_WATCHDOG0_BASE 0x1000F000 /* Watchdog 0 */ +#define REALVIEW_PBA8_WATCHDOG_BASE 0x10010000 /* watchdog interface */ +#define REALVIEW_PBA8_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */ +#define REALVIEW_PBA8_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */ +#define REALVIEW_PBA8_GPIO0_BASE 0x10013000 /* GPIO port 0 */ +#define REALVIEW_PBA8_RTC_BASE 0x10017000 /* Real Time Clock */ +#define REALVIEW_PBA8_TIMER4_5_BASE 0x10018000 /* Timer 4/5 */ +#define REALVIEW_PBA8_TIMER6_7_BASE 0x10019000 /* Timer 6/7 */ +#define REALVIEW_PBA8_SCTL_BASE 0x1001A000 /* System Controller */ +#define REALVIEW_PBA8_CLCD_BASE 0x10020000 /* CLCD */ +#define REALVIEW_PBA8_ONB_SRAM_BASE 0x10060000 /* On-board SRAM */ +#define REALVIEW_PBA8_DMC_BASE 0x100E0000 /* DMC configuration */ +#define REALVIEW_PBA8_SMC_BASE 0x100E1000 /* SMC configuration */ +#define REALVIEW_PBA8_CAN_BASE 0x100E2000 /* CAN bus */ +#define REALVIEW_PBA8_CF_BASE 0x18000000 /* Compact flash */ +#define REALVIEW_PBA8_CF_MEM_BASE 0x18003000 /* SMC for Compact flash */ +#define REALVIEW_PBA8_GIC_CPU_BASE 0x1E000000 /* Generic interrupt controller CPU interface */ +#define REALVIEW_PBA8_FLASH0_BASE 0x40000000 +#define REALVIEW_PBA8_FLASH0_SIZE SZ_64M +#define REALVIEW_PBA8_FLASH1_BASE 0x44000000 +#define REALVIEW_PBA8_FLASH1_SIZE SZ_64M +#define REALVIEW_PBA8_ETH_BASE 0x4E000000 /* Ethernet */ +#define REALVIEW_PBA8_USB_BASE 0x4F000000 /* USB */ +#define REALVIEW_PBA8_GIC_DIST_BASE 0x1E001000 /* Generic interrupt controller distributor */ +#define REALVIEW_PBA8_LT_BASE 0xC0000000 /* Logic Tile expansion */ +#define REALVIEW_PBA8_SDRAM6_BASE 0x70000000 /* SDRAM bank 6 256MB */ +#define REALVIEW_PBA8_SDRAM7_BASE 0x80000000 /* SDRAM bank 7 256MB */ + +#define REALVIEW_PBA8_SYS_PLD_CTRL1 0x74 + +/* + * PBA8 PCI regions + */ +#define REALVIEW_PBA8_PCI_BASE 0x90040000 /* PCI-X Unit base */ +#define REALVIEW_PBA8_PCI_IO_BASE 0x90050000 /* IO Region on AHB */ +#define REALVIEW_PBA8_PCI_MEM_BASE 0xA0000000 /* MEM Region on AHB */ + +#define REALVIEW_PBA8_PCI_BASE_SIZE 0x10000 /* 16 Kb */ +#define REALVIEW_PBA8_PCI_IO_SIZE 0x1000 /* 4 Kb */ +#define REALVIEW_PBA8_PCI_MEM_SIZE 0x20000000 /* 512 MB */ + +/* + * Irqs + */ +#define IRQ_PBA8_GIC_START 32 + +/* L220 +#define IRQ_PBA8_L220_EVENT (IRQ_PBA8_GIC_START + 29) +#define IRQ_PBA8_L220_SLAVE (IRQ_PBA8_GIC_START + 30) +#define IRQ_PBA8_L220_DECODE (IRQ_PBA8_GIC_START + 31) +*/ + +/* + * PB-A8 on-board gic irq sources + */ +#define IRQ_PBA8_WATCHDOG (IRQ_PBA8_GIC_START + 0) /* Watchdog timer */ +#define IRQ_PBA8_SOFT (IRQ_PBA8_GIC_START + 1) /* Software interrupt */ +#define IRQ_PBA8_COMMRx (IRQ_PBA8_GIC_START + 2) /* Debug Comm Rx interrupt */ +#define IRQ_PBA8_COMMTx (IRQ_PBA8_GIC_START + 3) /* Debug Comm Tx interrupt */ +#define IRQ_PBA8_TIMER0_1 (IRQ_PBA8_GIC_START + 4) /* Timer 0/1 (default timer) */ +#define IRQ_PBA8_TIMER2_3 (IRQ_PBA8_GIC_START + 5) /* Timer 2/3 */ +#define IRQ_PBA8_GPIO0 (IRQ_PBA8_GIC_START + 6) /* GPIO 0 */ +#define IRQ_PBA8_GPIO1 (IRQ_PBA8_GIC_START + 7) /* GPIO 1 */ +#define IRQ_PBA8_GPIO2 (IRQ_PBA8_GIC_START + 8) /* GPIO 2 */ + /* 9 reserved */ +#define IRQ_PBA8_RTC (IRQ_PBA8_GIC_START + 10) /* Real Time Clock */ +#define IRQ_PBA8_SSP (IRQ_PBA8_GIC_START + 11) /* Synchronous Serial Port */ +#define IRQ_PBA8_UART0 (IRQ_PBA8_GIC_START + 12) /* UART 0 on development chip */ +#define IRQ_PBA8_UART1 (IRQ_PBA8_GIC_START + 13) /* UART 1 on development chip */ +#define IRQ_PBA8_UART2 (IRQ_PBA8_GIC_START + 14) /* UART 2 on development chip */ +#define IRQ_PBA8_UART3 (IRQ_PBA8_GIC_START + 15) /* UART 3 on development chip */ +#define IRQ_PBA8_SCI (IRQ_PBA8_GIC_START + 16) /* Smart Card Interface */ +#define IRQ_PBA8_MMCI0A (IRQ_PBA8_GIC_START + 17) /* Multimedia Card 0A */ +#define IRQ_PBA8_MMCI0B (IRQ_PBA8_GIC_START + 18) /* Multimedia Card 0B */ +#define IRQ_PBA8_AACI (IRQ_PBA8_GIC_START + 19) /* Audio Codec */ +#define IRQ_PBA8_KMI0 (IRQ_PBA8_GIC_START + 20) /* Keyboard/Mouse port 0 */ +#define IRQ_PBA8_KMI1 (IRQ_PBA8_GIC_START + 21) /* Keyboard/Mouse port 1 */ +#define IRQ_PBA8_CHARLCD (IRQ_PBA8_GIC_START + 22) /* Character LCD */ +#define IRQ_PBA8_CLCD (IRQ_PBA8_GIC_START + 23) /* CLCD controller */ +#define IRQ_PBA8_DMAC (IRQ_PBA8_GIC_START + 24) /* DMA controller */ +#define IRQ_PBA8_PWRFAIL (IRQ_PBA8_GIC_START + 25) /* Power failure */ +#define IRQ_PBA8_PISMO (IRQ_PBA8_GIC_START + 26) /* PISMO interface */ +#define IRQ_PBA8_DoC (IRQ_PBA8_GIC_START + 27) /* Disk on Chip memory controller */ +#define IRQ_PBA8_ETH (IRQ_PBA8_GIC_START + 28) /* Ethernet controller */ +#define IRQ_PBA8_USB (IRQ_PBA8_GIC_START + 29) /* USB controller */ +#define IRQ_PBA8_TSPEN (IRQ_PBA8_GIC_START + 30) /* Touchscreen pen */ +#define IRQ_PBA8_TSKPAD (IRQ_PBA8_GIC_START + 31) /* Touchscreen keypad */ + +/* ... */ +#define IRQ_PBA8_PCI0 (IRQ_PBA8_GIC_START + 50) +#define IRQ_PBA8_PCI1 (IRQ_PBA8_GIC_START + 51) +#define IRQ_PBA8_PCI2 (IRQ_PBA8_GIC_START + 52) +#define IRQ_PBA8_PCI3 (IRQ_PBA8_GIC_START + 53) + +#define IRQ_PBA8_SMC -1 +#define IRQ_PBA8_SCTL -1 + +#define NR_GIC_PBA8 1 + +/* + * Only define NR_IRQS if less than NR_IRQS_PBA8 + */ +#define NR_IRQS_PBA8 (IRQ_PBA8_GIC_START + 64) + +#if defined(CONFIG_MACH_REALVIEW_PBA8) + +#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PBA8) +#undef NR_IRQS +#define NR_IRQS NR_IRQS_PBA8 +#endif + +#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PBA8) +#undef MAX_GIC_NR +#define MAX_GIC_NR NR_GIC_PBA8 +#endif + +#endif /* CONFIG_MACH_REALVIEW_PBA8 */ + +#endif /* __ASM_ARCH_BOARD_PBA8_H */ diff --git a/arch/arm/mach-realview/include/mach/clkdev.h b/arch/arm/mach-realview/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-realview/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S index 7196bcadff0c..92dbcb9e1792 100644 --- a/arch/arm/mach-realview/include/mach/debug-macro.S +++ b/arch/arm/mach-realview/include/mach/debug-macro.S @@ -8,15 +8,36 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * -*/ + */ + +#if defined(CONFIG_MACH_REALVIEW_EB) || \ + defined(CONFIG_MACH_REALVIEW_PB11MP) || \ + defined(CONFIG_MACH_REALVIEW_PBA8) +#ifndef DEBUG_LL_UART_OFFSET +#define DEBUG_LL_UART_OFFSET 0x00009000 +#elif DEBUG_LL_UART_OFFSET != 0x00009000 +#warning "DEBUG_LL_UART_OFFSET already defined to a different value" +#endif +#endif + +#ifdef CONFIG_MACH_REALVIEW_PB1176 +#ifndef DEBUG_LL_UART_OFFSET +#define DEBUG_LL_UART_OFFSET 0x0010c000 +#elif DEBUG_LL_UART_OFFSET != 0x0010c000 +#warning "DEBUG_LL_UART_OFFSET already defined to a different value" +#endif +#endif + +#ifndef DEBUG_LL_UART_OFFSET +#error "Unknown RealView platform" +#endif .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? moveq \rx, #0x10000000 - movne \rx, #0xf0000000 @ virtual base - orr \rx, \rx, #0x00009000 + movne \rx, #0xfb000000 @ virtual base + orr \rx, \rx, #DEBUG_LL_UART_OFFSET .endm #include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-realview/include/mach/dma.h b/arch/arm/mach-realview/include/mach/dma.h deleted file mode 100644 index f1a5a1a10952..000000000000 --- a/arch/arm/mach-realview/include/mach/dma.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * arch/arm/mach-realview/include/mach/dma.h - * - * Copyright (C) 2003 ARM Limited. - * Copyright (C) 1997,1998 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/arch/arm/mach-realview/include/mach/hardware.h b/arch/arm/mach-realview/include/mach/hardware.h index 79a93b3dfca9..b42c14f89acb 100644 --- a/arch/arm/mach-realview/include/mach/hardware.h +++ b/arch/arm/mach-realview/include/mach/hardware.h @@ -25,7 +25,14 @@ #include <asm/sizes.h> /* macro to get at IO space when running virtually */ -#define IO_ADDRESS(x) (((x) & 0x0fffffff) + 0xf0000000) +/* + * Statically mapped addresses: + * + * 10xx xxxx -> fbxx xxxx + * 1exx xxxx -> fdxx xxxx + * 1fxx xxxx -> fexx xxxx + */ +#define IO_ADDRESS(x) (((x) & 0x03ffffff) + 0xfb000000) #define __io_address(n) __io(IO_ADDRESS(n)) #endif diff --git a/arch/arm/mach-realview/include/mach/io.h b/arch/arm/mach-realview/include/mach/io.h index aa069424d310..f05bcdf605d8 100644 --- a/arch/arm/mach-realview/include/mach/io.h +++ b/arch/arm/mach-realview/include/mach/io.h @@ -22,12 +22,7 @@ #define IO_SPACE_LIMIT 0xffffffff -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} - -#define __io(a) __io(a) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-realview/include/mach/irqs.h b/arch/arm/mach-realview/include/mach/irqs.h index 02a918529db3..fe5cb987aa21 100644 --- a/arch/arm/mach-realview/include/mach/irqs.h +++ b/arch/arm/mach-realview/include/mach/irqs.h @@ -25,6 +25,7 @@ #include <mach/board-eb.h> #include <mach/board-pb11mp.h> #include <mach/board-pb1176.h> +#include <mach/board-pba8.h> #define IRQ_LOCALTIMER 29 #define IRQ_LOCALWDOG 30 diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h index 0e673483a141..293c30025e7e 100644 --- a/arch/arm/mach-realview/include/mach/memory.h +++ b/arch/arm/mach-realview/include/mach/memory.h @@ -23,16 +23,10 @@ /* * Physical DRAM offset. */ +#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET +#define PHYS_OFFSET UL(0x70000000) +#else #define PHYS_OFFSET UL(0x00000000) - -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) ((x) - PAGE_OFFSET) -#define __bus_to_virt(x) ((x) + PAGE_OFFSET) +#endif #endif diff --git a/arch/arm/mach-realview/include/mach/uncompress.h b/arch/arm/mach-realview/include/mach/uncompress.h index 79f50f218e77..415d634d52ab 100644 --- a/arch/arm/mach-realview/include/mach/uncompress.h +++ b/arch/arm/mach-realview/include/mach/uncompress.h @@ -23,6 +23,7 @@ #include <mach/board-eb.h> #include <mach/board-pb11mp.h> #include <mach/board-pb1176.h> +#include <mach/board-pba8.h> #define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) #define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c)) @@ -40,6 +41,8 @@ static inline unsigned long get_uart_base(void) return REALVIEW_PB11MP_UART0_BASE; else if (machine_is_realview_pb1176()) return REALVIEW_PB1176_UART0_BASE; + else if (machine_is_realview_pba8()) + return REALVIEW_PBA8_UART0_BASE; else return 0; } diff --git a/arch/arm/mach-realview/include/mach/vmalloc.h b/arch/arm/mach-realview/include/mach/vmalloc.h index 48cbcc873db2..fe0de1b507ac 100644 --- a/arch/arm/mach-realview/include/mach/vmalloc.h +++ b/arch/arm/mach-realview/include/mach/vmalloc.h @@ -18,4 +18,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x18000000) +#define VMALLOC_END 0xf8000000 diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c index 44d178cd5733..9019ef2e5611 100644 --- a/arch/arm/mach-realview/localtimer.c +++ b/arch/arm/mach-realview/localtimer.c @@ -38,18 +38,14 @@ void local_timer_interrupt(void) #ifdef CONFIG_LOCAL_TIMERS -#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size) - /* set up by the platform code */ -void __iomem *twd_base_addr; -unsigned int twd_size; +void __iomem *twd_base; static unsigned long mpcore_timer_rate; static void local_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { - void __iomem *base = TWD_BASE(smp_processor_id()); unsigned long ctrl; switch(mode) { @@ -68,17 +64,16 @@ static void local_timer_set_mode(enum clock_event_mode mode, ctrl = 0; } - __raw_writel(ctrl, base + TWD_TIMER_CONTROL); + __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); } static int local_timer_set_next_event(unsigned long evt, struct clock_event_device *unused) { - void __iomem *base = TWD_BASE(smp_processor_id()); - unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL); + unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); - __raw_writel(evt, base + TWD_TIMER_COUNTER); - __raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL); + __raw_writel(evt, twd_base + TWD_TIMER_COUNTER); + __raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, twd_base + TWD_TIMER_CONTROL); return 0; } @@ -91,19 +86,16 @@ static int local_timer_set_next_event(unsigned long evt, */ int local_timer_ack(void) { - void __iomem *base = TWD_BASE(smp_processor_id()); - - if (__raw_readl(base + TWD_TIMER_INTSTAT)) { - __raw_writel(1, base + TWD_TIMER_INTSTAT); + if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { + __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); return 1; } return 0; } -static void __cpuinit twd_calibrate_rate(unsigned int cpu) +static void __cpuinit twd_calibrate_rate(void) { - void __iomem *base = TWD_BASE(cpu); unsigned long load, count; u64 waitjiffies; @@ -124,15 +116,15 @@ static void __cpuinit twd_calibrate_rate(unsigned int cpu) waitjiffies += 5; /* enable, no interrupt or reload */ - __raw_writel(0x1, base + TWD_TIMER_CONTROL); + __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL); /* maximum value */ - __raw_writel(0xFFFFFFFFU, base + TWD_TIMER_COUNTER); + __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); while (get_jiffies_64() < waitjiffies) udelay(10); - count = __raw_readl(base + TWD_TIMER_COUNTER); + count = __raw_readl(twd_base + TWD_TIMER_COUNTER); mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); @@ -142,18 +134,19 @@ static void __cpuinit twd_calibrate_rate(unsigned int cpu) load = mpcore_timer_rate / HZ; - __raw_writel(load, base + TWD_TIMER_LOAD); + __raw_writel(load, twd_base + TWD_TIMER_LOAD); } /* * Setup the local clock events for a CPU. */ -void __cpuinit local_timer_setup(unsigned int cpu) +void __cpuinit local_timer_setup(void) { + unsigned int cpu = smp_processor_id(); struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); unsigned long flags; - twd_calibrate_rate(cpu); + twd_calibrate_rate(); clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; @@ -178,9 +171,9 @@ void __cpuinit local_timer_setup(unsigned int cpu) /* * take a local timer down */ -void __cpuexit local_timer_stop(unsigned int cpu) +void __cpuexit local_timer_stop(void) { - __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); + __raw_writel(0, twd_base + TWD_TIMER_CONTROL); } #else /* CONFIG_LOCAL_TIMERS */ @@ -190,8 +183,9 @@ static void dummy_timer_set_mode(enum clock_event_mode mode, { } -void __cpuinit local_timer_setup(unsigned int cpu) +void __cpuinit local_timer_setup(void) { + unsigned int cpu = smp_processor_id(); struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); clk->name = "dummy_timer"; diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index e102aeb0f76e..8fce85f33033 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -23,6 +23,8 @@ #include <mach/board-pb11mp.h> #include <mach/scu.h> +#include "core.h" + extern void realview_secondary_startup(void); /* @@ -31,15 +33,20 @@ extern void realview_secondary_startup(void); */ volatile int __cpuinitdata pen_release = -1; +static void __iomem *scu_base_addr(void) +{ + if (machine_is_realview_eb_mp()) + return __io_address(REALVIEW_EB11MP_SCU_BASE); + else if (machine_is_realview_pb11mp()) + return __io_address(REALVIEW_TC11MP_SCU_BASE); + else + return (void __iomem *)0; +} + static unsigned int __init get_core_count(void) { unsigned int ncores; - void __iomem *scu_base = 0; - - if (machine_is_realview_eb() && core_tile_eb11mp()) - scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE); - else if (machine_is_realview_pb11mp()) - scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE); + void __iomem *scu_base = scu_base_addr(); if (scu_base) { ncores = __raw_readl(scu_base + SCU_CONFIG); @@ -56,14 +63,7 @@ static unsigned int __init get_core_count(void) static void scu_enable(void) { u32 scu_ctrl; - void __iomem *scu_base; - - if (machine_is_realview_eb() && core_tile_eb11mp()) - scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE); - else if (machine_is_realview_pb11mp()) - scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE); - else - BUG(); + void __iomem *scu_base = scu_base_addr(); scu_ctrl = __raw_readl(scu_base + SCU_CTRL); scu_ctrl |= 1; @@ -88,10 +88,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - if (machine_is_realview_eb() && core_tile_eb11mp()) - gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE)); - else if (machine_is_realview_pb11mp()) - gic_cpu_init(0, __io_address(REALVIEW_TC11MP_GIC_CPU_BASE)); + gic_cpu_init(0, gic_cpu_base_addr); /* * let the primary processor know we're out of the @@ -232,9 +229,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in * realview_timer_init */ - if ((machine_is_realview_eb() && core_tile_eb11mp()) || - machine_is_realview_pb11mp()) - local_timer_setup(cpu); + local_timer_setup(); #endif /* diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index eb829eb1ebe2..bed39ed97613 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -108,7 +108,7 @@ static struct map_desc realview_eb11mp_io_desc[] __initdata = { static void __init realview_eb_map_io(void) { iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc)); - if (core_tile_eb11mp()) + if (core_tile_eb11mp() || core_tile_a9mp()) iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc)); } @@ -242,12 +242,6 @@ static struct resource realview_eb_eth_resources[] = { }, }; -static struct platform_device realview_eb_eth_device = { - .id = 0, - .num_resources = ARRAY_SIZE(realview_eb_eth_resources), - .resource = realview_eb_eth_resources, -}; - /* * Detect and register the correct Ethernet device. RealView/EB rev D * platforms use the newer SMSC LAN9118 Ethernet chip @@ -255,26 +249,24 @@ static struct platform_device realview_eb_eth_device = { static int eth_device_register(void) { void __iomem *eth_addr = ioremap(REALVIEW_EB_ETH_BASE, SZ_4K); + const char *name = NULL; u32 idrev; if (!eth_addr) return -ENOMEM; idrev = readl(eth_addr + 0x50); - if ((idrev & 0xFFFF0000) == 0x01180000) - /* SMSC LAN9118 chip present */ - realview_eb_eth_device.name = "smc911x"; - else - /* SMSC 91C111 chip present */ - realview_eb_eth_device.name = "smc91x"; + if ((idrev & 0xFFFF0000) != 0x01180000) + /* SMSC LAN9118 not present, use LAN91C111 instead */ + name = "smc91x"; iounmap(eth_addr); - return platform_device_register(&realview_eb_eth_device); + return realview_eth_register(name, realview_eb_eth_resources); } static void __init gic_init_irq(void) { - if (core_tile_eb11mp()) { + if (core_tile_eb11mp() || core_tile_a9mp()) { unsigned int pldctrl; /* new irq mode */ @@ -342,10 +334,9 @@ static void __init realview_eb_timer_init(void) timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE); timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20; - if (core_tile_eb11mp()) { + if (core_tile_eb11mp() || core_tile_a9mp()) { #ifdef CONFIG_LOCAL_TIMERS - twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE); - twd_size = REALVIEW_EB11MP_TWD_SIZE; + twd_base = __io_address(REALVIEW_EB11MP_TWD_BASE); #endif timer_irq = IRQ_EB11MP_TIMER0_1; } else @@ -362,7 +353,7 @@ static void __init realview_eb_init(void) { int i; - if (core_tile_eb11mp()) { + if (core_tile_eb11mp() || core_tile_a9mp()) { realview_eb11mp_fixup(); #ifdef CONFIG_CACHE_L2X0 @@ -372,8 +363,6 @@ static void __init realview_eb_init(void) #endif } - clk_register(&realview_clcd_clk); - realview_flash_register(&realview_eb_flash_resource, 1); platform_device_register(&realview_i2c_device); eth_device_register(); @@ -392,7 +381,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .phys_io = REALVIEW_EB_UART0_BASE, .io_pg_offst = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = PHYS_OFFSET + 0x00000100, .map_io = realview_eb_map_io, .init_irq = gic_init_irq, .timer = &realview_eb_timer, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index cccdb3eb90fe..8f0683c22140 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -222,13 +222,6 @@ static struct resource realview_pb1176_smsc911x_resources[] = { }, }; -static struct platform_device realview_pb1176_smsc911x_device = { - .name = "smc911x", - .id = 0, - .num_resources = ARRAY_SIZE(realview_pb1176_smsc911x_resources), - .resource = realview_pb1176_smsc911x_resources, -}; - static void __init gic_init_irq(void) { /* ARM1176 DevChip GIC, primary */ @@ -265,10 +258,8 @@ static void __init realview_pb1176_init(void) l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff); #endif - clk_register(&realview_clcd_clk); - realview_flash_register(&realview_pb1176_flash_resource, 1); - platform_device_register(&realview_pb1176_smsc911x_device); + realview_eth_register(NULL, realview_pb1176_smsc911x_resources); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; @@ -284,7 +275,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .phys_io = REALVIEW_PB1176_UART0_BASE, .io_pg_offst = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = PHYS_OFFSET + 0x00000100, .map_io = realview_pb1176_map_io, .init_irq = gic_init_irq, .timer = &realview_pb1176_timer, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 8b863148ec18..3ebdb2dadd6f 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -230,13 +230,6 @@ static struct resource realview_pb11mp_smsc911x_resources[] = { }, }; -static struct platform_device realview_pb11mp_smsc911x_device = { - .name = "smc911x", - .id = 0, - .num_resources = ARRAY_SIZE(realview_pb11mp_smsc911x_resources), - .resource = realview_pb11mp_smsc911x_resources, -}; - struct resource realview_pb11mp_cf_resources[] = { [0] = { .start = REALVIEW_PB11MP_CF_BASE, @@ -292,8 +285,7 @@ static void __init realview_pb11mp_timer_init(void) timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20; #ifdef CONFIG_LOCAL_TIMERS - twd_base_addr = __io_address(REALVIEW_TC11MP_TWD_BASE); - twd_size = REALVIEW_TC11MP_TWD_SIZE; + twd_base = __io_address(REALVIEW_TC11MP_TWD_BASE); #endif realview_timer_init(IRQ_TC11MP_TIMER0_1); } @@ -312,11 +304,9 @@ static void __init realview_pb11mp_init(void) l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); #endif - clk_register(&realview_clcd_clk); - realview_flash_register(realview_pb11mp_flash_resource, ARRAY_SIZE(realview_pb11mp_flash_resource)); - platform_device_register(&realview_pb11mp_smsc911x_device); + realview_eth_register(NULL, realview_pb11mp_smsc911x_resources); platform_device_register(&realview_i2c_device); platform_device_register(&realview_pb11mp_cf_device); @@ -334,7 +324,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .phys_io = REALVIEW_PB11MP_UART0_BASE, .io_pg_offst = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, + .boot_params = PHYS_OFFSET + 0x00000100, .map_io = realview_pb11mp_map_io, .init_irq = gic_init_irq, .timer = &realview_pb11mp_timer, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c new file mode 100644 index 000000000000..34c94435d2d8 --- /dev/null +++ b/arch/arm/mach-realview/realview_pba8.c @@ -0,0 +1,300 @@ +/* + * linux/arch/arm/mach-realview/realview_pba8.c + * + * Copyright (C) 2008 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/amba/bus.h> +#include <linux/io.h> + +#include <asm/irq.h> +#include <asm/leds.h> +#include <asm/mach-types.h> +#include <asm/hardware/gic.h> +#include <asm/hardware/icst307.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/mmc.h> +#include <asm/mach/time.h> + +#include <mach/hardware.h> +#include <mach/board-pba8.h> +#include <mach/irqs.h> + +#include "core.h" +#include "clock.h" + +static struct map_desc realview_pba8_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(REALVIEW_SYS_BASE), + .pfn = __phys_to_pfn(REALVIEW_SYS_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_PBA8_GIC_CPU_BASE), + .pfn = __phys_to_pfn(REALVIEW_PBA8_GIC_CPU_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_PBA8_GIC_DIST_BASE), + .pfn = __phys_to_pfn(REALVIEW_PBA8_GIC_DIST_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), + .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_PBA8_TIMER0_1_BASE), + .pfn = __phys_to_pfn(REALVIEW_PBA8_TIMER0_1_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_PBA8_TIMER2_3_BASE), + .pfn = __phys_to_pfn(REALVIEW_PBA8_TIMER2_3_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#ifdef CONFIG_PCI + { + .virtual = PCIX_UNIT_BASE, + .pfn = __phys_to_pfn(REALVIEW_PBA8_PCI_BASE), + .length = REALVIEW_PBA8_PCI_BASE_SIZE, + .type = MT_DEVICE + }, +#endif +#ifdef CONFIG_DEBUG_LL + { + .virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE), + .pfn = __phys_to_pfn(REALVIEW_PBA8_UART0_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#endif +}; + +static void __init realview_pba8_map_io(void) +{ + iotable_init(realview_pba8_io_desc, ARRAY_SIZE(realview_pba8_io_desc)); +} + +/* + * RealView PBA8Core AMBA devices + */ + +#define GPIO2_IRQ { IRQ_PBA8_GPIO2, NO_IRQ } +#define GPIO2_DMA { 0, 0 } +#define GPIO3_IRQ { IRQ_PBA8_GPIO3, NO_IRQ } +#define GPIO3_DMA { 0, 0 } +#define AACI_IRQ { IRQ_PBA8_AACI, NO_IRQ } +#define AACI_DMA { 0x80, 0x81 } +#define MMCI0_IRQ { IRQ_PBA8_MMCI0A, IRQ_PBA8_MMCI0B } +#define MMCI0_DMA { 0x84, 0 } +#define KMI0_IRQ { IRQ_PBA8_KMI0, NO_IRQ } +#define KMI0_DMA { 0, 0 } +#define KMI1_IRQ { IRQ_PBA8_KMI1, NO_IRQ } +#define KMI1_DMA { 0, 0 } +#define PBA8_SMC_IRQ { NO_IRQ, NO_IRQ } +#define PBA8_SMC_DMA { 0, 0 } +#define MPMC_IRQ { NO_IRQ, NO_IRQ } +#define MPMC_DMA { 0, 0 } +#define PBA8_CLCD_IRQ { IRQ_PBA8_CLCD, NO_IRQ } +#define PBA8_CLCD_DMA { 0, 0 } +#define DMAC_IRQ { IRQ_PBA8_DMAC, NO_IRQ } +#define DMAC_DMA { 0, 0 } +#define SCTL_IRQ { NO_IRQ, NO_IRQ } +#define SCTL_DMA { 0, 0 } +#define PBA8_WATCHDOG_IRQ { IRQ_PBA8_WATCHDOG, NO_IRQ } +#define PBA8_WATCHDOG_DMA { 0, 0 } +#define PBA8_GPIO0_IRQ { IRQ_PBA8_GPIO0, NO_IRQ } +#define PBA8_GPIO0_DMA { 0, 0 } +#define GPIO1_IRQ { IRQ_PBA8_GPIO1, NO_IRQ } +#define GPIO1_DMA { 0, 0 } +#define PBA8_RTC_IRQ { IRQ_PBA8_RTC, NO_IRQ } +#define PBA8_RTC_DMA { 0, 0 } +#define SCI_IRQ { IRQ_PBA8_SCI, NO_IRQ } +#define SCI_DMA { 7, 6 } +#define PBA8_UART0_IRQ { IRQ_PBA8_UART0, NO_IRQ } +#define PBA8_UART0_DMA { 15, 14 } +#define PBA8_UART1_IRQ { IRQ_PBA8_UART1, NO_IRQ } +#define PBA8_UART1_DMA { 13, 12 } +#define PBA8_UART2_IRQ { IRQ_PBA8_UART2, NO_IRQ } +#define PBA8_UART2_DMA { 11, 10 } +#define PBA8_UART3_IRQ { IRQ_PBA8_UART3, NO_IRQ } +#define PBA8_UART3_DMA { 0x86, 0x87 } +#define PBA8_SSP_IRQ { IRQ_PBA8_SSP, NO_IRQ } +#define PBA8_SSP_DMA { 9, 8 } + +/* FPGA Primecells */ +AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); +AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data); +AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL); +AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL); +AMBA_DEVICE(uart3, "fpga:09", PBA8_UART3, NULL); + +/* DevChip Primecells */ +AMBA_DEVICE(smc, "dev:00", PBA8_SMC, NULL); +AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL); +AMBA_DEVICE(wdog, "dev:e1", PBA8_WATCHDOG, NULL); +AMBA_DEVICE(gpio0, "dev:e4", PBA8_GPIO0, NULL); +AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL); +AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL); +AMBA_DEVICE(rtc, "dev:e8", PBA8_RTC, NULL); +AMBA_DEVICE(sci0, "dev:f0", SCI, NULL); +AMBA_DEVICE(uart0, "dev:f1", PBA8_UART0, NULL); +AMBA_DEVICE(uart1, "dev:f2", PBA8_UART1, NULL); +AMBA_DEVICE(uart2, "dev:f3", PBA8_UART2, NULL); +AMBA_DEVICE(ssp0, "dev:f4", PBA8_SSP, NULL); + +/* Primecells on the NEC ISSP chip */ +AMBA_DEVICE(clcd, "issp:20", PBA8_CLCD, &clcd_plat_data); +AMBA_DEVICE(dmac, "issp:30", DMAC, NULL); + +static struct amba_device *amba_devs[] __initdata = { + &dmac_device, + &uart0_device, + &uart1_device, + &uart2_device, + &uart3_device, + &smc_device, + &clcd_device, + &sctl_device, + &wdog_device, + &gpio0_device, + &gpio1_device, + &gpio2_device, + &rtc_device, + &sci0_device, + &ssp0_device, + &aaci_device, + &mmc0_device, + &kmi0_device, + &kmi1_device, +}; + +/* + * RealView PB-A8 platform devices + */ +static struct resource realview_pba8_flash_resource[] = { + [0] = { + .start = REALVIEW_PBA8_FLASH0_BASE, + .end = REALVIEW_PBA8_FLASH0_BASE + REALVIEW_PBA8_FLASH0_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = REALVIEW_PBA8_FLASH1_BASE, + .end = REALVIEW_PBA8_FLASH1_BASE + REALVIEW_PBA8_FLASH1_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource realview_pba8_smsc911x_resources[] = { + [0] = { + .start = REALVIEW_PBA8_ETH_BASE, + .end = REALVIEW_PBA8_ETH_BASE + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PBA8_ETH, + .end = IRQ_PBA8_ETH, + .flags = IORESOURCE_IRQ, + }, +}; + +struct resource realview_pba8_cf_resources[] = { + [0] = { + .start = REALVIEW_PBA8_CF_BASE, + .end = REALVIEW_PBA8_CF_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = REALVIEW_PBA8_CF_MEM_BASE, + .end = REALVIEW_PBA8_CF_MEM_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = -1, /* FIXME: Find correct irq */ + .end = -1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device realview_pba8_cf_device = { + .name = "compactflash", + .id = 0, + .num_resources = ARRAY_SIZE(realview_pba8_cf_resources), + .resource = realview_pba8_cf_resources, +}; + +static void __init gic_init_irq(void) +{ + /* ARM PB-A8 on-board GIC */ + gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START); + gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); +} + +static void __init realview_pba8_timer_init(void) +{ + timer0_va_base = __io_address(REALVIEW_PBA8_TIMER0_1_BASE); + timer1_va_base = __io_address(REALVIEW_PBA8_TIMER0_1_BASE) + 0x20; + timer2_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE); + timer3_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE) + 0x20; + + realview_timer_init(IRQ_PBA8_TIMER0_1); +} + +static struct sys_timer realview_pba8_timer = { + .init = realview_pba8_timer_init, +}; + +static void __init realview_pba8_init(void) +{ + int i; + + realview_flash_register(realview_pba8_flash_resource, + ARRAY_SIZE(realview_pba8_flash_resource)); + realview_eth_register(NULL, realview_pba8_smsc911x_resources); + platform_device_register(&realview_i2c_device); + platform_device_register(&realview_pba8_cf_device); + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } + +#ifdef CONFIG_LEDS + leds_event = realview_leds_event; +#endif +} + +MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") + /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ + .phys_io = REALVIEW_PBA8_UART0_BASE, + .io_pg_offst = (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x00000100, + .map_io = realview_pba8_map_io, + .init_irq = gic_init_irq, + .timer = &realview_pba8_timer, + .init_machine = realview_pba8_init, +MACHINE_END diff --git a/arch/arm/mach-rpc/include/mach/io.h b/arch/arm/mach-rpc/include/mach/io.h index 9f0553b7ec28..20da7f486e51 100644 --- a/arch/arm/mach-rpc/include/mach/io.h +++ b/arch/arm/mach-rpc/include/mach/io.h @@ -18,49 +18,6 @@ #define IO_SPACE_LIMIT 0xffffffff /* - * GCC is totally crap at loading/storing data. We try to persuade it - * to do the right thing by using these whereever possible instead of - * the above. - */ -#define __arch_base_getb(b,o) \ - ({ \ - unsigned int __v, __r = (b); \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2]" \ - : "=r" (__v) \ - : "r" (__r), "Ir" (o)); \ - __v; \ - }) - -#define __arch_base_getl(b,o) \ - ({ \ - unsigned int __v, __r = (b); \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (__v) \ - : "r" (__r), "Ir" (o)); \ - __v; \ - }) - -#define __arch_base_putb(v,b,o) \ - ({ \ - unsigned int __r = (b); \ - __asm__ __volatile__( \ - "strb %0, [%1, %2]" \ - : \ - : "r" (v), "r" (__r), "Ir" (o));\ - }) - -#define __arch_base_putl(v,b,o) \ - ({ \ - unsigned int __r = (b); \ - __asm__ __volatile__( \ - "str %0, [%1, %2]" \ - : \ - : "r" (v), "r" (__r), "Ir" (o));\ - }) - -/* * We use two different types of addressing - PC style addresses, and ARM * addresses. PC style accesses the PC hardware with the normal PC IO * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ @@ -232,15 +189,13 @@ DECLARE_IO(int,l,"") result; \ }) -#define __ioaddrc(port) __ioaddr(port) - #define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p)) #define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p)) #define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p)) #define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p)) #define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p)) #define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p)) -#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p)) + /* the following macro is deprecated */ #define ioaddr(port) ((unsigned long)__ioaddr((port))) diff --git a/arch/arm/mach-rpc/include/mach/irqs.h b/arch/arm/mach-rpc/include/mach/irqs.h index 4ce6ca97f669..3d2037496e38 100644 --- a/arch/arm/mach-rpc/include/mach/irqs.h +++ b/arch/arm/mach-rpc/include/mach/irqs.h @@ -44,3 +44,4 @@ #define IRQ_TIMER IRQ_TIMER0 +#define NR_IRQS 128 diff --git a/arch/arm/mach-rpc/include/mach/dma.h b/arch/arm/mach-rpc/include/mach/isa-dma.h index 360b56f8f29f..bad720548587 100644 --- a/arch/arm/mach-rpc/include/mach/dma.h +++ b/arch/arm/mach-rpc/include/mach/isa-dma.h @@ -1,5 +1,5 @@ /* - * arch/arm/mach-rpc/include/mach/dma.h + * arch/arm/mach-rpc/include/mach/isa-dma.h * * Copyright (C) 1997 Russell King * @@ -10,12 +10,6 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H -/* - * This is the maximum DMA address that can be DMAd to. - * There should not be more than (0xd0000000 - 0xc0000000) - * bytes of RAM. - */ -#define MAX_DMA_ADDRESS 0xd0000000 #define MAX_DMA_CHANNELS 8 #define DMA_0 0 diff --git a/arch/arm/mach-rpc/include/mach/memory.h b/arch/arm/mach-rpc/include/mach/memory.h index 9bf7e43e2863..78191bf25192 100644 --- a/arch/arm/mach-rpc/include/mach/memory.h +++ b/arch/arm/mach-rpc/include/mach/memory.h @@ -24,13 +24,6 @@ #define PHYS_OFFSET UL(0x10000000) /* - * These are exactly the same on the RiscPC as the - * physical memory view. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -/* * Cache flushing area - ROM */ #define FLUSH_BASE_PHYS 0x00000000 diff --git a/arch/arm/mach-s3c2400/include/mach/memory.h b/arch/arm/mach-s3c2400/include/mach/memory.h index 8f4878e4f591..cf5901ffd385 100644 --- a/arch/arm/mach-s3c2400/include/mach/memory.h +++ b/arch/arm/mach-s3c2400/include/mach/memory.h @@ -17,7 +17,4 @@ #define PHYS_OFFSET UL(0x0C000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 99fdc736698c..63a30d1dd425 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -7,6 +7,7 @@ config CPU_S3C2410 bool depends on ARCH_S3C2410 + select CPU_ARM920T select S3C2410_CLOCK select S3C2410_GPIO select CPU_LLSERIAL_S3C2410 @@ -32,11 +33,6 @@ config S3C2410_GPIO help GPIO code for S3C2410 and similar processors -config S3C2410_CLOCK - bool - help - Clock code for the S3C2410, and similar processors - config SIMTEC_NOR bool help @@ -84,6 +80,7 @@ config ARCH_BAST select PM_SIMTEC if PM select SIMTEC_NOR select MACH_BAST_IDE + select S3C24XX_DCLK select ISA help Say Y here if you are using the Simtec Electronics EB2410ITX @@ -121,6 +118,7 @@ config MACH_TCT_HAMMER config MACH_VR1000 bool "Thorcom VR1000" select PM_SIMTEC if PM + select S3C24XX_DCLK select SIMTEC_NOR select MACH_BAST_IDE select CPU_S3C2410 diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 00f31f8c4e78..fca02f82711c 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o obj-$(CONFIG_S3C2410_GPIO) += gpio.o -obj-$(CONFIG_S3C2410_CLOCK) += clock.o # Machine support diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 7d914a470b6c..552b4c778fdc 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -17,7 +17,6 @@ #include <linux/sysdev.h> #include <linux/serial_core.h> -#include <asm/dma.h> #include <mach/dma.h> #include <plat/cpu.h> @@ -25,12 +24,12 @@ #include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c/regs-ac97.h> +#include <plat/regs-ac97.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> #include <mach/regs-sdi.h> #include <asm/plat-s3c24xx/regs-iis.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = { [DMACH_XD0] = { diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 891b53cd69b8..13358ce2128c 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -16,11 +16,6 @@ #include <linux/sysdev.h> #include <mach/hardware.h> -/* - * This is the maximum DMA address(physical address) that can be DMAd to. - * - */ -#define MAX_DMA_ADDRESS 0x40000000 #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ /* We use `virtual` dma channels to hide the fact we have only a limited @@ -254,7 +249,7 @@ typedef unsigned long dma_device_t; * request a dma channel exclusivley */ -extern int s3c2410_dma_request(dmach_t channel, +extern int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *, void *dev); @@ -263,14 +258,14 @@ extern int s3c2410_dma_request(dmach_t channel, * change the state of the dma channel */ -extern int s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op); +extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op); /* s3c2410_dma_setflags * * set the channel's flags to a given state */ -extern int s3c2410_dma_setflags(dmach_t channel, +extern int s3c2410_dma_setflags(unsigned int channel, unsigned int flags); /* s3c2410_dma_free @@ -278,7 +273,7 @@ extern int s3c2410_dma_setflags(dmach_t channel, * free the dma channel (will also abort any outstanding operations) */ -extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *); +extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *); /* s3c2410_dma_enqueue * @@ -287,7 +282,7 @@ extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *); * drained before the buffer is given to the DMA system. */ -extern int s3c2410_dma_enqueue(dmach_t channel, void *id, +extern int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size); /* s3c2410_dma_config @@ -295,7 +290,7 @@ extern int s3c2410_dma_enqueue(dmach_t channel, void *id, * configure the dma channel */ -extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon); +extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon); /* s3c2410_dma_devconfig * @@ -310,11 +305,11 @@ extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, * get the position that the dma transfer is currently at */ -extern int s3c2410_dma_getposition(dmach_t channel, +extern int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dest); -extern int s3c2410_dma_set_opfn(dmach_t, s3c2410_dma_opfn_t rtn); -extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn); +extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); +extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); /* DMA Register definitions */ diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-core.h b/arch/arm/mach-s3c2410/include/mach/gpio-core.h new file mode 100644 index 000000000000..6c9fbb99ef14 --- /dev/null +++ b/arch/arm/mach-s3c2410/include/mach/gpio-core.h @@ -0,0 +1,34 @@ +/* arch/arm/mach-s3c24100/include/mach/gpio-core.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C2410 - GPIO core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_GPIO_CORE_H +#define __ASM_ARCH_GPIO_CORE_H __FILE__ + +#include <plat/gpio-core.h> +#include <mach/regs-gpio.h> + +extern struct s3c_gpio_chip s3c24xx_gpios[]; + +static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) +{ + struct s3c_gpio_chip *chip; + + if (pin > S3C2410_GPG10) + return NULL; + + chip = &s3c24xx_gpios[pin/32]; + return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL; +} + +#endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h index 3b52b86498a6..e0349af8a483 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio.h @@ -15,4 +15,10 @@ #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep +/* some boards require extra gpio capacity to support external + * devices that need GPIO. + */ + +#define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) + #include <asm-generic/gpio.h> diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h index 950c71bf1489..9565903d490b 100644 --- a/arch/arm/mach-s3c2410/include/mach/irqs.h +++ b/arch/arm/mach-s3c2410/include/mach/irqs.h @@ -134,6 +134,8 @@ #define IRQ_S3C2443_HSMMC S3C2410_IRQ(20) /* IRQ_SDI */ #define IRQ_S3C2443_NAND S3C2410_IRQ(24) /* reserved */ +#define IRQ_HSMMC0 IRQ_S3C2443_HSMMC + #define IRQ_S3C2443_LCD1 S3C2410_IRQSUB(14) #define IRQ_S3C2443_LCD2 S3C2410_IRQSUB(15) #define IRQ_S3C2443_LCD3 S3C2410_IRQSUB(16) @@ -160,6 +162,12 @@ #define NR_IRQS (IRQ_S3C2440_AC97+1) #endif +/* compatibility define. */ +#define IRQ_UART3 IRQ_S3C2443_UART3 +#define IRQ_S3CUART_RX3 IRQ_S3C2443_RX3 +#define IRQ_S3CUART_TX3 IRQ_S3C2443_TX3 +#define IRQ_S3CUART_ERR3 IRQ_S3C2443_ERR3 + /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */ #define FIQ_START IRQ_EINT0 diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h index 23c470c2e5b1..255fdfeaf957 100644 --- a/arch/arm/mach-s3c2410/include/mach/map.h +++ b/arch/arm/mach-s3c2410/include/mach/map.h @@ -13,34 +13,20 @@ #ifndef __ASM_ARCH_MAP_H #define __ASM_ARCH_MAP_H +#include <plat/map-base.h> #include <plat/map.h> #define S3C2410_ADDR(x) S3C_ADDR(x) -/* interrupt controller is the first thing we put in, to make - * the assembly code for the irq detection easier - */ -#define S3C24XX_VA_IRQ S3C_VA_IRQ -#define S3C2410_PA_IRQ (0x4A000000) -#define S3C24XX_SZ_IRQ SZ_1M - -/* memory controller registers */ -#define S3C24XX_VA_MEMCTRL S3C_VA_MEM -#define S3C2410_PA_MEMCTRL (0x48000000) -#define S3C24XX_SZ_MEMCTRL SZ_1M - /* USB host controller */ #define S3C2410_PA_USBHOST (0x49000000) -#define S3C24XX_SZ_USBHOST SZ_1M /* DMA controller */ #define S3C2410_PA_DMA (0x4B000000) #define S3C24XX_SZ_DMA SZ_1M /* Clock and Power management */ -#define S3C24XX_VA_CLKPWR S3C_VA_SYS #define S3C2410_PA_CLKPWR (0x4C000000) -#define S3C24XX_SZ_CLKPWR SZ_1M /* LCD controller */ #define S3C2410_PA_LCD (0x4D000000) @@ -48,48 +34,12 @@ /* NAND flash controller */ #define S3C2410_PA_NAND (0x4E000000) -#define S3C24XX_SZ_NAND SZ_1M - -/* UARTs */ -#define S3C24XX_VA_UART S3C_VA_UART -#define S3C2410_PA_UART (0x50000000) -#define S3C24XX_SZ_UART SZ_1M - -/* Timers */ -#define S3C24XX_VA_TIMER S3C_VA_TIMER -#define S3C2410_PA_TIMER (0x51000000) -#define S3C24XX_SZ_TIMER SZ_1M - -/* USB Device port */ -#define S3C2410_PA_USBDEV (0x52000000) -#define S3C24XX_SZ_USBDEV SZ_1M - -/* Watchdog */ -#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG -#define S3C2410_PA_WATCHDOG (0x53000000) -#define S3C24XX_SZ_WATCHDOG SZ_1M /* IIC hardware controller */ #define S3C2410_PA_IIC (0x54000000) -#define S3C24XX_SZ_IIC SZ_1M /* IIS controller */ #define S3C2410_PA_IIS (0x55000000) -#define S3C24XX_SZ_IIS SZ_1M - -/* GPIO ports */ - -/* the calculation for the VA of this must ensure that - * it is the same distance apart from the UART in the - * phsyical address space, as the initial mapping for the IO - * is done as a 1:1 maping. This puts it (currently) at - * 0xFA800000, which is not in the way of any current mapping - * by the base system. -*/ - -#define S3C2410_PA_GPIO (0x56000000) -#define S3C24XX_VA_GPIO ((S3C2410_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART) -#define S3C24XX_SZ_GPIO SZ_1M /* RTC */ #define S3C2410_PA_RTC (0x57000000) @@ -97,15 +47,12 @@ /* ADC */ #define S3C2410_PA_ADC (0x58000000) -#define S3C24XX_SZ_ADC SZ_1M /* SPI */ #define S3C2410_PA_SPI (0x59000000) -#define S3C24XX_SZ_SPI SZ_1M /* SDI */ #define S3C2410_PA_SDI (0x5A000000) -#define S3C24XX_SZ_SDI SZ_1M /* CAMIF */ #define S3C2440_PA_CAMIF (0x4F000000) @@ -120,13 +67,6 @@ #define S3C2443_PA_HSMMC (0x4A800000) #define S3C2443_SZ_HSMMC (256) -/* ISA style IO, for each machine to sort out mappings for, if it - * implements it. We reserve two 16M regions for ISA. - */ - -#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000) -#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000) - /* physical addresses of all the chip-select areas */ #define S3C2410_CS0 (0x00000000) @@ -152,27 +92,16 @@ #define S3C24XX_PA_TIMER S3C2410_PA_TIMER #define S3C24XX_PA_USBDEV S3C2410_PA_USBDEV #define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG -#define S3C24XX_PA_IIC S3C2410_PA_IIC #define S3C24XX_PA_IIS S3C2410_PA_IIS #define S3C24XX_PA_GPIO S3C2410_PA_GPIO #define S3C24XX_PA_RTC S3C2410_PA_RTC #define S3C24XX_PA_ADC S3C2410_PA_ADC #define S3C24XX_PA_SPI S3C2410_PA_SPI +#define S3C24XX_PA_SDI S3C2410_PA_SDI +#define S3C24XX_PA_NAND S3C2410_PA_NAND -/* deal with the registers that move under the 2412/2413 */ - -#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) -#ifndef __ASSEMBLY__ -extern void __iomem *s3c24xx_va_gpio2; -#endif -#ifdef CONFIG_CPU_S3C2412_ONLY -#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10) -#else -#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2 -#endif -#else -#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO -#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO -#endif +#define S3C_PA_IIC S3C2410_PA_IIC +#define S3C_PA_UART S3C24XX_PA_UART +#define S3C_PA_HSMMC0 S3C2443_PA_HSMMC #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/memory.h b/arch/arm/mach-s3c2410/include/mach/memory.h index 93782628a786..6f1e5871ae4b 100644 --- a/arch/arm/mach-s3c2410/include/mach/memory.h +++ b/arch/arm/mach-s3c2410/include/mach/memory.h @@ -13,7 +13,4 @@ #define PHYS_OFFSET UL(0x30000000) -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - #endif diff --git a/arch/arm/mach-s3c2410/include/mach/regs-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-clock.h index b3f90aa78076..2a5d90e957fb 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-clock.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-clock.h @@ -42,13 +42,6 @@ #define S3C2410_CLKCON_IIS (1<<17) #define S3C2410_CLKCON_SPI (1<<18) -#define S3C2410_PLLCON_MDIVSHIFT 12 -#define S3C2410_PLLCON_PDIVSHIFT 4 -#define S3C2410_PLLCON_SDIVSHIFT 0 -#define S3C2410_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1) -#define S3C2410_PLLCON_PDIVMASK ((1<<5)-1) -#define S3C2410_PLLCON_SDIVMASK 3 - /* DCLKCON register addresses in gpio.h */ #define S3C2410_DCLKCON_DCLK0EN (1<<0) @@ -76,32 +69,6 @@ #define S3C2410_CLKSLOW_SLOWVAL(x) (x) #define S3C2410_CLKSLOW_GET_SLOWVAL(x) ((x) & 7) -#ifndef __ASSEMBLY__ - -#include <asm/div64.h> - -static inline unsigned int -s3c2410_get_pll(unsigned int pllval, unsigned int baseclk) -{ - unsigned int mdiv, pdiv, sdiv; - uint64_t fvco; - - mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT; - pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT; - sdiv = pllval >> S3C2410_PLLCON_SDIVSHIFT; - - mdiv &= S3C2410_PLLCON_MDIVMASK; - pdiv &= S3C2410_PLLCON_PDIVMASK; - sdiv &= S3C2410_PLLCON_SDIVMASK; - - fvco = (uint64_t)baseclk * (mdiv + 8); - do_div(fvco, (pdiv + 2) << sdiv); - - return (unsigned int)fvco; -} - -#endif /* __ASSEMBLY__ */ - #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) /* extra registers */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h index 528080ceac44..321077613067 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h @@ -1053,13 +1053,6 @@ #define S3C24XX_EXTINT1 S3C24XX_GPIOREG2(0x8C) #define S3C24XX_EXTINT2 S3C24XX_GPIOREG2(0x90) -/* values for S3C2410_EXTINT0/1/2 */ -#define S3C2410_EXTINT_LOWLEV (0x00) -#define S3C2410_EXTINT_HILEV (0x01) -#define S3C2410_EXTINT_FALLEDGE (0x02) -#define S3C2410_EXTINT_RISEEDGE (0x04) -#define S3C2410_EXTINT_BOTHEDGE (0x06) - /* interrupt filtering conrrol for EINT16..EINT23 */ #define S3C2410_EINFLT0 S3C2410_GPIOREG(0x94) #define S3C2410_EINFLT1 S3C2410_GPIOREG(0x98) diff --git a/arch/arm/mach-s3c2410/include/mach/spi.h b/arch/arm/mach-s3c2410/include/mach/spi.h index 46d46f5b99f2..774f3adfe8ad 100644 --- a/arch/arm/mach-s3c2410/include/mach/spi.h +++ b/arch/arm/mach-s3c2410/include/mach/spi.h @@ -22,5 +22,12 @@ struct s3c2410_spi_info { void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol); }; +/* Standard setup / suspend routines for SPI GPIO pins. */ + +extern void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, + int enable); + +extern void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi, + int enable); #endif /* __ASM_ARCH_SPI_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h b/arch/arm/mach-s3c2410/include/mach/system-reset.h index 43535a0e7186..7613d0a384ba 100644 --- a/arch/arm/mach-s3c2410/include/mach/system-reset.h +++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h @@ -13,7 +13,7 @@ #include <mach/hardware.h> #include <linux/io.h> -#include <asm/plat-s3c/regs-watchdog.h> +#include <plat/regs-watchdog.h> #include <mach/regs-clock.h> #include <linux/clk.h> diff --git a/arch/arm/mach-s3c2410/include/mach/tick.h b/arch/arm/mach-s3c2410/include/mach/tick.h new file mode 100644 index 000000000000..544da41979db --- /dev/null +++ b/arch/arm/mach-s3c2410/include/mach/tick.h @@ -0,0 +1,15 @@ +/* linux/arch/arm/mach-s3c2410/include/mach/tick.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C2410 - timer tick support + */ + +#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) + +static inline int s3c24xx_ostimer_pending(void) +{ + return __raw_readl(S3C2410_SRCPND) & SRCPND_TIMER4; +} diff --git a/arch/arm/mach-s3c2410/include/mach/uncompress.h b/arch/arm/mach-s3c2410/include/mach/uncompress.h index ab39491beee2..c9432103750d 100644 --- a/arch/arm/mach-s3c2410/include/mach/uncompress.h +++ b/arch/arm/mach-s3c2410/include/mach/uncompress.h @@ -1,3 +1,4 @@ + /* arch/arm/mach-s3c2410/include/mach/uncompress.h * * Copyright (c) 2003, 2007 Simtec Electronics diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index d061fea01900..6d6995afeb43 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -52,6 +52,7 @@ #include <mach/regs-lcd.h> #include <mach/regs-gpio.h> +#include <plat/iic.h> #include <plat/devs.h> #include <plat/cpu.h> @@ -150,7 +151,7 @@ static struct platform_device *amlm5900_devices[] __initdata = { #endif &s3c_device_adc, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_usb, &s3c_device_rtc, &s3c_device_usbgadget, @@ -233,6 +234,7 @@ static void __init amlm5900_init(void) #ifdef CONFIG_FB_S3C2410 s3c24xx_fb_set_platdata(&amlm5900_fb_info); #endif + s3c_i2c0_set_platdata(NULL); platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 8db9c700e3c2..01bd76725b92 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -44,8 +44,8 @@ #include <mach/regs-mem.h> #include <mach/regs-lcd.h> -#include <asm/plat-s3c/nand.h> -#include <asm/plat-s3c/iic.h> +#include <plat/nand.h> +#include <plat/iic.h> #include <mach/fb.h> #include <linux/mtd/mtd.h> @@ -406,7 +406,7 @@ static struct platform_device bast_sio = { * standard 100KHz i2c bus frequency */ -static struct s3c2410_platform_i2c bast_i2c_info = { +static struct s3c2410_platform_i2c __initdata bast_i2c_info = { .flags = 0, .slave_addr = 0x10, .bus_freq = 100*1000, @@ -553,7 +553,7 @@ static struct platform_device *bast_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_rtc, &s3c_device_nand, &bast_device_dm9k, @@ -588,7 +588,8 @@ static void __init bast_map_io(void) s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); s3c_device_nand.dev.platform_data = &bast_nand_info; - s3c_device_i2c.dev.platform_data = &bast_i2c_info; + + s3c_i2c0_set_platdata(&bast_i2c_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 98716d0108e9..821a1668c3ac 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -38,11 +38,13 @@ #include <mach/h1940.h> #include <mach/h1940-latch.h> #include <mach/fb.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/udc.h> +#include <plat/iic.h> #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/pll.h> #include <plat/pm.h> static struct map_desc h1940_iodesc[] __initdata = { @@ -183,7 +185,7 @@ static struct platform_device *h1940_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_usbgadget, &s3c_device_leds, @@ -215,6 +217,7 @@ static void __init h1940_init(void) s3c24xx_fb_set_platdata(&h1940_fb_info); s3c24xx_udc_set_platdata(&h1940_udc_cfg); + s3c_i2c0_set_platdata(NULL); /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ @@ -223,10 +226,9 @@ static void __init h1940_init(void) S3C2410_MISCCR_USBSUSPND0 | S3C2410_MISCCR_USBSUSPND1, 0x0); - tmp = ( - 0x78 << S3C2410_PLLCON_MDIVSHIFT) - | (0x02 << S3C2410_PLLCON_PDIVSHIFT) - | (0x03 << S3C2410_PLLCON_SDIVSHIFT); + tmp = (0x78 << S3C24XX_PLLCON_MDIVSHIFT) + | (0x02 << S3C24XX_PLLCON_PDIVSHIFT) + | (0x03 << S3C24XX_PLLCON_SDIVSHIFT); writel(tmp, S3C2410_UPLLCON); platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 82505517846c..05a5e877b49b 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/types.h> -#include <linux/delay.h> #include <linux/gpio_keys.h> #include <linux/init.h> #include <linux/input.h> @@ -40,14 +39,14 @@ #include <asm/mach/irq.h> #include <asm/mach/map.h> -#include <asm/plat-s3c/iic.h> +#include <plat/iic.h> #include <plat/regs-serial.h> #include <plat/clock.h> #include <plat/cpu.h> #include <plat/devs.h> #include <plat/s3c2410.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/udc.h> static struct map_desc n30_iodesc[] __initdata = { /* nothing here yet */ @@ -320,7 +319,7 @@ static struct s3c2410fb_mach_info n30_fb_info __initdata = { static struct platform_device *n30_devices[] __initdata = { &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_usb, &s3c_device_usbgadget, @@ -332,7 +331,7 @@ static struct platform_device *n30_devices[] __initdata = { static struct platform_device *n35_devices[] __initdata = { &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_usbgadget, &n35_button_device, @@ -501,7 +500,7 @@ static void __init n30_init_irq(void) static void __init n30_init(void) { s3c24xx_fb_set_platdata(&n30_fb_info); - s3c_device_i2c.dev.platform_data = &n30_i2ccfg; + s3c_device_i2c0.dev.platform_data = &n30_i2ccfg; s3c24xx_udc_set_platdata(&n30_udc_cfg); /* Turn off suspend on both USB ports, and switch the diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c index d8255cf87e44..f6c7261a4a12 100644 --- a/arch/arm/mach-s3c2410/mach-otom.c +++ b/arch/arm/mach-s3c2410/mach-otom.c @@ -35,6 +35,7 @@ #include <plat/s3c2410.h> #include <plat/clock.h> #include <plat/devs.h> +#include <plat/iic.h> #include <plat/cpu.h> static struct map_desc otom11_iodesc[] __initdata = { @@ -94,7 +95,7 @@ static struct platform_device *otom11_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_rtc, &otom_device_nor, @@ -109,6 +110,7 @@ static void __init otom11_map_io(void) static void __init otom11_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(otom11_devices, ARRAY_SIZE(otom11_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c index 661807e14e8a..9678a53ceeb1 100644 --- a/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/arch/arm/mach-s3c2410/mach-qt2410.c @@ -50,10 +50,11 @@ #include <mach/leds-gpio.h> #include <plat/regs-serial.h> #include <mach/fb.h> -#include <asm/plat-s3c/nand.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/nand.h> +#include <plat/udc.h> #include <mach/spi.h> #include <mach/spi-gpio.h> +#include <plat/iic.h> #include <plat/common-smdk.h> #include <plat/devs.h> @@ -247,7 +248,7 @@ static struct platform_device *qt2410_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_sdi, &s3c_device_usbgadget, @@ -349,6 +350,7 @@ static void __init qt2410_machine_init(void) s3c2410_gpio_setpin(S3C2410_GPB0, 1); s3c24xx_udc_set_platdata(&qt2410_udc_cfg); + s3c_i2c0_set_platdata(NULL); s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT); diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 152527bb2872..c49126ccb1d5 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -47,6 +47,7 @@ #include <asm/mach-types.h> #include <plat/regs-serial.h> +#include <plat/iic.h> #include <plat/devs.h> #include <plat/cpu.h> @@ -89,7 +90,7 @@ static struct platform_device *smdk2410_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, }; @@ -102,6 +103,7 @@ static void __init smdk2410_map_io(void) static void __init smdk2410_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices)); smdk_machine_init(); } diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c index 309dcf4c870a..8fdb0430bd48 100644 --- a/arch/arm/mach-s3c2410/mach-tct_hammer.c +++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c @@ -45,6 +45,7 @@ #include <asm/mach-types.h> #include <plat/regs-serial.h> +#include <plat/iic.h> #include <plat/devs.h> #include <plat/cpu.h> @@ -127,7 +128,7 @@ static struct s3c2410_uartcfg tct_hammer_uartcfgs[] = { static struct platform_device *tct_hammer_devices[] __initdata = { &s3c_device_adc, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_usb, &s3c_device_rtc, &s3c_device_usbgadget, @@ -146,6 +147,7 @@ static void __init tct_hammer_map_io(void) static void __init tct_hammer_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(tct_hammer_devices, ARRAY_SIZE(tct_hammer_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 941353af16dc..61a1ea9c5c5c 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -47,6 +47,7 @@ #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/iic.h> #include "usb-simtec.h" #include "nor-simtec.h" @@ -334,7 +335,7 @@ static struct platform_device *vr1000_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_adc, &serial_device, &vr1000_dm9k0, @@ -384,6 +385,7 @@ static void __init vr1000_map_io(void) static void __init vr1000_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(vr1000_devices, ARRAY_SIZE(vr1000_devices)); i2c_register_board_info(0, vr1000_i2c_devs, diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index ac79b536c4c3..feb141b1f915 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -16,6 +16,7 @@ #include <linux/list.h> #include <linux/timer.h> #include <linux/init.h> +#include <linux/clk.h> #include <linux/sysdev.h> #include <linux/serial_core.h> #include <linux/platform_device.h> @@ -28,6 +29,8 @@ #include <mach/hardware.h> #include <asm/irq.h> +#include <plat/cpu-freq.h> + #include <mach/regs-clock.h> #include <plat/regs-serial.h> @@ -35,6 +38,7 @@ #include <plat/cpu.h> #include <plat/devs.h> #include <plat/clock.h> +#include <plat/pll.h> /* Initial IO mappings */ @@ -59,25 +63,28 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) * machine specific initialisation. */ -void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size) +void __init s3c2410_map_io(void) { - /* register our io-tables */ - iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); - iotable_init(mach_desc, mach_size); } -void __init s3c2410_init_clocks(int xtal) +void __init_or_cpufreq s3c2410_setup_clocks(void) { + struct clk *xtal_clk; unsigned long tmp; + unsigned long xtal; unsigned long fclk; unsigned long hclk; unsigned long pclk; + xtal_clk = clk_get(NULL, "xtal"); + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + /* now we've got our machine bits initialised, work out what * clocks we've got */ - fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); + fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); tmp = __raw_readl(S3C2410_CLKDIVN); @@ -95,7 +102,13 @@ void __init s3c2410_init_clocks(int xtal) * console to use them */ - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c24xx_setup_clocks(fclk, hclk, pclk); +} + +void __init s3c2410_init_clocks(int xtal) +{ + s3c24xx_register_baseclocks(xtal); + s3c2410_setup_clocks(); s3c2410_baseclk_add(); } diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index c59a9d2ee9a6..ca99564ae4b5 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -7,6 +7,7 @@ config CPU_S3C2412 bool depends on ARCH_S3C2410 + select CPU_ARM926T select CPU_LLSERIAL_S3C2440 select S3C2412_PM if PM select S3C2412_DMA if S3C2410_DMA diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 96d9eb15424f..a037df5e1c2d 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c @@ -93,12 +93,6 @@ static int s3c2412_upll_enable(struct clk *clk, int enable) /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "extclk", - .id = -1, -}; - static struct clk clk_erefclk = { .name = "erefclk", .id = -1, @@ -773,5 +767,6 @@ int __init s3c2412_baseclk_add(void) s3c2412_clkcon_enable(clkp, 0); } + s3c_pwmclk_init(); return 0; } diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c index ba0591e71f32..919856c9433f 100644 --- a/arch/arm/mach-s3c2412/dma.c +++ b/arch/arm/mach-s3c2412/dma.c @@ -18,7 +18,6 @@ #include <linux/serial_core.h> #include <linux/io.h> -#include <asm/dma.h> #include <mach/dma.h> #include <plat/dma.h> @@ -26,13 +25,13 @@ #include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c/regs-ac97.h> +#include <plat/regs-ac97.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> #include <mach/regs-sdi.h> #include <asm/plat-s3c24xx/regs-s3c2412-iis.h> #include <asm/plat-s3c24xx/regs-iis.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID } diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index b08f18c8c47a..ecddbbb34832 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -17,7 +17,6 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/sysdev.h> -#include <linux/delay.h> #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/i2c.h> @@ -31,8 +30,8 @@ #include <asm/mach/irq.h> #include <plat/regs-serial.h> -#include <asm/plat-s3c/nand.h> -#include <asm/plat-s3c/iic.h> +#include <plat/nand.h> +#include <plat/iic.h> #include <mach/regs-power.h> #include <mach/regs-gpio.h> @@ -52,7 +51,8 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <plat/pm.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/udc.h> +#include <plat/iic.h> static struct map_desc jive_iodesc[] __initdata = { }; @@ -398,11 +398,12 @@ static struct s3c2410_spigpio_info jive_lcd_spi = { .bus_num = 1, .pin_clk = S3C2410_GPG8, .pin_mosi = S3C2410_GPB8, + .num_chipselect = 1, .chip_select = jive_lcd_spi_chipselect, }; static struct platform_device jive_device_lcdspi = { - .name = "s3c24xx-spi-gpio", + .name = "spi_s3c24xx_gpio", .id = 1, .num_resources = 0, .dev.platform_data = &jive_lcd_spi, @@ -419,11 +420,12 @@ static struct s3c2410_spigpio_info jive_wm8750_spi = { .bus_num = 2, .pin_clk = S3C2410_GPB4, .pin_mosi = S3C2410_GPB9, + .num_chipselect = 1, .chip_select = jive_wm8750_chipselect, }; static struct platform_device jive_device_wm8750 = { - .name = "s3c24xx-spi-gpio", + .name = "spi_s3c24xx_gpio", .id = 2, .num_resources = 0, .dev.platform_data = &jive_wm8750_spi, @@ -450,14 +452,14 @@ static struct spi_board_info __initdata jive_spi_devs[] = { /* I2C bus and device configuration. */ -static struct s3c2410_platform_i2c jive_i2c_cfg = { +static struct s3c2410_platform_i2c jive_i2c_cfg __initdata = { .max_freq = 80 * 1000, .bus_freq = 50 * 1000, .flags = S3C_IICFLG_FILTER, .sda_delay = 2, }; -static struct i2c_board_info jive_i2c_devs[] = { +static struct i2c_board_info jive_i2c_devs[] __initdata = { [0] = { I2C_BOARD_INFO("lis302dl", 0x1c), .irq = IRQ_EINT14, @@ -470,7 +472,7 @@ static struct platform_device *jive_devices[] __initdata = { &s3c_device_usb, &s3c_device_rtc, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_lcd, &jive_device_lcdspi, &jive_device_wm8750, @@ -663,7 +665,7 @@ static void __init jive_machine_init(void) spi_register_board_info(jive_spi_devs, ARRAY_SIZE(jive_spi_devs)); - s3c_device_i2c.dev.platform_data = &jive_i2c_cfg; + s3c_i2c0_set_platdata(&jive_i2c_cfg); i2c_register_board_info(0, jive_i2c_devs, ARRAY_SIZE(jive_i2c_devs)); pm_power_off = jive_power_off; diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c index c719b5a740a9..eba66aa6bd20 100644 --- a/arch/arm/mach-s3c2412/mach-smdk2413.c +++ b/arch/arm/mach-s3c2412/mach-smdk2413.c @@ -37,7 +37,8 @@ #include <mach/regs-lcd.h> #include <mach/idle.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/udc.h> +#include <plat/iic.h> #include <mach/fb.h> #include <plat/s3c2410.h> @@ -105,7 +106,7 @@ static struct platform_device *smdk2413_devices[] __initdata = { &s3c_device_usb, //&s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_usbgadget, }; @@ -142,6 +143,7 @@ static void __init smdk2413_machine_init(void) s3c24xx_udc_set_platdata(&smdk2413_udc_cfg); + s3c_i2c0_set_platdata(NULL); platform_add_devices(smdk2413_devices, ARRAY_SIZE(smdk2413_devices)); smdk_machine_init(); diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c index 4cfa19ad9be0..11e8ad49fc7b 100644 --- a/arch/arm/mach-s3c2412/mach-vstms.c +++ b/arch/arm/mach-s3c2412/mach-vstms.c @@ -39,7 +39,8 @@ #include <mach/idle.h> #include <mach/fb.h> -#include <asm/plat-s3c/nand.h> +#include <plat/iic.h> +#include <plat/nand.h> #include <plat/s3c2410.h> #include <plat/s3c2412.h> @@ -122,7 +123,7 @@ static struct s3c2410_platform_nand vstms_nand_info = { static struct platform_device *vstms_devices[] __initdata = { &s3c_device_usb, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_rtc, &s3c_device_nand, @@ -151,6 +152,7 @@ static void __init vstms_map_io(void) static void __init vstms_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(vstms_devices, ARRAY_SIZE(vstms_devices)); } diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index 313759c3da69..5b5aba69ec3f 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c @@ -16,6 +16,7 @@ #include <linux/list.h> #include <linux/timer.h> #include <linux/init.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/sysdev.h> #include <linux/serial_core.h> @@ -33,13 +34,15 @@ #include <mach/reset.h> #include <mach/idle.h> +#include <plat/cpu-freq.h> + #include <mach/regs-clock.h> #include <plat/regs-serial.h> #include <mach/regs-power.h> #include <mach/regs-gpio.h> #include <mach/regs-gpioj.h> #include <mach/regs-dsc.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> #include <mach/regs-s3c2412.h> #include <plat/s3c2412.h> @@ -47,6 +50,7 @@ #include <plat/devs.h> #include <plat/clock.h> #include <plat/pm.h> +#include <plat/pll.h> #ifndef CONFIG_CPU_S3C2412_ONLY void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; @@ -136,7 +140,7 @@ static void s3c2412_hard_reset(void) * machine specific initialisation. */ -void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size) +void __init s3c2412_map_io(void) { /* move base of IO */ @@ -153,20 +157,25 @@ void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size) /* register our io-tables */ iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc)); - iotable_init(mach_desc, mach_size); } -void __init s3c2412_init_clocks(int xtal) +void __init_or_cpufreq s3c2412_setup_clocks(void) { + struct clk *xtal_clk; unsigned long tmp; + unsigned long xtal; unsigned long fclk; unsigned long hclk; unsigned long pclk; + xtal_clk = clk_get(NULL, "xtal"); + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + /* now we've got our machine bits initialised, work out what * clocks we've got */ - fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2); + fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal * 2); clk_mpll.rate = fclk; @@ -183,11 +192,17 @@ void __init s3c2412_init_clocks(int xtal) printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + s3c24xx_setup_clocks(fclk, hclk, pclk); +} + +void __init s3c2412_init_clocks(int xtal) +{ /* initialise the clocks here, to allow other things like the * console to use them */ - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c24xx_register_baseclocks(xtal); + s3c2412_setup_clocks(); s3c2412_baseclk_add(); } diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index 25de042ab996..cde5ae9a4340 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -7,6 +7,7 @@ config CPU_S3C2440 bool depends on ARCH_S3C2410 + select CPU_ARM920T select S3C2410_CLOCK select S3C2410_PM if PM select S3C2410_GPIO @@ -28,8 +29,10 @@ menu "S3C2440 Machines" config MACH_ANUBIS bool "Simtec Electronics ANUBIS" select CPU_S3C2440 + select S3C24XX_DCLK select PM_SIMTEC if PM select HAVE_PATA_PLATFORM + select S3C24XX_GPIO_EXTRA64 help Say Y here if you are using the Simtec Electronics ANUBIS development system @@ -37,7 +40,9 @@ config MACH_ANUBIS config MACH_OSIRIS bool "Simtec IM2440D20 (OSIRIS) module" select CPU_S3C2440 + select S3C24XX_DCLK select PM_SIMTEC if PM + select S3C24XX_GPIO_EXTRA128 help Say Y here if you are using the Simtec IM2440D20 module, also known as the Osiris. diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c index 32303f6a8321..5b5ee0b8f4e0 100644 --- a/arch/arm/mach-s3c2440/dma.c +++ b/arch/arm/mach-s3c2440/dma.c @@ -17,7 +17,6 @@ #include <linux/sysdev.h> #include <linux/serial_core.h> -#include <asm/dma.h> #include <mach/dma.h> #include <plat/dma.h> @@ -25,12 +24,12 @@ #include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c/regs-ac97.h> +#include <plat/regs-ac97.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> #include <mach/regs-sdi.h> #include <asm/plat-s3c24xx/regs-iis.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = { [DMACH_XD0] = { diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index e2beca470484..b05d56e230a1 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -39,7 +39,8 @@ #include <mach/regs-gpio.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> -#include <asm/plat-s3c/nand.h> +#include <plat/nand.h> +#include <plat/iic.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -366,6 +367,8 @@ static struct sm501_initdata anubis_sm501_initdata = { .mask = 0, }, + .devices = SM501_USE_GPIO, + /* set the SDRAM and bus clocks */ .mclk = 72 * MHZ, .m1xclk = 144 * MHZ, @@ -373,10 +376,12 @@ static struct sm501_initdata anubis_sm501_initdata = { static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { [0] = { + .bus_num = 1, .pin_scl = 44, .pin_sda = 45, }, [1] = { + .bus_num = 2, .pin_scl = 40, .pin_sda = 41, }, @@ -384,6 +389,7 @@ static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { static struct sm501_platdata anubis_sm501_platdata = { .init = &anubis_sm501_initdata, + .gpio_base = -1, .gpio_i2c = anubis_sm501_gpio_i2c, .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), }; @@ -404,7 +410,7 @@ static struct platform_device *anubis_devices[] __initdata = { &s3c_device_usb, &s3c_device_wdt, &s3c_device_adc, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_rtc, &s3c_device_nand, &anubis_device_ide0, @@ -468,6 +474,7 @@ static void __init anubis_map_io(void) static void __init anubis_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices)); i2c_register_board_info(0, anubis_i2c_devs, diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c index 66876c6f2f1c..0a6d0a5d961b 100644 --- a/arch/arm/mach-s3c2440/mach-at2440evb.c +++ b/arch/arm/mach-s3c2440/mach-at2440evb.c @@ -28,6 +28,7 @@ #include <asm/mach/irq.h> #include <mach/hardware.h> +#include <mach/fb.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -35,7 +36,8 @@ #include <mach/regs-gpio.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> -#include <asm/plat-s3c/nand.h> +#include <plat/nand.h> +#include <plat/iic.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -45,6 +47,7 @@ #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <asm/plat-s3c24xx/mci.h> static struct map_desc at2440evb_iodesc[] __initdata = { /* Nothing here */ @@ -162,19 +165,60 @@ static struct platform_device at2440evb_device_eth = { }, }; +static struct s3c24xx_mci_pdata at2440evb_mci_pdata = { + .gpio_detect = S3C2410_GPG10, +}; + +/* 7" LCD panel */ + +static struct s3c2410fb_display at2440evb_lcd_cfg __initdata = { + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + + .width = 800, + .height = 480, + + .pixclock = 33333, /* HCLK 60 MHz, divisor 2 */ + .xres = 800, + .yres = 480, + .bpp = 16, + .left_margin = 88, + .right_margin = 40, + .hsync_len = 128, + .upper_margin = 32, + .lower_margin = 11, + .vsync_len = 2, +}; + +static struct s3c2410fb_mach_info at2440evb_fb_info __initdata = { + .displays = &at2440evb_lcd_cfg, + .num_displays = 1, + .default_display = 0, +}; + static struct platform_device *at2440evb_devices[] __initdata = { &s3c_device_usb, &s3c_device_wdt, &s3c_device_adc, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_rtc, &s3c_device_nand, + &s3c_device_sdi, + &s3c_device_lcd, &at2440evb_device_eth, }; static void __init at2440evb_map_io(void) { s3c_device_nand.dev.platform_data = &at2440evb_nand_info; + s3c_device_sdi.name = "s3c2440-sdi"; + s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata; s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); s3c24xx_init_clocks(16934400); @@ -183,6 +227,9 @@ static void __init at2440evb_map_io(void) static void __init at2440evb_init(void) { + s3c24xx_fb_set_platdata(&at2440evb_fb_info); + s3c_i2c0_set_platdata(NULL); + platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices)); } diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c index a546307fd53d..7aeaa972d7f5 100644 --- a/arch/arm/mach-s3c2440/mach-nexcoder.c +++ b/arch/arm/mach-s3c2440/mach-nexcoder.c @@ -37,6 +37,7 @@ //#include <asm/debug-ll.h> #include <mach/regs-gpio.h> #include <plat/regs-serial.h> +#include <plat/iic.h> #include <plat/s3c2410.h> #include <plat/s3c2440.h> @@ -107,7 +108,7 @@ static struct platform_device *nexcoder_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_rtc, &s3c_device_camif, @@ -142,6 +143,7 @@ static void __init nexcoder_map_io(void) static void __init nexcoder_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(nexcoder_devices, ARRAY_SIZE(nexcoder_devices)); }; diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 2361d606abc5..41a00f57e5da 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -37,7 +37,8 @@ #include <mach/regs-gpio.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> -#include <asm/plat-s3c/nand.h> +#include <plat/nand.h> +#include <plat/iic.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -335,7 +336,7 @@ static struct i2c_board_info osiris_i2c_devs[] __initdata = { /* Standard Osiris devices */ static struct platform_device *osiris_devices[] __initdata = { - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_wdt, &s3c_device_nand, &osiris_pcmcia, @@ -398,6 +399,8 @@ static void __init osiris_init(void) sysdev_class_register(&osiris_pm_sysclass); sysdev_register(&osiris_pm_sysdev); + s3c_i2c0_set_platdata(NULL); + i2c_register_board_info(0, osiris_i2c_devs, ARRAY_SIZE(osiris_i2c_devs)); diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index 4d14c7cff892..12d378f84ad2 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -42,7 +42,7 @@ #include <mach/regs-lcd.h> #include <mach/h1940.h> -#include <asm/plat-s3c/nand.h> +#include <plat/nand.h> #include <mach/fb.h> #include <plat/clock.h> @@ -179,7 +179,7 @@ static struct platform_device *rx3715_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, &s3c_device_nand, }; diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c index fefeaaa4155f..db6eafbd4d90 100644 --- a/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -37,6 +37,7 @@ #include <mach/idle.h> #include <mach/fb.h> +#include <plat/iic.h> #include <plat/s3c2410.h> #include <plat/s3c2440.h> @@ -152,7 +153,7 @@ static struct platform_device *smdk2440_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, - &s3c_device_i2c, + &s3c_device_i2c0, &s3c_device_iis, }; @@ -166,6 +167,7 @@ static void __init smdk2440_map_io(void) static void __init smdk2440_machine_init(void) { s3c24xx_fb_set_platdata(&smdk2440_fb_info); + s3c_i2c0_set_platdata(NULL); platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig index 26d131a77074..b289d198020e 100644 --- a/arch/arm/mach-s3c2442/Kconfig +++ b/arch/arm/mach-s3c2442/Kconfig @@ -7,6 +7,7 @@ config CPU_S3C2442 bool depends on ARCH_S3C2410 + select CPU_ARM920T select S3C2410_CLOCK select S3C2410_GPIO select S3C2410_PM if PM diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig index 14252f573754..212141baebec 100644 --- a/arch/arm/mach-s3c2443/Kconfig +++ b/arch/arm/mach-s3c2443/Kconfig @@ -24,6 +24,7 @@ config MACH_SMDK2443 bool "SMDK2443" select CPU_S3C2443 select MACH_SMDK + select S3C_DEV_HSMMC help Say Y here if you are using an SMDK2443 diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index f854e7385e3c..2785d69c95b0 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -29,7 +29,6 @@ #include <linux/sysdev.h> #include <linux/clk.h> #include <linux/mutex.h> -#include <linux/delay.h> #include <linux/serial_core.h> #include <linux/io.h> @@ -39,6 +38,8 @@ #include <mach/regs-s3c2443-clock.h> +#include <plat/cpu-freq.h> + #include <plat/s3c2443.h> #include <plat/clock.h> #include <plat/cpu.h> @@ -145,12 +146,6 @@ static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk, /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "ext", - .id = -1, -}; - static struct clk clk_mpllref = { .name = "mpllref", .parent = &clk_xtal, @@ -165,14 +160,6 @@ static struct clk clk_mpll = { }; #endif -static struct clk clk_epllref; - -static struct clk clk_epll = { - .name = "epll", - .parent = &clk_epllref, - .id = -1, -}; - static struct clk clk_i2s_ext = { .name = "i2s-ext", .id = -1, @@ -1011,22 +998,20 @@ static struct clk *clks[] __initdata = { &clk_prediv, }; -void __init s3c2443_init_clocks(int xtal) +void __init_or_cpufreq s3c2443_setup_clocks(void) { - unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); + struct clk *xtal_clk; + unsigned long xtal; unsigned long pll; unsigned long fclk; unsigned long hclk; unsigned long pclk; - struct clk *clkp; - int ret; - int ptr; - /* s3c2443 parents h and p clocks from prediv */ - clk_h.parent = &clk_prediv; - clk_p.parent = &clk_prediv; + xtal_clk = clk_get(NULL, "xtal"); + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); pll = s3c2443_get_mpll(mpllcon, xtal); clk_msysclk.rate = pll; @@ -1036,13 +1021,29 @@ void __init s3c2443_init_clocks(int xtal) hclk /= s3c2443_get_hdiv(clkdiv0); pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c24xx_setup_clocks(fclk, hclk, pclk); printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", print_mhz(pll), print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + s3c24xx_setup_clocks(fclk, hclk, pclk); +} + +void __init s3c2443_init_clocks(int xtal) +{ + struct clk *clkp; + unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); + int ret; + int ptr; + + /* s3c2443 parents h and p clocks from prediv */ + clk_h.parent = &clk_prediv; + clk_p.parent = &clk_prediv; + + s3c24xx_register_baseclocks(xtal); + s3c2443_setup_clocks(); s3c2443_clk_initparents(); for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { @@ -1056,7 +1057,7 @@ void __init s3c2443_init_clocks(int xtal) } clk_epll.rate = s3c2443_get_epll(epllcon, xtal); - + clk_epll.parent = &clk_epllref; clk_usb_bus.parent = &clk_usb_bus_host; /* ensure usb bus clock is within correct rate of 48MHz */ @@ -1105,4 +1106,6 @@ void __init s3c2443_init_clocks(int xtal) (clkp->enable)(clkp, 0); } + + s3c_pwmclk_init(); } diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c index f73ccb25ff94..2a58a4d5aa5a 100644 --- a/arch/arm/mach-s3c2443/dma.c +++ b/arch/arm/mach-s3c2443/dma.c @@ -18,7 +18,6 @@ #include <linux/serial_core.h> #include <linux/io.h> -#include <asm/dma.h> #include <mach/dma.h> #include <plat/dma.h> @@ -26,12 +25,12 @@ #include <plat/regs-serial.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c/regs-ac97.h> +#include <plat/regs-ac97.h> #include <mach/regs-mem.h> #include <mach/regs-lcd.h> #include <mach/regs-sdi.h> #include <asm/plat-s3c24xx/regs-iis.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> #define MAP(x) { \ [0] = (x) | DMA_CH_VALID, \ diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c index a7fe65f3dcc1..039a46243105 100644 --- a/arch/arm/mach-s3c2443/mach-smdk2443.c +++ b/arch/arm/mach-s3c2443/mach-smdk2443.c @@ -37,6 +37,7 @@ #include <mach/idle.h> #include <mach/fb.h> +#include <plat/iic.h> #include <plat/s3c2410.h> #include <plat/s3c2440.h> @@ -103,8 +104,8 @@ static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = { static struct platform_device *smdk2443_devices[] __initdata = { &s3c_device_wdt, - &s3c_device_i2c, - &s3c_device_hsmmc, + &s3c_device_i2c0, + &s3c_device_hsmmc0, }; static void __init smdk2443_map_io(void) @@ -116,6 +117,7 @@ static void __init smdk2443_map_io(void) static void __init smdk2443_machine_init(void) { + s3c_i2c0_set_platdata(NULL); platform_add_devices(smdk2443_devices, ARRAY_SIZE(smdk2443_devices)); smdk_machine_init(); } diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c index bbeddf9ddcb1..ce2ec3298930 100644 --- a/arch/arm/mach-s3c2443/s3c2443.c +++ b/arch/arm/mach-s3c2443/s3c2443.c @@ -81,10 +81,9 @@ void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no) * machine specific initialisation. */ -void __init s3c2443_map_io(struct map_desc *mach_desc, int mach_size) +void __init s3c2443_map_io(void) { iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); - iotable_init(mach_desc, mach_size); } /* need to register class before we actually register the device, and diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S new file mode 100644 index 000000000000..f0ef0ab475f6 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S @@ -0,0 +1,28 @@ +/* arch/arm/mach-s3c2410/include/mach/debug-macro.S + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* pull in the relevant register and map files. */ + +#include <mach/map.h> +#include <plat/regs-serial.h> + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, = S3C24XX_PA_UART + ldrne \rx, = S3C24XX_VA_UART +#if CONFIG_DEBUG_S3C_UART != 0 + add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +/* include the reset of the code which will do the work, we're only + * compiling for a single cpu processor type so the default of s3c2440 + * will be fine with us. + */ + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s3c24a0/include/mach/irqs.h b/arch/arm/mach-s3c24a0/include/mach/irqs.h new file mode 100644 index 000000000000..ae8c0e359783 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/irqs.h @@ -0,0 +1,115 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/irqs.h + * + * Copyright (c) 2003-2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + + +#ifndef __ASM_ARCH_24A0_IRQS_H +#define __ASM_ARCH_24A0_IRQS_H __FILE__ + +#define IRQ_EINT0t2 S3C2410_IRQ(0) /* 16 */ +/* for generic entry-macro.S */ +#define IRQ_EINT0 IRQ_EINT0t2 + +#define IRQ_EINT3t6 S3C2410_IRQ(1) +#define IRQ_EINT7t10 S3C2410_IRQ(2) +#define IRQ_EINT11t14 S3C2410_IRQ(3) +#define IRQ_EINT15t18 S3C2410_IRQ(4) /* 20 */ +#define IRQ_TICK S3C2410_IRQ(5) +#define IRQ_DCTQ S3C2410_IRQ(6) +#define IRQ_MC S3C2410_IRQ(7) +#define IRQ_ME S3C2410_IRQ(8) /* 24 */ +#define IRQ_KEYPAD S3C2410_IRQ(9) +#define IRQ_TIMER0 S3C2410_IRQ(10) +#define IRQ_TIMER1 S3C2410_IRQ(11) +#define IRQ_TIMER2 S3C2410_IRQ(12) +#define IRQ_TIMER3_4 S3C2410_IRQ(13) +#define IRQ_OS_TIMER IRQ_TIMER3_4 +#define IRQ_LCD S3C2410_IRQ(14) +#define IRQ_CAM_C S3C2410_IRQ(15) +#define IRQ_WDT_BATFLT S3C2410_IRQ(16) /* 32 */ +#define IRQ_UART0 S3C2410_IRQ(17) +#define IRQ_CAM_P S3C2410_IRQ(18) +#define IRQ_MODEM S3C2410_IRQ(19) +#define IRQ_DMA S3C2410_IRQ(20) +#define IRQ_SDI S3C2410_IRQ(21) +#define IRQ_SPI0 S3C2410_IRQ(22) +#define IRQ_UART1 S3C2410_IRQ(23) +#define IRQ_AC97_NFLASH S3C2410_IRQ(24) /* 40 */ +#define IRQ_USBD S3C2410_IRQ(25) +#define IRQ_USBH S3C2410_IRQ(26) +#define IRQ_IIC S3C2410_IRQ(27) +#define IRQ_IRDA_MSTICK S3C2410_IRQ(28) /* 44 */ +#define IRQ_VLX_SPI1 S3C2410_IRQ(29) +#define IRQ_RTC S3C2410_IRQ(30) /* 46 */ +#define IRQ_ADC_PEN S3C2410_IRQ(31) + +/* interrupts generated from the external interrupts sources */ +#define IRQ_EINT00 S3C2410_IRQ(32) /* 48 */ +#define IRQ_EINT1 S3C2410_IRQ(33) +#define IRQ_EINT2 S3C2410_IRQ(34) +#define IRQ_EINT3 S3C2410_IRQ(35) +#define IRQ_EINT4 S3C2410_IRQ(36) +#define IRQ_EINT5 S3C2410_IRQ(37) +#define IRQ_EINT6 S3C2410_IRQ(38) +#define IRQ_EINT7 S3C2410_IRQ(39) +#define IRQ_EINT8 S3C2410_IRQ(40) +#define IRQ_EINT9 S3C2410_IRQ(41) +#define IRQ_EINT10 S3C2410_IRQ(42) +#define IRQ_EINT11 S3C2410_IRQ(43) +#define IRQ_EINT12 S3C2410_IRQ(44) +#define IRQ_EINT13 S3C2410_IRQ(45) +#define IRQ_EINT14 S3C2410_IRQ(46) +#define IRQ_EINT15 S3C2410_IRQ(47) +#define IRQ_EINT16 S3C2410_IRQ(48) +#define IRQ_EINT17 S3C2410_IRQ(49) +#define IRQ_EINT18 S3C2410_IRQ(50) + +/* SUB IRQS */ +#define IRQ_S3CUART_RX0 S3C2410_IRQ(51) /* 67 */ +#define IRQ_S3CUART_TX0 S3C2410_IRQ(52) +#define IRQ_S3CUART_ERR0 S3C2410_IRQ(53) + +#define IRQ_S3CUART_RX1 S3C2410_IRQ(54) +#define IRQ_S3CUART_TX1 S3C2410_IRQ(55) +#define IRQ_S3CUART_ERR1 S3C2410_IRQ(56) + +#define IRQ_S3CUART_RX2 (0x0) +#define IRQ_S3CUART_TX2 (0x0) +#define IRQ_S3CUART_ERR2 (0x0) + + +#define IRQ_IRDA S3C2410_IRQ(57) +#define IRQ_MSTICK S3C2410_IRQ(58) +#define IRQ_RESERVED0 S3C2410_IRQ(59) +#define IRQ_RESERVED1 S3C2410_IRQ(60) +#define IRQ_RESERVED2 S3C2410_IRQ(61) +#define IRQ_TIMER3 S3C2410_IRQ(62) +#define IRQ_TIMER4 S3C2410_IRQ(63) +#define IRQ_WDT S3C2410_IRQ(64) +#define IRQ_BATFLT S3C2410_IRQ(65) +#define IRQ_POST S3C2410_IRQ(66) +#define IRQ_DISP_FIFO S3C2410_IRQ(67) +#define IRQ_PENUP S3C2410_IRQ(68) +#define IRQ_PENDN S3C2410_IRQ(69) +#define IRQ_ADC S3C2410_IRQ(70) +#define IRQ_DISP_FRAME S3C2410_IRQ(71) +#define IRQ_NFLASH S3C2410_IRQ(72) +#define IRQ_AC97 S3C2410_IRQ(73) +#define IRQ_SPI1 S3C2410_IRQ(74) +#define IRQ_VLX S3C2410_IRQ(75) +#define IRQ_DMA0 S3C2410_IRQ(76) +#define IRQ_DMA1 S3C2410_IRQ(77) +#define IRQ_DMA2 S3C2410_IRQ(78) +#define IRQ_DMA3 S3C2410_IRQ(79) + +#define IRQ_TC (0x0) + +#define NR_IRQS (IRQ_DMA3+1) + +#endif /* __ASM_ARCH_24A0_IRQS_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/map.h b/arch/arm/mach-s3c24a0/include/mach/map.h new file mode 100644 index 000000000000..a01132717e34 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/map.h @@ -0,0 +1,85 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/map.h + * + * Copyright 2003,2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24A0 - Memory map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_24A0_MAP_H +#define __ASM_ARCH_24A0_MAP_H __FILE__ + +#include <plat/map-base.h> +#include <plat/map.h> + +#define S3C24A0_PA_IO_BASE (0x40000000) +#define S3C24A0_PA_CLKPWR (0x40000000) +#define S3C24A0_PA_IRQ (0x40200000) +#define S3C24A0_PA_DMA (0x40400000) +#define S3C24A0_PA_MEMCTRL (0x40C00000) +#define S3C24A0_PA_NAND (0x40C00000) +#define S3C24A0_PA_SROM (0x40C20000) +#define S3C24A0_PA_SDRAM (0x40C40000) +#define S3C24A0_PA_BUSM (0x40CE0000) +#define S3C24A0_PA_USBHOST (0x41000000) +#define S3C24A0_PA_MODEMIF (0x41180000) +#define S3C24A0_PA_IRDA (0x41800000) +#define S3C24A0_PA_TIMER (0x44000000) +#define S3C24A0_PA_WATCHDOG (0x44100000) +#define S3C24A0_PA_RTC (0x44200000) +#define S3C24A0_PA_UART (0x44400000) +#define S3C24A0_PA_UART0 (S3C24A0_PA_UART) +#define S3C24A0_PA_UART1 (S3C24A0_PA_UART + 0x4000) +#define S3C24A0_PA_SPI (0x44500000) +#define S3C24A0_PA_IIC (0x44600000) +#define S3C24A0_PA_IIS (0x44700000) +#define S3C24A0_PA_GPIO (0x44800000) +#define S3C24A0_PA_KEYIF (0x44900000) +#define S3C24A0_PA_USBDEV (0x44A00000) +#define S3C24A0_PA_AC97 (0x45000000) +#define S3C24A0_PA_ADC (0x45800000) +#define S3C24A0_PA_SDI (0x46000000) +#define S3C24A0_PA_MS (0x46100000) +#define S3C24A0_PA_LCD (0x4A000000) +#define S3C24A0_PA_VPOST (0x4A100000) + +/* physical addresses of all the chip-select areas */ + +#define S3C24A0_CS0 (0x00000000) +#define S3C24A0_CS1 (0x04000000) +#define S3C24A0_CS2 (0x08000000) +#define S3C24A0_CS3 (0x0C000000) +#define S3C24A0_CS4 (0x10000000) +#define S3C24A0_CS5 (0x40000000) + +#define S3C24A0_SDRAM_PA (S3C24A0_CS4) + +/* Use a single interface for common resources between S3C24XX cpus */ + +#define S3C24XX_PA_IRQ S3C24A0_PA_IRQ +#define S3C24XX_PA_MEMCTRL S3C24A0_PA_MEMCTRL +#define S3C24XX_PA_USBHOST S3C24A0_PA_USBHOST +#define S3C24XX_PA_DMA S3C24A0_PA_DMA +#define S3C24XX_PA_CLKPWR S3C24A0_PA_CLKPWR +#define S3C24XX_PA_LCD S3C24A0_PA_LCD +#define S3C24XX_PA_UART S3C24A0_PA_UART +#define S3C24XX_PA_TIMER S3C24A0_PA_TIMER +#define S3C24XX_PA_USBDEV S3C24A0_PA_USBDEV +#define S3C24XX_PA_WATCHDOG S3C24A0_PA_WATCHDOG +#define S3C24XX_PA_IIS S3C24A0_PA_IIS +#define S3C24XX_PA_GPIO S3C24A0_PA_GPIO +#define S3C24XX_PA_RTC S3C24A0_PA_RTC +#define S3C24XX_PA_ADC S3C24A0_PA_ADC +#define S3C24XX_PA_SPI S3C24A0_PA_SPI +#define S3C24XX_PA_SDI S3C24A0_PA_SDI +#define S3C24XX_PA_NAND S3C24A0_PA_NAND + +#define S3C_PA_UART S3C24A0_PA_UART +#define S3C_PA_IIC S3C24A0_PA_IIC + +#endif /* __ASM_ARCH_24A0_MAP_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h new file mode 100644 index 000000000000..585211ca0187 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/memory.h @@ -0,0 +1,19 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/memory.h + * from linux/include/asm-arm/arch-rpc/memory.h + * + * Copyright (C) 1996,1997,1998 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_24A0_MEMORY_H +#define __ASM_ARCH_24A0_MEMORY_H __FILE__ + +#define PHYS_OFFSET UL(0x10000000) + +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h new file mode 100644 index 000000000000..af2abd756c30 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h @@ -0,0 +1,88 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/regs-clock.h + * + * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C24A0 clock register definitions +*/ + +#ifndef __ASM_ARCH_24A0_REGS_CLOCK_H +#define __ASM_ARCH_24A0_REGS_CLOCK_H __FILE__ + +#define S3C24A0_MPLLCON S3C2410_CLKREG(0x10) +#define S3C24A0_UPLLCON S3C2410_CLKREG(0x14) +#define S3C24A0_CLKCON S3C2410_CLKREG(0x20) +#define S3C24A0_CLKSRC S3C2410_CLKREG(0x24) +#define S3C24A0_CLKDIVN S3C2410_CLKREG(0x28) + +/* CLKCON register bits */ + +#define S3C24A0_CLKCON_VLX (1<<29) +#define S3C24A0_CLKCON_VPOST (1<<28) +#define S3C24A0_CLKCON_WDT (1<<27) /* reserved */ +#define S3C24A0_CLKCON_MPEGDCTQ (1<<26) +#define S3C24A0_CLKCON_VPOSTIF (1<<25) +#define S3C24A0_CLKCON_MPEG4IF (1<<24) +#define S3C24A0_CLKCON_CAM_UPLL (1<<23) +#define S3C24A0_CLKCON_LCDC (1<<22) +#define S3C24A0_CLKCON_CAM_HCLK (1<<21) +#define S3C24A0_CLKCON_MPEG4 (1<<20) +#define S3C24A0_CLKCON_KEYPAD (1<<19) +#define S3C24A0_CLKCON_ADC (1<<18) +#define S3C24A0_CLKCON_SDI (1<<17) +#define S3C24A0_CLKCON_MS (1<<16) /* memory stick */ +#define S3C24A0_CLKCON_USBD (1<<15) +#define S3C24A0_CLKCON_GPIO (1<<14) +#define S3C24A0_CLKCON_IIS (1<<13) +#define S3C24A0_CLKCON_IIC (1<<12) +#define S3C24A0_CLKCON_SPI (1<<11) +#define S3C24A0_CLKCON_UART1 (1<<10) +#define S3C24A0_CLKCON_UART0 (1<<9) +#define S3C24A0_CLKCON_PWMT (1<<8) +#define S3C24A0_CLKCON_USBH (1<<7) +#define S3C24A0_CLKCON_AC97 (1<<6) +#define S3C24A0_CLKCON_IrDA (1<<4) +#define S3C24A0_CLKCON_IDLE (1<<2) +#define S3C24A0_CLKCON_MON (1<<1) +#define S3C24A0_CLKCON_STOP (1<<0) + +/* CLKSRC register bits */ + +#define S3C24A0_CLKSRC_OSC (1<<8) /* CLKSRC */ +#define S3C24A0_CLKSRC_UPLL (1<<7) +#define S3C24A0_CLKSRC_MPLL (1<<5) +#define S3C24A0_CLKSRC_EXT (1<<4) + +/* Use a single interface with the common code, for s3c24xx */ + +#define S3C2410_MPLLCON S3C24A0_MPLLCON +#define S3C2410_UPLLCON S3C24A0_UPLLCON +#define S3C2410_CLKCON S3C24A0_CLKCON +#define S3C2410_CLKSLOW S3C24A0_CLKSRC +#define S3C2410_CLKDIVN S3C24A0_CLKDIVN + +#define S3C2410_CLKCON_IDLE S3C24A0_CLKCON_IDLE +#define S3C2410_CLKCON_POWER S3C24A0_CLKCON_STOP +#define S3C2410_CLKCON_LCDC S3C24A0_CLKCON_LCDC +#define S3C2410_CLKCON_USBH S3C24A0_CLKCON_USBH +#define S3C2410_CLKCON_USBD S3C24A0_CLKCON_USBD +#define S3C2410_CLKCON_PWMT S3C24A0_CLKCON_PWMT +#define S3C2410_CLKCON_SDI S3C24A0_CLKCON_SDI +#define S3C2410_CLKCON_UART0 S3C24A0_CLKCON_UART0 +#define S3C2410_CLKCON_UART1 S3C24A0_CLKCON_UART1 +#define S3C2410_CLKCON_GPIO S3C24A0_CLKCON_GPIO +#define S3C2410_CLKCON_ADC S3C24A0_CLKCON_ADC +#define S3C2410_CLKCON_IIC S3C24A0_CLKCON_IIC +#define S3C2410_CLKCON_IIS S3C24A0_CLKCON_IIS +#define S3C2410_CLKCON_SPI S3C24A0_CLKCON_SPI + +#define S3C2410_CLKSLOW_UCLK_OFF S3C24A0_CLKSRC_UPLL +#define S3C2410_CLKSLOW_MPLL_OFF S3C24A0_CLKSRC_MPLL +#define S3C2410_CLKSLOW_SLOW (0xFF) +#define S3C2410_CLKSLOW_GET_SLOWVAL(x) (0x1) + +#endif /* __ASM_ARCH_24A0_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h new file mode 100644 index 000000000000..6086f6f189eb --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/regs-irq.h + * + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> + * http://www.simtec.co.uk/products/SWLINUX/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + + +#ifndef ___ASM_ARCH_24A0_REGS_IRQ_H +#define ___ASM_ARCH_24A0_REGS_IRQ_H __FILE__ + + +#define S3C2410_EINTMASK S3C2410_EINTREG(0x034) +#define S3C2410_EINTPEND S3C2410_EINTREG(0X038) + +#define S3C24XX_EINTMASK S3C24XX_EINTREG(0x034) +#define S3C24XX_EINTPEND S3C24XX_EINTREG(0X038) + +#endif /* __ASM_ARCH_24A0_REGS_IRQ_H */ + + + diff --git a/arch/arm/mach-s3c24a0/include/mach/system.h b/arch/arm/mach-s3c24a0/include/mach/system.h new file mode 100644 index 000000000000..bd1bd1957656 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/system.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/system.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24A0 - System function defines and includes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <mach/hardware.h> +#include <asm/io.h> + +#include <mach/map.h> + +static void arch_idle(void) +{ + /* currently no specific idle support. */ +} + +void (*s3c24xx_reset_hook)(void); + +#include <asm/plat-s3c24xx/system-reset.h> diff --git a/arch/arm/mach-s3c24a0/include/mach/tick.h b/arch/arm/mach-s3c24a0/include/mach/tick.h new file mode 100644 index 000000000000..9dea8ba6fb72 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/tick.h @@ -0,0 +1,15 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/tick.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C24A0 - timer tick support + */ + +#define SUBSRC_TIMER4 (1 << (IRQ_TIMER4 - IRQ_S3CUART_RX0)) + +static inline int s3c24xx_ostimer_pending(void) +{ + return __raw_readl(S3C2410_SUBSRCPND) & SUBSRC_TIMER4; +} diff --git a/arch/arm/mach-s3c24a0/include/mach/timex.h b/arch/arm/mach-s3c24a0/include/mach/timex.h new file mode 100644 index 000000000000..98573424a016 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/timex.h @@ -0,0 +1,18 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/timex.h + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 - time parameters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#define CLOCK_TICK_RATE 12000000 + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h new file mode 100644 index 000000000000..4d4fe4849589 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h @@ -0,0 +1,17 @@ +/* linux/include/asm-arm/arch-s3c24ao/vmalloc.h + * + * Copyright 2008 Simtec Electronics <linux@simtec.co.uk> + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C24A0 vmalloc definition +*/ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +#define VMALLOC_END (0xE0000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-s3c6400/Kconfig b/arch/arm/mach-s3c6400/Kconfig new file mode 100644 index 000000000000..6da82b5c09ba --- /dev/null +++ b/arch/arm/mach-s3c6400/Kconfig @@ -0,0 +1,8 @@ +# arch/arm/mach-s3c6400/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Simtec Electronics, Ben Dooks <ben@simtec.co.uk> +# +# Licensed under GPLv2 + +# Currently nothing here, this will be added later diff --git a/arch/arm/mach-s3c6400/Makefile b/arch/arm/mach-s3c6400/Makefile new file mode 100644 index 000000000000..8f397db25b87 --- /dev/null +++ b/arch/arm/mach-s3c6400/Makefile @@ -0,0 +1,15 @@ +# arch/arm/mach-s3c6400/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S3C6400 system + +obj-n += blank.o diff --git a/arch/arm/mach-s3c6400/Makefile.boot b/arch/arm/mach-s3c6400/Makefile.boot new file mode 100644 index 000000000000..ba41fdc0a586 --- /dev/null +++ b/arch/arm/mach-s3c6400/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x50008000 +params_phys-y := 0x50000100 diff --git a/arch/arm/mach-s3c6400/include/mach/debug-macro.S b/arch/arm/mach-s3c6400/include/mach/debug-macro.S new file mode 100644 index 000000000000..b18ac5266dfc --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/debug-macro.S @@ -0,0 +1,39 @@ +/* arch/arm/mach-s3c6400/include/mach/debug-macro.S + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* pull in the relevant register and map files. */ + +#include <mach/map.h> +#include <plat/regs-serial.h> + + /* note, for the boot process to work we have to keep the UART + * virtual address aligned to an 1MiB boundary for the L1 + * mapping the head code makes. We keep the UART virtual address + * aligned and add in the offset when we load the value here. + */ + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, = S3C_PA_UART + ldrne \rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff) +#if CONFIG_DEBUG_S3C_UART != 0 + add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +/* include the reset of the code which will do the work, we're only + * compiling for a single cpu processor type so the default of s3c2440 + * will be fine with us. + */ + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s3c6400/include/mach/dma.h b/arch/arm/mach-s3c6400/include/mach/dma.h new file mode 100644 index 000000000000..9771ac2cb07e --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/dma.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/dma.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - DMA support + */ + +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/entry-macro.S b/arch/arm/mach-s3c6400/include/mach/entry-macro.S new file mode 100644 index 000000000000..fbd90d2cf355 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/entry-macro.S @@ -0,0 +1,44 @@ +/* arch/arm/mach-s3c6400/include/mach/entry-macro.S + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * Low-level IRQ helper macros for the Samsung S3C64XX series + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. +*/ + +#include <asm/hardware/vic.h> +#include <mach/map.h> +#include <plat/irqs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =S3C_VA_VIC0 + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + @ check the vic0 + mov \irqnr, # S3C_IRQ_OFFSET + 31 + ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] + teq \irqstat, #0 + + @ otherwise try vic1 + addeq \tmp, \base, #(S3C_VA_VIC1 - S3C_VA_VIC0) + addeq \irqnr, \irqnr, #32 + ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] + teqeq \irqstat, #0 + + clzne \irqstat, \irqstat + subne \irqnr, \irqnr, \irqstat + .endm diff --git a/arch/arm/mach-s3c6400/include/mach/gpio-core.h b/arch/arm/mach-s3c6400/include/mach/gpio-core.h new file mode 100644 index 000000000000..d89aae68b0a5 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/gpio-core.h @@ -0,0 +1,21 @@ +/* arch/arm/mach-s3c6400/include/mach/gpio-core.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIO core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_GPIO_CORE_H +#define __ASM_ARCH_GPIO_CORE_H __FILE__ + +/* currently we just include the platform support */ +#include <plat/gpio-core.h> + +#endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/gpio.h b/arch/arm/mach-s3c6400/include/mach/gpio.h new file mode 100644 index 000000000000..e8e35e8fe731 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/gpio.h @@ -0,0 +1,96 @@ +/* arch/arm/mach-s3c6400/include/mach/gpio.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C6400 - GPIO lib support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* GPIO bank sizes */ +#define S3C64XX_GPIO_A_NR (8) +#define S3C64XX_GPIO_B_NR (7) +#define S3C64XX_GPIO_C_NR (8) +#define S3C64XX_GPIO_D_NR (5) +#define S3C64XX_GPIO_E_NR (5) +#define S3C64XX_GPIO_F_NR (16) +#define S3C64XX_GPIO_G_NR (7) +#define S3C64XX_GPIO_H_NR (10) +#define S3C64XX_GPIO_I_NR (16) +#define S3C64XX_GPIO_J_NR (12) +#define S3C64XX_GPIO_K_NR (16) +#define S3C64XX_GPIO_L_NR (15) +#define S3C64XX_GPIO_M_NR (6) +#define S3C64XX_GPIO_N_NR (16) +#define S3C64XX_GPIO_O_NR (16) +#define S3C64XX_GPIO_P_NR (15) +#define S3C64XX_GPIO_Q_NR (9) + +/* GPIO bank numbes */ + +/* CONFIG_S3C_GPIO_SPACE allows the user to select extra + * space for debugging purposes so that any accidental + * change from one gpio bank to another can be caught. +*/ + +#define S3C64XX_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) + +enum s3c_gpio_number { + S3C64XX_GPIO_A_START = 0, + S3C64XX_GPIO_B_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_A), + S3C64XX_GPIO_C_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_B), + S3C64XX_GPIO_D_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_C), + S3C64XX_GPIO_E_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_D), + S3C64XX_GPIO_F_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_E), + S3C64XX_GPIO_G_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_F), + S3C64XX_GPIO_H_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_G), + S3C64XX_GPIO_I_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_H), + S3C64XX_GPIO_J_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_I), + S3C64XX_GPIO_K_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_J), + S3C64XX_GPIO_L_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_K), + S3C64XX_GPIO_M_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_L), + S3C64XX_GPIO_N_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_M), + S3C64XX_GPIO_O_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_N), + S3C64XX_GPIO_P_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_O), + S3C64XX_GPIO_Q_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_P), +}; + +/* S3C64XX GPIO number definitions. */ + +#define S3C64XX_GPA(_nr) (S3C64XX_GPIO_A_START + (_nr)) +#define S3C64XX_GPB(_nr) (S3C64XX_GPIO_B_START + (_nr)) +#define S3C64XX_GPC(_nr) (S3C64XX_GPIO_C_START + (_nr)) +#define S3C64XX_GPD(_nr) (S3C64XX_GPIO_D_START + (_nr)) +#define S3C64XX_GPE(_nr) (S3C64XX_GPIO_E_START + (_nr)) +#define S3C64XX_GPF(_nr) (S3C64XX_GPIO_F_START + (_nr)) +#define S3C64XX_GPG(_nr) (S3C64XX_GPIO_G_START + (_nr)) +#define S3C64XX_GPH(_nr) (S3C64XX_GPIO_H_START + (_nr)) +#define S3C64XX_GPI(_nr) (S3C64XX_GPIO_I_START + (_nr)) +#define S3C64XX_GPJ(_nr) (S3C64XX_GPIO_J_START + (_nr)) +#define S3C64XX_GPK(_nr) (S3C64XX_GPIO_K_START + (_nr)) +#define S3C64XX_GPL(_nr) (S3C64XX_GPIO_L_START + (_nr)) +#define S3C64XX_GPM(_nr) (S3C64XX_GPIO_M_START + (_nr)) +#define S3C64XX_GPN(_nr) (S3C64XX_GPIO_N_START + (_nr)) +#define S3C64XX_GPO(_nr) (S3C64XX_GPIO_O_START + (_nr)) +#define S3C64XX_GPP(_nr) (S3C64XX_GPIO_P_START + (_nr)) +#define S3C64XX_GPQ(_nr) (S3C64XX_GPIO_Q_START + (_nr)) + +/* the end of the S3C64XX specific gpios */ +#define S3C64XX_GPIO_END (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1) +#define S3C_GPIO_END S3C64XX_GPIO_END + +/* define the number of gpios we need to the one after the GPQ() range */ +#define ARCH_NR_GPIOS (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1) + +#include <asm-generic/gpio.h> diff --git a/arch/arm/mach-s3c6400/include/mach/hardware.h b/arch/arm/mach-s3c6400/include/mach/hardware.h new file mode 100644 index 000000000000..862d033e57a4 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/hardware.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/hardware.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - Hardware support + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/irqs.h b/arch/arm/mach-s3c6400/include/mach/irqs.h new file mode 100644 index 000000000000..b38c47cffc28 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/irqs.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/irqs.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - IRQ definitions + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ + +#ifndef __ASM_ARM_IRQ_H +#error "Do not include this directly, instead #include <asm/irq.h>" +#endif + +#include <plat/irqs.h> + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h new file mode 100644 index 000000000000..cff27d813fc6 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -0,0 +1,68 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/map.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - Memory map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H __FILE__ + +#include <plat/map-base.h> + +/* HSMMC units */ +#define S3C64XX_PA_HSMMC(x) (0x7C200000 + ((x) * 0x100000)) +#define S3C64XX_PA_HSMMC0 S3C64XX_PA_HSMMC(0) +#define S3C64XX_PA_HSMMC1 S3C64XX_PA_HSMMC(1) +#define S3C64XX_PA_HSMMC2 S3C64XX_PA_HSMMC(2) + +#define S3C_PA_UART (0x7F005000) +#define S3C_PA_UART0 (S3C_PA_UART + 0x00) +#define S3C_PA_UART1 (S3C_PA_UART + 0x400) +#define S3C_PA_UART2 (S3C_PA_UART + 0x800) +#define S3C_PA_UART3 (S3C_PA_UART + 0xC00) +#define S3C_UART_OFFSET (0x400) + +/* See notes on UART VA mapping in debug-macro.S */ +#define S3C_VA_UARTx(x) (S3C_VA_UART + (S3C_PA_UART & 0xfffff) + ((x) * S3C_UART_OFFSET)) + +#define S3C_VA_UART0 S3C_VA_UARTx(0) +#define S3C_VA_UART1 S3C_VA_UARTx(1) +#define S3C_VA_UART2 S3C_VA_UARTx(2) +#define S3C_VA_UART3 S3C_VA_UARTx(3) + +#define S3C64XX_PA_FB (0x77100000) +#define S3C64XX_PA_SYSCON (0x7E00F000) +#define S3C64XX_PA_TIMER (0x7F006000) +#define S3C64XX_PA_IIC0 (0x7F004000) +#define S3C64XX_PA_IIC1 (0x7F00F000) + +#define S3C64XX_PA_GPIO (0x7F008000) +#define S3C64XX_VA_GPIO S3C_ADDR(0x00500000) +#define S3C64XX_SZ_GPIO SZ_4K + +#define S3C64XX_PA_SDRAM (0x50000000) +#define S3C64XX_PA_VIC0 (0x71200000) +#define S3C64XX_PA_VIC1 (0x71300000) + +/* place VICs close together */ +#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00) +#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000) + +/* compatibiltiy defines. */ +#define S3C_PA_TIMER S3C64XX_PA_TIMER +#define S3C_PA_HSMMC0 S3C64XX_PA_HSMMC0 +#define S3C_PA_HSMMC1 S3C64XX_PA_HSMMC1 +#define S3C_PA_HSMMC2 S3C64XX_PA_HSMMC2 +#define S3C_PA_IIC S3C64XX_PA_IIC0 +#define S3C_PA_IIC1 S3C64XX_PA_IIC1 +#define S3C_PA_FB S3C64XX_PA_FB + +#endif /* __ASM_ARCH_6400_MAP_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/memory.h b/arch/arm/mach-s3c6400/include/mach/memory.h new file mode 100644 index 000000000000..a3ac84a65480 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/memory.h @@ -0,0 +1,18 @@ +/* arch/arm/mach-s3c6400/include/mach/memory.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x50000000) + +#endif diff --git a/arch/arm/mach-s3c6400/include/mach/pwm-clock.h b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h new file mode 100644 index 000000000000..b25bedee0d52 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h @@ -0,0 +1,56 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64xx - pwm clock and timer support + */ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @tcfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg >= S3C64XX_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << tcfg1; +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 1; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div); +} + +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK diff --git a/arch/arm/mach-s3c6400/include/mach/regs-fb.h b/arch/arm/mach-s3c6400/include/mach/regs-fb.h new file mode 100644 index 000000000000..47019795ce06 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/regs-fb.h @@ -0,0 +1,259 @@ +/* arch/arm/mach-s3c6400/include/mach/regs-fb.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - new-style framebuffer register definitions + * + * This is the register set for the new style framebuffer interface + * found from the S3C2443 onwards and specifically the S3C64XX series + * S3C6400 and S3C6410. + * + * The file contains the cpu specific items which change between whichever + * architecture is selected. See <plat/regs-fb.h> for the core definitions + * that are the same. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* include the core definitions here, in case we really do need to + * override them at a later date. +*/ + +#include <plat/regs-fb.h> + +#define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */ +#define VIDCON1_FSTATUS_EVEN (1 << 15) + +/* Video timing controls */ +#define VIDTCON0 (0x10) +#define VIDTCON1 (0x14) +#define VIDTCON2 (0x18) + +/* Window position controls */ + +#define WINCON(_win) (0x20 + ((_win) * 4)) + +/* OSD1 and OSD4 do not have register D */ + +#define VIDOSD_A(_win) (0x40 + ((_win) * 16)) +#define VIDOSD_B(_win) (0x44 + ((_win) * 16)) +#define VIDOSD_C(_win) (0x48 + ((_win) * 16)) +#define VIDOSD_D(_win) (0x4C + ((_win) * 16)) + +/* Video buffer addresses */ + +#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) +#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) +#define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8)) +#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) +#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) + +#define VIDINTCON0 (0x130) + +#define WxKEYCONy(_win, _con) ((0x140 + ((_win) * 8)) + ((_con) * 4)) + +/* WINCONx */ + +#define WINCONx_CSCWIDTH_MASK (0x3 << 26) +#define WINCONx_CSCWIDTH_SHIFT (26) +#define WINCONx_CSCWIDTH_WIDE (0x0 << 26) +#define WINCONx_CSCWIDTH_NARROW (0x3 << 26) + +#define WINCONx_ENLOCAL (1 << 22) +#define WINCONx_BUFSTATUS (1 << 21) +#define WINCONx_BUFSEL (1 << 20) +#define WINCONx_BUFAUTOEN (1 << 19) +#define WINCONx_YCbCr (1 << 13) + +#define WINCON1_LOCALSEL_CAMIF (1 << 23) + +#define WINCON2_LOCALSEL_CAMIF (1 << 23) +#define WINCON2_BLD_PIX (1 << 6) + +#define WINCON2_ALPHA_SEL (1 << 1) +#define WINCON2_BPPMODE_MASK (0xf << 2) +#define WINCON2_BPPMODE_SHIFT (2) +#define WINCON2_BPPMODE_1BPP (0x0 << 2) +#define WINCON2_BPPMODE_2BPP (0x1 << 2) +#define WINCON2_BPPMODE_4BPP (0x2 << 2) +#define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2) +#define WINCON2_BPPMODE_16BPP_565 (0x5 << 2) +#define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2) +#define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2) +#define WINCON2_BPPMODE_18BPP_666 (0x8 << 2) +#define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2) +#define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2) +#define WINCON2_BPPMODE_24BPP_888 (0xb << 2) +#define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2) +#define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2) +#define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2) + +#define WINCON3_BLD_PIX (1 << 6) + +#define WINCON3_ALPHA_SEL (1 << 1) +#define WINCON3_BPPMODE_MASK (0xf << 2) +#define WINCON3_BPPMODE_SHIFT (2) +#define WINCON3_BPPMODE_1BPP (0x0 << 2) +#define WINCON3_BPPMODE_2BPP (0x1 << 2) +#define WINCON3_BPPMODE_4BPP (0x2 << 2) +#define WINCON3_BPPMODE_16BPP_565 (0x5 << 2) +#define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2) +#define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2) +#define WINCON3_BPPMODE_18BPP_666 (0x8 << 2) +#define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2) +#define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2) +#define WINCON3_BPPMODE_24BPP_888 (0xb << 2) +#define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2) +#define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2) +#define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2) + +#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5) +#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5) +#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5) + +#define DITHMODE (0x170) +#define WINxMAP(_win) (0x180 + ((_win) * 4)) + + +#define DITHMODE_R_POS_MASK (0x3 << 5) +#define DITHMODE_R_POS_SHIFT (5) +#define DITHMODE_R_POS_8BIT (0x0 << 5) +#define DITHMODE_R_POS_6BIT (0x1 << 5) +#define DITHMODE_R_POS_5BIT (0x2 << 5) + +#define DITHMODE_G_POS_MASK (0x3 << 3) +#define DITHMODE_G_POS_SHIFT (3) +#define DITHMODE_G_POS_8BIT (0x0 << 3) +#define DITHMODE_G_POS_6BIT (0x1 << 3) +#define DITHMODE_G_POS_5BIT (0x2 << 3) + +#define DITHMODE_B_POS_MASK (0x3 << 1) +#define DITHMODE_B_POS_SHIFT (1) +#define DITHMODE_B_POS_8BIT (0x0 << 1) +#define DITHMODE_B_POS_6BIT (0x1 << 1) +#define DITHMODE_B_POS_5BIT (0x2 << 1) + +#define DITHMODE_DITH_EN (1 << 0) + +#define WPALCON (0x1A0) + +#define WPALCON_W4PAL_16BPP_A555 (1 << 8) +#define WPALCON_W3PAL_16BPP_A555 (1 << 7) +#define WPALCON_W2PAL_16BPP_A555 (1 << 6) + +/* Palette registers */ + +#define WIN2_PAL(_entry) (0x300 + ((_entry) * 2)) +#define WIN3_PAL(_entry) (0x320 + ((_entry) * 2)) +#define WIN4_PAL(_entry) (0x340 + ((_entry) * 2)) +#define WIN0_PAL(_entry) (0x400 + ((_entry) * 4)) +#define WIN1_PAL(_entry) (0x800 + ((_entry) * 4)) + +/* system specific implementation code for palette sizes, and other + * information that changes depending on which architecture is being + * compiled. +*/ + +/* return true if window _win has OSD register D */ +#define s3c_fb_has_osd_d(_win) ((_win) != 4 && (_win) != 0) + +static inline unsigned int s3c_fb_win_pal_size(unsigned int win) +{ + if (win < 2) + return 256; + if (win < 4) + return 16; + if (win == 4) + return 4; + + BUG(); /* shouldn't get here */ +} + +static inline int s3c_fb_validate_win_bpp(unsigned int win, unsigned int bpp) +{ + /* all windows can do 1/2 bpp */ + + if ((bpp == 25 || bpp == 19) && win == 0) + return 0; /* win 0 does not have 19 or 25bpp modes */ + + if (bpp == 4 && win == 4) + return 0; + + if (bpp == 8 && (win >= 3)) + return 0; /* win 3/4 cannot do 8bpp in any mode */ + + return 1; +} + +static inline unsigned int s3c_fb_pal_reg(unsigned int window, int reg) +{ + switch (window) { + case 0: return WIN0_PAL(reg); + case 1: return WIN1_PAL(reg); + case 2: return WIN2_PAL(reg); + case 3: return WIN3_PAL(reg); + case 4: return WIN4_PAL(reg); + } + + BUG(); +} + +static inline int s3c_fb_pal_is16(unsigned int window) +{ + return window > 1; +} + +struct s3c_fb_palette { + struct fb_bitfield r; + struct fb_bitfield g; + struct fb_bitfield b; + struct fb_bitfield a; +}; + +static inline void s3c_fb_init_palette(unsigned int window, + struct s3c_fb_palette *palette) +{ + if (window < 2) { + /* Windows 0/1 are 8/8/8 or A/8/8/8 */ + palette->r.offset = 16; + palette->r.length = 8; + palette->g.offset = 8; + palette->g.length = 8; + palette->b.offset = 0; + palette->b.length = 8; + } else { + /* currently we assume RGB 5/6/5 */ + palette->r.offset = 11; + palette->r.length = 5; + palette->g.offset = 5; + palette->g.length = 6; + palette->b.offset = 0; + palette->b.length = 5; + } +} + +/* Notes on per-window bpp settings + * + * Value Win0 Win1 Win2 Win3 Win 4 + * 0000 1(P) 1(P) 1(P) 1(P) 1(P) + * 0001 2(P) 2(P) 2(P) 2(P) 2(P) + * 0010 4(P) 4(P) 4(P) 4(P) -none- + * 0011 8(P) 8(P) -none- -none- -none- + * 0100 -none- 8(A232) 8(A232) -none- -none- + * 0101 16(565) 16(565) 16(565) 16(565) 16(565) + * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555) + * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555) + * 1000 18(666) 18(666) 18(666) 18(666) 18(666) + * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665) + * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666) + * 1011 24(888) 24(888) 24(888) 24(888) 24(888) + * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887) + * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888) + * 1110 -none- -none- -none- -none- -none- + * 1111 -none- -none- -none- -none- -none- +*/ diff --git a/arch/arm/mach-s3c6400/include/mach/regs-irq.h b/arch/arm/mach-s3c6400/include/mach/regs-irq.h new file mode 100644 index 000000000000..bcce68a0bb75 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/regs-irq.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/regs-irq.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - IRQ register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_REGS_IRQ_H +#define __ASM_ARCH_REGS_IRQ_H __FILE__ + +#include <asm/hardware/vic.h> + +#endif /* __ASM_ARCH_6400_REGS_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c6400/include/mach/system.h new file mode 100644 index 000000000000..652bbc403f0b --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/system.h @@ -0,0 +1,24 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/system.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - system implementation + */ + +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H __FILE__ + +static void arch_idle(void) +{ + /* nothing here yet */ +} + +static void arch_reset(char mode) +{ + /* nothing here yet */ +} + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/tick.h b/arch/arm/mach-s3c6400/include/mach/tick.h new file mode 100644 index 000000000000..d9c0dc7014ec --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/tick.h @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/tick.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - Timer tick support definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_TICK_H +#define __ASM_ARCH_TICK_H __FILE__ + +/* note, the timer interrutps turn up in 2 places, the vic and then + * the timer block. We take the VIC as the base at the moment. + */ +static inline u32 s3c24xx_ostimer_pending(void) +{ + u32 pend = __raw_readl(S3C_VA_VIC0 + VIC_RAW_STATUS); + return pend & 1 << (IRQ_TIMER4_VIC - S3C64XX_IRQ_VIC0(0)); +} + +#define TICK_MAX (0xffffffff) + +#endif /* __ASM_ARCH_6400_TICK_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/uncompress.h b/arch/arm/mach-s3c6400/include/mach/uncompress.h new file mode 100644 index 000000000000..c6a82a20bf2a --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/uncompress.h @@ -0,0 +1,28 @@ +/* arch/arm/mach-s3c6400/include/mach/uncompress.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C6400 - uncompress code + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <mach/map.h> +#include <plat/uncompress.h> + +static void arch_detect_cpu(void) +{ + /* we do not need to do any cpu detection here at the moment. */ + fifo_mask = S3C2440_UFSTAT_TXMASK; + fifo_max = 63 << S3C2440_UFSTAT_TXSHIFT; +} + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig new file mode 100644 index 000000000000..1d5010070027 --- /dev/null +++ b/arch/arm/mach-s3c6410/Kconfig @@ -0,0 +1,62 @@ +# arch/arm/mach-s3c6410/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +# Configuration options for the S3C6410 CPU + +config CPU_S3C6410 + bool + select CPU_S3C6400_INIT + select CPU_S3C6400_CLOCK + help + Enable S3C6410 CPU support + +config S3C6410_SETUP_SDHCI + bool + help + Internal helper functions for S3C6410 based SDHCI systems + +config MACH_SMDK6410 + bool "SMDK6410" + select CPU_S3C6410 + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_I2C1 + select S3C_DEV_FB + select S3C6410_SETUP_SDHCI + select S3C64XX_SETUP_I2C1 + select S3C64XX_SETUP_FB_24BPP + help + Machine support for the Samsung SMDK6410 + +# At least some of the SMDK6410s were shipped with the card detect +# for the MMC/SD slots connected to the same input. This means that +# either the boards need to be altered to have channel0 to an alternate +# configuration or that only one slot can be used. + +choice + prompt "SMDK6410 MMC/SD slot setup" + depends on MACH_SMDK6410 + +config SMDK6410_SD_CH0 + bool "Use channel 0 only" + depends on MACH_SMDK6410 + help + Select CON7 (channel 0) as the MMC/SD slot, as + at least some SMDK6410 boards come with the + resistors fitted so that the card detects for + channels 0 and 1 are the same. + +config SMDK6410_SD_CH1 + bool "Use channel 1 only" + depends on MACH_SMDK6410 + help + Select CON6 (channel 1) as the MMC/SD slot, as + at least some SMDK6410 boards come with the + resistors fitted so that the card detects for + channels 0 and 1 are the same. + +endchoice diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile new file mode 100644 index 000000000000..2cd4f189036b --- /dev/null +++ b/arch/arm/mach-s3c6410/Makefile @@ -0,0 +1,23 @@ +# arch/arm/plat-s3c6410/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S3C6410 system + +obj-$(CONFIG_CPU_S3C6410) += cpu.o + +# Helper and device support + +obj-$(CONFIG_S3C6410_SETUP_SDHCI) += setup-sdhci.o + +# machine support + +obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c new file mode 100644 index 000000000000..6a73ca6b7a3a --- /dev/null +++ b/arch/arm/mach-s3c6410/cpu.c @@ -0,0 +1,101 @@ +/* linux/arch/arm/mach-s3c6410/cpu.c + * + * Copyright 2008 Simtec Electronics + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/sysdev.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <asm/irq.h> + +#include <plat/cpu-freq.h> +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> +#include <plat/sdhci.h> +#include <plat/iic-core.h> +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* Initial IO mappings */ + +static struct map_desc s3c6410_iodesc[] __initdata = { +}; + +/* s3c6410_map_io + * + * register the standard cpu IO areas +*/ + +void __init s3c6410_map_io(void) +{ + iotable_init(s3c6410_iodesc, ARRAY_SIZE(s3c6410_iodesc)); + + /* initialise device information early */ + s3c6410_default_sdhci0(); + s3c6410_default_sdhci1(); + + /* the i2c devices are directly compatible with s3c2440 */ + s3c_i2c0_setname("s3c2440-i2c"); + s3c_i2c1_setname("s3c2440-i2c"); +} + +void __init s3c6410_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initialising clocks\n", __func__); + s3c24xx_register_baseclocks(xtal); + s3c64xx_register_clocks(); + s3c6400_register_clocks(); + s3c6400_setup_clocks(); +} + +void __init s3c6410_init_irq(void) +{ + /* VIC0 is missing IRQ7, VIC1 is fully populated. */ + s3c64xx_init_irq(~0 & ~(1 << 7), ~0); +} + +struct sysdev_class s3c6410_sysclass = { + .name = "s3c6410-core", +}; + +static struct sys_device s3c6410_sysdev = { + .cls = &s3c6410_sysclass, +}; + +static int __init s3c6410_core_init(void) +{ + return sysdev_class_register(&s3c6410_sysclass); +} + +core_initcall(s3c6410_core_init); + +int __init s3c6410_init(void) +{ + printk("S3C6410: Initialising architecture\n"); + + return sysdev_register(&s3c6410_sysdev); +} diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c new file mode 100644 index 000000000000..3c4d47145c83 --- /dev/null +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c @@ -0,0 +1,185 @@ +/* linux/arch/arm/mach-s3c6410/mach-smdk6410.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/fb.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include <video/platform_lcd.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-fb.h> +#include <mach/map.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <plat/regs-serial.h> +#include <plat/iic.h> +#include <plat/fb.h> + +#include <plat/s3c6410.h> +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE + +static struct s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, +}; + +/* framebuffer and LCD setup. */ + +/* GPF15 = LCD backlight control + * GPF13 => Panel power + * GPN5 = LCD nRESET signal + * PWM_TOUT1 => backlight brightness + */ + +static void smdk6410_lcd_power_set(struct plat_lcd_data *pd, + unsigned int power) +{ + if (power) { + gpio_direction_output(S3C64XX_GPF(13), 1); + gpio_direction_output(S3C64XX_GPF(15), 1); + + /* fire nRESET on power up */ + gpio_direction_output(S3C64XX_GPN(5), 0); + msleep(10); + gpio_direction_output(S3C64XX_GPN(5), 1); + msleep(1); + } else { + gpio_direction_output(S3C64XX_GPF(15), 0); + gpio_direction_output(S3C64XX_GPF(13), 0); + } +} + +static struct plat_lcd_data smdk6410_lcd_power_data = { + .set_power = smdk6410_lcd_power_set, +}; + +static struct platform_device smdk6410_lcd_powerdev = { + .name = "platform-lcd", + .dev.parent = &s3c_device_fb.dev, + .dev.platform_data = &smdk6410_lcd_power_data, +}; + +static struct s3c_fb_pd_win smdk6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, +}; + +/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ +static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &smdk6410_fb_win0, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, +}; + +struct map_desc smdk6410_iodesc[] = {}; + +static struct platform_device *smdk6410_devices[] __initdata = { +#ifdef CONFIG_SMDK6410_SD_CH0 + &s3c_device_hsmmc0, +#endif +#ifdef CONFIG_SMDK6410_SD_CH1 + &s3c_device_hsmmc1, +#endif + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_fb, + &smdk6410_lcd_powerdev, +}; + +static struct i2c_board_info i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, + { I2C_BOARD_INFO("WM8580", 0X1b), }, +}; + +static struct i2c_board_info i2c_devs1[] __initdata = { + { I2C_BOARD_INFO("24c128", 0x57), }, /* Samsung S524AD0XD1 */ +}; + +static void __init smdk6410_map_io(void) +{ + s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs)); +} + +static void __init smdk6410_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + s3c_i2c1_set_platdata(NULL); + s3c_fb_set_platdata(&smdk6410_lcd_pdata); + + i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0)); + i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); + + platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); +} + +MACHINE_START(SMDK6410, "SMDK6410") + /* Maintainer: Ben Dooks <ben@fluff.org> */ + .phys_io = S3C_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C64XX_PA_SDRAM + 0x100, + + .init_irq = s3c6410_init_irq, + .map_io = smdk6410_map_io, + .init_machine = smdk6410_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s3c6410/setup-sdhci.c b/arch/arm/mach-s3c6410/setup-sdhci.c new file mode 100644 index 000000000000..0b5788bd5985 --- /dev/null +++ b/arch/arm/mach-s3c6410/setup-sdhci.c @@ -0,0 +1,102 @@ +/* linux/arch/arm/mach-s3c6410/setup-sdhci.c + * + * Copyright 2008 Simtec Electronics + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> + +#include <mach/gpio.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-sdhci.h> +#include <plat/sdhci.h> + +/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */ + +char *s3c6410_hsmmc_clksrcs[4] = { + [0] = "hsmmc", + [1] = "hsmmc", + [2] = "mmc_bus", + /* [3] = "48m", - note not succesfully used yet */ +}; + +void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) +{ + unsigned int gpio; + unsigned int end; + + end = S3C64XX_GPG(2 + width); + + /* Set all the necessary GPG pins to special-function 0 */ + for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2)); +} + +void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card) +{ + u32 ctrl2, ctrl3; + + /* don't need to alter anything acording to card-type */ + + writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4); + + ctrl2 = readl(r + S3C_SDHCI_CONTROL2); + ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; + ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR | + S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK | + S3C_SDHCI_CTRL2_ENFBCLKRX | + S3C_SDHCI_CTRL2_DFCNT_NONE | + S3C_SDHCI_CTRL2_ENCLKOUTHOLD); + + if (ios->clock < 25 * 1000000) + ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 | + S3C_SDHCI_CTRL3_FCSEL2 | + S3C_SDHCI_CTRL3_FCSEL1 | + S3C_SDHCI_CTRL3_FCSEL0); + else + ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0); + + printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3); + writel(ctrl2, r + S3C_SDHCI_CONTROL2); + writel(ctrl3, r + S3C_SDHCI_CONTROL3); +} + +void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) +{ + unsigned int gpio; + unsigned int end; + + end = S3C64XX_GPH(2 + width); + + /* Set all the necessary GPG pins to special-function 0 */ + for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3)); +} diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c index 43c30f84abf2..dab3c6347a8f 100644 --- a/arch/arm/mach-sa1100/clock.c +++ b/arch/arm/mach-sa1100/clock.c @@ -3,6 +3,7 @@ */ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/device.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> @@ -14,36 +15,39 @@ #include <mach/hardware.h> /* - * Very simple clock implementation - we only have one clock to - * deal with at the moment, so we only match using the "name". + * Very simple clock implementation - we only have one clock to deal with. */ struct clk { - struct list_head node; - unsigned long rate; - const char *name; unsigned int enabled; - void (*enable)(void); - void (*disable)(void); }; -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); +static void clk_gpio27_enable(void) +{ + /* + * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: + * (SA-1110 Developer's Manual, section 9.1.2.1) + */ + GAFR |= GPIO_32_768kHz; + GPDR |= GPIO_32_768kHz; + TUCR = TUCR_3_6864MHz; +} + +static void clk_gpio27_disable(void) +{ + TUCR = 0; + GPDR &= ~GPIO_32_768kHz; + GAFR &= ~GPIO_32_768kHz; +} + +static struct clk clk_gpio27; + static DEFINE_SPINLOCK(clocks_lock); struct clk *clk_get(struct device *dev, const char *id) { - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0) { - clk = p; - break; - } - } - mutex_unlock(&clocks_mutex); + const char *devname = dev_name(dev); - return clk; + return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27; } EXPORT_SYMBOL(clk_get); @@ -58,7 +62,7 @@ int clk_enable(struct clk *clk) spin_lock_irqsave(&clocks_lock, flags); if (clk->enabled++ == 0) - clk->enable(); + clk_gpio27_enable(); spin_unlock_irqrestore(&clocks_lock, flags); return 0; } @@ -72,63 +76,13 @@ void clk_disable(struct clk *clk) spin_lock_irqsave(&clocks_lock, flags); if (--clk->enabled == 0) - clk->disable(); + clk_gpio27_disable(); spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); unsigned long clk_get_rate(struct clk *clk) { - return clk->rate; + return 3686400; } EXPORT_SYMBOL(clk_get_rate); - - -static void clk_gpio27_enable(void) -{ - /* - * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: - * (SA-1110 Developer's Manual, section 9.1.2.1) - */ - GAFR |= GPIO_32_768kHz; - GPDR |= GPIO_32_768kHz; - TUCR = TUCR_3_6864MHz; -} - -static void clk_gpio27_disable(void) -{ - TUCR = 0; - GPDR &= ~GPIO_32_768kHz; - GAFR &= ~GPIO_32_768kHz; -} - -static struct clk clk_gpio27 = { - .name = "SA1111_CLK", - .rate = 3686400, - .enable = clk_gpio27_enable, - .disable = clk_gpio27_disable, -}; - -int clk_register(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init(void) -{ - clk_register(&clk_gpio27); - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index fe289997cfaf..2052eb88c961 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -68,23 +68,22 @@ struct platform_device colliescoop_device = { }; static struct scoop_pcmcia_dev collie_pcmcia_scoop[] = { -{ - .dev = &colliescoop_device.dev, - .irq = COLLIE_IRQ_GPIO_CF_IRQ, - .cd_irq = COLLIE_IRQ_GPIO_CF_CD, - .cd_irq_str = "PCMCIA0 CD", -}, + { + .dev = &colliescoop_device.dev, + .irq = COLLIE_IRQ_GPIO_CF_IRQ, + .cd_irq = COLLIE_IRQ_GPIO_CF_CD, + .cd_irq_str = "PCMCIA0 CD", + }, }; static struct scoop_pcmcia_config collie_pcmcia_config = { - .devs = &collie_pcmcia_scoop[0], - .num_devs = 1, + .devs = &collie_pcmcia_scoop[0], + .num_devs = 1, }; - static struct mcp_plat_data collie_mcp_data = { - .mccr0 = MCCR0_ADM | MCCR0_ExtClk, - .sclk_rate = 9216000, + .mccr0 = MCCR0_ADM | MCCR0_ExtClk, + .sclk_rate = 9216000, }; #ifdef CONFIG_SHARP_LOCOMO @@ -95,14 +94,14 @@ struct platform_device collie_locomo_device; static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl) { - if (mctrl & TIOCM_RTS) + if (mctrl & TIOCM_RTS) locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 0); - else + else locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 1); - if (mctrl & TIOCM_DTR) + if (mctrl & TIOCM_DTR) locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 0); - else + else locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 1); } diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c index b1161fc80602..b39307f26b52 100644 --- a/arch/arm/mach-sa1100/collie_pm.c +++ b/arch/arm/mach-sa1100/collie_pm.c @@ -26,7 +26,7 @@ #include <asm/irq.h> #include <mach/hardware.h> #include <asm/hardware/scoop.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/collie.h> #include <asm/mach/sharpsl_param.h> #include <asm/hardware/sharpsl_pm.h> @@ -263,24 +263,24 @@ static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev) } static struct ucb1x00_driver collie_pm_ucb_driver = { - .add = collie_pm_ucb_add, + .add = collie_pm_ucb_add, }; static struct platform_device *collie_pm_device; static int __init collie_pm_init(void) { - int ret; + int ret; - collie_pm_device = platform_device_alloc("sharpsl-pm", -1); - if (!collie_pm_device) - return -ENOMEM; + collie_pm_device = platform_device_alloc("sharpsl-pm", -1); + if (!collie_pm_device) + return -ENOMEM; - collie_pm_device->dev.platform_data = &collie_pm_machinfo; - ret = platform_device_add(collie_pm_device); + collie_pm_device->dev.platform_data = &collie_pm_machinfo; + ret = platform_device_add(collie_pm_device); - if (ret) - platform_device_put(collie_pm_device); + if (ret) + platform_device_put(collie_pm_device); if (!ret) ret = ucb1x00_register_driver(&collie_pm_ucb_driver); @@ -291,7 +291,7 @@ static int __init collie_pm_init(void) static void __exit collie_pm_exit(void) { ucb1x00_unregister_driver(&collie_pm_ucb_driver); - platform_device_unregister(collie_pm_device); + platform_device_unregister(collie_pm_device); } module_init(collie_pm_init); diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index 244d5956312c..ef817876a5d6 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -3,17 +3,17 @@ * * Copyright (C) 2000 2001, The Delft University of Technology * - * Authors: + * Authors: * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl): * - major rewrite for linux-2.3.99 - * - rewritten for the more generic power management scheme in + * - rewritten for the more generic power management scheme in * linux-2.4.5-rmk1 * * This software has been developed while working on the LART * computing board (http://www.lartmaker.nl/), which is * sponsored by the Mobile Multi-media Communications - * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications + * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications * (http://www.ubicom.tudelft.nl/) projects. * * The authors can be reached at: @@ -36,7 +36,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -44,7 +44,7 @@ * * Theory of operations * ==================== - * + * * Clock scaling can be used to lower the power consumption of the CPU * core. This will give you a somewhat longer running time. * @@ -58,11 +58,11 @@ * MDCNFG 0xA0000000 DRAM config * MDCAS0 0xA0000004 Access waveform * MDCAS1 0xA0000008 Access waveform - * MDCAS2 0xA000000C Access waveform + * MDCAS2 0xA000000C Access waveform * * Care must be taken to change the DRAM parameters the correct way, * because otherwise the DRAM becomes unusable and the kernel will - * crash. + * crash. * * The simple solution to avoid a kernel crash is to put the actual * clock change in ROM and jump to that code from the kernel. The main @@ -75,7 +75,7 @@ * as long as all re-configuration steps yield a valid DRAM * configuration. The advantages are clear: it will run on all SA-1100 * platforms, and the code is very simple. - * + * * If you really want to understand what is going on in * sa1100_update_dram_timings(), you'll have to read sections 8.2, * 9.5.7.3, and 10.2 from the "Intel StrongARM SA-1100 Microprocessor @@ -97,7 +97,7 @@ typedef struct { int speed; u32 mdcnfg; - u32 mdcas0; + u32 mdcas0; u32 mdcas1; u32 mdcas2; } sa1100_dram_regs_t; @@ -147,7 +147,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) /* No risk, no fun: run with interrupts on! */ if (new_speed > current_speed) { /* We're going FASTER, so first relax the memory - * timings before changing the core frequency + * timings before changing the core frequency */ /* Half the memory access clock */ diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 3e4fb214eada..63b32b68b296 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -81,14 +81,14 @@ static struct sdram_params sdram_tbl[] __initdata = { .twr = 9, .refresh = 64000, .cas_latency = 3, - }, { /* Samsung K4S281632B-1H */ - .name = "K4S281632B-1H", - .rows = 12, - .tck = 10, - .trp = 20, - .twr = 10, - .refresh = 64000, - .cas_latency = 3, + }, { /* Samsung K4S281632B-1H */ + .name = "K4S281632B-1H", + .rows = 12, + .tck = 10, + .trp = 20, + .twr = 10, + .refresh = 64000, + .cas_latency = 3, }, { /* Samsung KM416S4030CT */ .name = "KM416S4030CT", .rows = 13, @@ -220,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) } /* - * Ok, set the CPU frequency. + * Ok, set the CPU frequency. */ static int sa1110_target(struct cpufreq_policy *policy, unsigned int target_freq, diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c index f990a3e85846..95f9c5a6d6d5 100644 --- a/arch/arm/mach-sa1100/dma.c +++ b/arch/arm/mach-sa1100/dma.c @@ -19,7 +19,7 @@ #include <asm/system.h> #include <asm/irq.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> #undef DEBUG @@ -113,10 +113,10 @@ int sa1100_request_dma (dma_device_t device, const char *device_id, } } if (!err) { - if (dma) - dma->device = device; - else - err = -ENOSR; + if (dma) + dma->device = device; + else + err = -ENOSR; } spin_unlock(&dma_list_lock); if (err) diff --git a/arch/arm/mach-sa1100/include/mach/h3600.h b/arch/arm/mach-sa1100/include/mach/h3600.h index 3ca0ecf095e6..9cc47fddb335 100644 --- a/arch/arm/mach-sa1100/include/mach/h3600.h +++ b/arch/arm/mach-sa1100/include/mach/h3600.h @@ -32,14 +32,14 @@ typedef int __bitwise pm_request_t; #define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800()) /* Physical memory regions corresponding to chip selects */ -#define H3600_EGPIO_PHYS (SA1100_CS5_PHYS + 0x01000000) -#define H3600_BANK_2_PHYS SA1100_CS2_PHYS -#define H3600_BANK_4_PHYS SA1100_CS4_PHYS +#define H3600_EGPIO_PHYS (SA1100_CS5_PHYS + 0x01000000) +#define H3600_BANK_2_PHYS SA1100_CS2_PHYS +#define H3600_BANK_4_PHYS SA1100_CS4_PHYS /* Virtual memory regions corresponding to chip selects 2 & 4 (used on sleeves) */ -#define H3600_EGPIO_VIRT 0xf0000000 -#define H3600_BANK_2_VIRT 0xf1000000 -#define H3600_BANK_4_VIRT 0xf3800000 +#define H3600_EGPIO_VIRT 0xf0000000 +#define H3600_BANK_2_VIRT 0xf1000000 +#define H3600_BANK_4_VIRT 0xf3800000 /* Machine-independent GPIO definitions diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h index b70846c096aa..60711822b125 100644 --- a/arch/arm/mach-sa1100/include/mach/hardware.h +++ b/arch/arm/mach-sa1100/include/mach/hardware.h @@ -59,6 +59,10 @@ # define __REG(x) (*((volatile unsigned long *)io_p2v(x))) # define __PREG(x) (io_v2p((unsigned long)&(x))) +static inline unsigned long get_clock_tick_rate(void) +{ + return 3686400; +} #else # define __REG(x) io_p2v(x) diff --git a/arch/arm/mach-sa1100/include/mach/io.h b/arch/arm/mach-sa1100/include/mach/io.h index 0c070a6149bc..d8b43f3dcd2d 100644 --- a/arch/arm/mach-sa1100/include/mach/io.h +++ b/arch/arm/mach-sa1100/include/mach/io.h @@ -16,11 +16,7 @@ * We don't actually have real ISA nor PCI buses, but there is so many * drivers out there that might just work if we fake them... */ -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} -#define __io(a) __io(a) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h index 1c127b68581d..e9f8eed900f5 100644 --- a/arch/arm/mach-sa1100/include/mach/memory.h +++ b/arch/arm/mach-sa1100/include/mach/memory.h @@ -23,23 +23,12 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes); sa1111_adjust_zones(node, size, holes) #define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_1M - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_1M) #endif #endif /* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - * - * On the SA1100, bus addresses are equivalent to physical addresses. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -/* * Because of the wide memory address space between physical RAM banks on the * SA1100, it's much convenient to use Linux's SparseMEM support to implement * our memory map representation. Assuming all memory nodes have equal access diff --git a/arch/arm/mach-sa1100/include/mach/mtd-xip.h b/arch/arm/mach-sa1100/include/mach/mtd-xip.h index eaa09e86ad16..b3d684098fbf 100644 --- a/arch/arm/mach-sa1100/include/mach/mtd-xip.h +++ b/arch/arm/mach-sa1100/include/mach/mtd-xip.h @@ -15,6 +15,8 @@ #ifndef __ARCH_SA1100_MTD_XIP_H__ #define __ARCH_SA1100_MTD_XIP_H__ +#include <mach/hardware.h> + #define xip_irqpending() (ICIP & ICMR) /* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */ diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index e45d3a1890bc..e1458bc1868e 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -122,12 +122,12 @@ static void __init pleb_map_io(void) sa1100_map_io(); sa1100_register_uart(0, 3); - sa1100_register_uart(1, 1); + sa1100_register_uart(1, 1); - GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD); - GPDR |= GPIO_UART_TXD; - GPDR &= ~GPIO_UART_RXD; - PPAR |= PPAR_UPR; + GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD); + GPDR |= GPIO_UART_TXD; + GPDR &= ~GPIO_UART_RXD; + PPAR |= PPAR_UPR; /* * Fix expansion memory timing for network card diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 9ccdd09cf69f..ddd917d1083d 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -33,7 +33,7 @@ static struct mtd_partition shannon_partitions[] = { .offset = MTDPART_OFS_APPEND, .size = 0xe0000 }, - { + { .name = "initrd", .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 171441f96710..80f31bad707c 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -100,36 +100,36 @@ ENTRY(sa1100_cpu_suspend) ldr r1, =MSC1 ldr r2, =MSC2 - ldr r3, [r0] - bic r3, r3, #FMsk(MSC_RT) - bic r3, r3, #FMsk(MSC_RT)<<16 + ldr r3, [r0] + bic r3, r3, #FMsk(MSC_RT) + bic r3, r3, #FMsk(MSC_RT)<<16 - ldr r4, [r1] - bic r4, r4, #FMsk(MSC_RT) - bic r4, r4, #FMsk(MSC_RT)<<16 + ldr r4, [r1] + bic r4, r4, #FMsk(MSC_RT) + bic r4, r4, #FMsk(MSC_RT)<<16 - ldr r5, [r2] - bic r5, r5, #FMsk(MSC_RT) - bic r5, r5, #FMsk(MSC_RT)<<16 + ldr r5, [r2] + bic r5, r5, #FMsk(MSC_RT) + bic r5, r5, #FMsk(MSC_RT)<<16 - ldr r6, =MDREFR + ldr r6, =MDREFR - ldr r7, [r6] - bic r7, r7, #0x0000FF00 - bic r7, r7, #0x000000F0 - orr r8, r7, #MDREFR_SLFRSH + ldr r7, [r6] +bic r7, r7, #0x0000FF00 +bic r7, r7, #0x000000F0 +orr r8, r7, #MDREFR_SLFRSH - ldr r9, =MDCNFG - ldr r10, [r9] - bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1) - bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3) + ldr r9, =MDCNFG + ldr r10, [r9] + bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1) + bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3) - bic r11, r8, #MDREFR_SLFRSH - bic r11, r11, #MDREFR_E1PIN + bic r11, r8, #MDREFR_SLFRSH + bic r11, r11, #MDREFR_E1PIN - ldr r12, =PMCR + ldr r12, =PMCR - mov r13, #PMCR_SF + mov r13, #PMCR_SF b sa1110_sdram_controller_fix @@ -188,10 +188,10 @@ ENTRY(sa1100_cpu_resume) mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache mcr p15, 0, r1, c9, c0, 0 @ invalidate RB - mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB + mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB - mcr p15, 0, r4, c3, c0, 0 @ domain ID - mcr p15, 0, r5, c2, c0, 0 @ translation table base addr + mcr p15, 0, r4, c3, c0, 0 @ domain ID + mcr p15, 0, r5, c2, c0, 0 @ translation table base addr mcr p15, 0, r6, c13, c0, 0 @ PID b resume_turn_on_mmu @ cache align execution @@ -209,7 +209,7 @@ sleep_save_sp: .text resume_after_mmu: - mcr p15, 0, r1, c15, c1, 2 @ enable clock switching + mcr p15, 0, r1, c15, c1, 2 @ enable clock switching ldmfd sp!, {r4 - r12, pc} @ return to caller diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 24c0a4bae850..8c5e727f3b75 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -2,8 +2,8 @@ * linux/arch/arm/mach-sa1100/time.c * * Copyright (C) 1998 Deborah Wallach. - * Twiddles (C) 1999 Hugo Fiennes <hugo@empeg.com> - * + * Twiddles (C) 1999 Hugo Fiennes <hugo@empeg.com> + * * 2000/03/29 (C) Nicolas Pitre <nico@cam.org> * Rewritten: big cleanup, much simpler, better HZ accuracy. * diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index a9400d984451..a23fd3d0163a 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -16,6 +16,8 @@ #include <asm/leds.h> #include <asm/param.h> +#include <mach/hardware.h> + #include <asm/mach/map.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h index cb0ee2943c1a..01bf76099ce5 100644 --- a/arch/arm/mach-shark/include/mach/hardware.h +++ b/arch/arm/mach-shark/include/mach/hardware.h @@ -28,8 +28,6 @@ #define ROMCARD_SIZE 0x08000000 #define ROMCARD_START 0x10000000 -#define PCIO_BASE 0xe0000000 - /* defines for the Framebuffer */ #define FB_START 0x06000000 diff --git a/arch/arm/mach-shark/include/mach/io.h b/arch/arm/mach-shark/include/mach/io.h index 92475922c068..c5cee829fc87 100644 --- a/arch/arm/mach-shark/include/mach/io.h +++ b/arch/arm/mach-shark/include/mach/io.h @@ -11,46 +11,10 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include <mach/hardware.h> +#define PCIO_BASE 0xe0000000 +#define IO_SPACE_LIMIT 0xffffffff -#define IO_SPACE_LIMIT 0xffffffff - -/* - * We use two different types of addressing - PC style addresses, and ARM - * addresses. PC style accesses the PC hardware with the normal PC IO - * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ - * and are translated to the start of IO. - */ -#define __PORT_PCIO(x) (!((x) & 0x80000000)) - -#define __io(a) ((void __iomem *)(PCIO_BASE + (a))) - - -static inline unsigned int __ioaddr (unsigned int port) \ -{ \ - if (__PORT_PCIO(port)) \ - return (unsigned int)(PCIO_BASE + (port)); \ - else \ - return (unsigned int)(IO_BASE + (port)); \ -} - -#define __mem_pci(addr) (addr) - -/* - * Translated address IO functions - * - * IO address has already been translated to a virtual address - */ -#define outb_t(v,p) \ - (*(volatile unsigned char *)(p) = (v)) - -#define inb_t(p) \ - (*(volatile unsigned char *)(p)) - -#define outl_t(v,p) \ - (*(volatile unsigned long *)(p) = (v)) - -#define inl_t(p) \ - (*(volatile unsigned long *)(p)) +#define __io(a) ((void __iomem *)(PCIO_BASE + (a))) +#define __mem_pci(addr) (addr) #endif diff --git a/arch/arm/mach-shark/include/mach/dma.h b/arch/arm/mach-shark/include/mach/isa-dma.h index c0a29bd2a74f..864298ff3927 100644 --- a/arch/arm/mach-shark/include/mach/dma.h +++ b/arch/arm/mach-shark/include/mach/isa-dma.h @@ -1,5 +1,5 @@ /* - * arch/arm/mach-shark/include/mach/dma.h + * arch/arm/mach-shark/include/mach/isa-dma.h * * by Alexander Schulz */ @@ -10,7 +10,6 @@ * The rest is not DMAable. See dev / .properties * in OpenFirmware. */ -#define MAX_DMA_ADDRESS 0xC0400000 #define MAX_DMA_CHANNELS 8 #define DMA_ISA_CASCADE 4 diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h index b7874ad9f9f6..c5ab038925d6 100644 --- a/arch/arm/mach-shark/include/mach/memory.h +++ b/arch/arm/mach-shark/include/mach/memory.h @@ -33,12 +33,10 @@ static inline void __arch_adjust_zones(int node, unsigned long *zone_size, unsig __arch_adjust_zones(node, size, holes) #define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_4M - 1) +#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_4M) #endif -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - /* * Cache flushing area */ diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig index 95096afd5271..c781f30c8368 100644 --- a/arch/arm/mach-versatile/Kconfig +++ b/arch/arm/mach-versatile/Kconfig @@ -3,12 +3,14 @@ menu "Versatile platform type" config ARCH_VERSATILE_PB bool "Support Versatile/PB platform" + select CPU_ARM926T default y help Include support for the ARM(R) Versatile/PB platform. config MACH_VERSATILE_AB bool "Support Versatile/AB platform" + select CPU_ARM926T help Include support for the ARM(R) Versatile/AP platform. diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 58937f1fb38c..c50a44ea7ee6 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -10,6 +10,7 @@ */ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/device.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> @@ -17,36 +18,11 @@ #include <linux/clk.h> #include <linux/mutex.h> +#include <asm/clkdev.h> #include <asm/hardware/icst307.h> #include "clock.h" -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - - mutex_lock(&clocks_mutex); - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); - int clk_enable(struct clk *clk) { return 0; @@ -66,7 +42,9 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - return rate; + struct icst307_vco vco; + vco = icst307_khz_to_vco(clk->params, rate / 1000); + return icst307_khz(clk->params, vco) * 1000; } EXPORT_SYMBOL(clk_round_rate); @@ -79,57 +57,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) vco = icst307_khz_to_vco(clk->params, rate / 1000); clk->rate = icst307_khz(clk->params, vco) * 1000; - - printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", - clk->name, vco.s, vco.r, vco.v); - clk->setvco(clk, vco); ret = 0; } return ret; } EXPORT_SYMBOL(clk_set_rate); - -/* - * These are fixed clocks. - */ -static struct clk kmi_clk = { - .name = "KMIREFCLK", - .rate = 24000000, -}; - -static struct clk uart_clk = { - .name = "UARTCLK", - .rate = 24000000, -}; - -static struct clk mmci_clk = { - .name = "MCLK", - .rate = 24000000, -}; - -int clk_register(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; -} -EXPORT_SYMBOL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -static int __init clk_init(void) -{ - clk_register(&kmi_clk); - clk_register(&uart_clk); - clk_register(&mmci_clk); - return 0; -} -arch_initcall(clk_init); diff --git a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h index 8b0b61dd17e4..03468fdc3e58 100644 --- a/arch/arm/mach-versatile/clock.h +++ b/arch/arm/mach-versatile/clock.h @@ -12,14 +12,9 @@ struct module; struct icst307_params; struct clk { - struct list_head node; unsigned long rate; - struct module *owner; - const char *name; const struct icst307_params *params; + u32 oscoff; void *data; void (*setvco)(struct clk *, struct icst307_vco vco); }; - -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 565e0ba0d67e..df25aa138509 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -31,6 +31,7 @@ #include <linux/cnt32_to_63.h> #include <linux/io.h> +#include <asm/clkdev.h> #include <asm/system.h> #include <mach/hardware.h> #include <asm/irq.h> @@ -373,22 +374,60 @@ static const struct icst307_params versatile_oscvco_params = { static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) { - void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; - void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET; + void __iomem *sys = __io_address(VERSATILE_SYS_BASE); + void __iomem *sys_lock = sys + VERSATILE_SYS_LOCK_OFFSET; u32 val; - val = readl(sys_osc) & ~0x7ffff; + val = readl(sys + clk->oscoff) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, sys_lock); - writel(val, sys_osc); + writel(val, sys + clk->oscoff); writel(0, sys_lock); } -static struct clk versatile_clcd_clk = { - .name = "CLCDCLK", +static struct clk osc4_clk = { .params = &versatile_oscvco_params, - .setvco = versatile_oscvco_set, + .oscoff = VERSATILE_SYS_OSCCLCD_OFFSET, + .setvco = versatile_oscvco_set, +}; + +/* + * These are fixed clocks. + */ +static struct clk ref24_clk = { + .rate = 24000000, +}; + +static struct clk_lookup lookups[] __initdata = { + { /* UART0 */ + .dev_id = "dev:f1", + .clk = &ref24_clk, + }, { /* UART1 */ + .dev_id = "dev:f2", + .clk = &ref24_clk, + }, { /* UART2 */ + .dev_id = "dev:f3", + .clk = &ref24_clk, + }, { /* UART3 */ + .dev_id = "fpga:09", + .clk = &ref24_clk, + }, { /* KMI0 */ + .dev_id = "fpga:06", + .clk = &ref24_clk, + }, { /* KMI1 */ + .dev_id = "fpga:07", + .clk = &ref24_clk, + }, { /* MMC0 */ + .dev_id = "fpga:05", + .clk = &ref24_clk, + }, { /* MMC1 */ + .dev_id = "fpga:0b", + .clk = &ref24_clk, + }, { /* CLCD */ + .dev_id = "dev:20", + .clk = &osc4_clk, + } }; /* @@ -786,7 +825,8 @@ void __init versatile_init(void) { int i; - clk_register(&versatile_clcd_clk); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); platform_device_register(&versatile_flash_device); platform_device_register(&versatile_i2c_device); diff --git a/arch/arm/mach-versatile/include/mach/clkdev.h b/arch/arm/mach-versatile/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-versatile/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-versatile/include/mach/dma.h b/arch/arm/mach-versatile/include/mach/dma.h deleted file mode 100644 index 0aabf12c8834..000000000000 --- a/arch/arm/mach-versatile/include/mach/dma.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * arch/arm/mach-versatile/include/mach/dma.h - * - * Copyright (C) 2003 ARM Limited. - * Copyright (C) 1997,1998 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/arch/arm/mach-versatile/include/mach/io.h b/arch/arm/mach-versatile/include/mach/io.h index c0b9dd1d0257..f067c14c7182 100644 --- a/arch/arm/mach-versatile/include/mach/io.h +++ b/arch/arm/mach-versatile/include/mach/io.h @@ -22,11 +22,7 @@ #define IO_SPACE_LIMIT 0xffffffff -static inline void __iomem *__io(unsigned long addr) -{ - return (void __iomem *)addr; -} -#define __io(a) __io(a) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-versatile/include/mach/irqs.h b/arch/arm/mach-versatile/include/mach/irqs.h index 216a1312e62e..9bfdb30e1f3f 100644 --- a/arch/arm/mach-versatile/include/mach/irqs.h +++ b/arch/arm/mach-versatile/include/mach/irqs.h @@ -60,39 +60,6 @@ #define IRQ_VICSOURCE31 (IRQ_VIC_START + INT_VICSOURCE31) #define IRQ_VIC_END (IRQ_VIC_START + 31) -#define IRQMASK_WDOGINT INTMASK_WDOGINT -#define IRQMASK_SOFTINT INTMASK_SOFTINT -#define IRQMASK_COMMRx INTMASK_COMMRx -#define IRQMASK_COMMTx INTMASK_COMMTx -#define IRQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1 -#define IRQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3 -#define IRQMASK_GPIOINT0 INTMASK_GPIOINT0 -#define IRQMASK_GPIOINT1 INTMASK_GPIOINT1 -#define IRQMASK_GPIOINT2 INTMASK_GPIOINT2 -#define IRQMASK_GPIOINT3 INTMASK_GPIOINT3 -#define IRQMASK_RTCINT INTMASK_RTCINT -#define IRQMASK_SSPINT INTMASK_SSPINT -#define IRQMASK_UARTINT0 INTMASK_UARTINT0 -#define IRQMASK_UARTINT1 INTMASK_UARTINT1 -#define IRQMASK_UARTINT2 INTMASK_UARTINT2 -#define IRQMASK_SCIINT INTMASK_SCIINT -#define IRQMASK_CLCDINT INTMASK_CLCDINT -#define IRQMASK_DMAINT INTMASK_DMAINT -#define IRQMASK_PWRFAILINT INTMASK_PWRFAILINT -#define IRQMASK_MBXINT INTMASK_MBXINT -#define IRQMASK_GNDINT INTMASK_GNDINT -#define IRQMASK_VICSOURCE21 INTMASK_VICSOURCE21 -#define IRQMASK_VICSOURCE22 INTMASK_VICSOURCE22 -#define IRQMASK_VICSOURCE23 INTMASK_VICSOURCE23 -#define IRQMASK_VICSOURCE24 INTMASK_VICSOURCE24 -#define IRQMASK_VICSOURCE25 INTMASK_VICSOURCE25 -#define IRQMASK_VICSOURCE26 INTMASK_VICSOURCE26 -#define IRQMASK_VICSOURCE27 INTMASK_VICSOURCE27 -#define IRQMASK_VICSOURCE28 INTMASK_VICSOURCE28 -#define IRQMASK_VICSOURCE29 INTMASK_VICSOURCE29 -#define IRQMASK_VICSOURCE30 INTMASK_VICSOURCE30 -#define IRQMASK_VICSOURCE31 INTMASK_VICSOURCE31 - /* * FIQ interrupts definitions are the same as the INT definitions. */ @@ -130,39 +97,6 @@ #define FIQ_VICSOURCE31 INT_VICSOURCE31 -#define FIQMASK_WDOGINT INTMASK_WDOGINT -#define FIQMASK_SOFTINT INTMASK_SOFTINT -#define FIQMASK_COMMRx INTMASK_COMMRx -#define FIQMASK_COMMTx INTMASK_COMMTx -#define FIQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1 -#define FIQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3 -#define FIQMASK_GPIOINT0 INTMASK_GPIOINT0 -#define FIQMASK_GPIOINT1 INTMASK_GPIOINT1 -#define FIQMASK_GPIOINT2 INTMASK_GPIOINT2 -#define FIQMASK_GPIOINT3 INTMASK_GPIOINT3 -#define FIQMASK_RTCINT INTMASK_RTCINT -#define FIQMASK_SSPINT INTMASK_SSPINT -#define FIQMASK_UARTINT0 INTMASK_UARTINT0 -#define FIQMASK_UARTINT1 INTMASK_UARTINT1 -#define FIQMASK_UARTINT2 INTMASK_UARTINT2 -#define FIQMASK_SCIINT INTMASK_SCIINT -#define FIQMASK_CLCDINT INTMASK_CLCDINT -#define FIQMASK_DMAINT INTMASK_DMAINT -#define FIQMASK_PWRFAILINT INTMASK_PWRFAILINT -#define FIQMASK_MBXINT INTMASK_MBXINT -#define FIQMASK_GNDINT INTMASK_GNDINT -#define FIQMASK_VICSOURCE21 INTMASK_VICSOURCE21 -#define FIQMASK_VICSOURCE22 INTMASK_VICSOURCE22 -#define FIQMASK_VICSOURCE23 INTMASK_VICSOURCE23 -#define FIQMASK_VICSOURCE24 INTMASK_VICSOURCE24 -#define FIQMASK_VICSOURCE25 INTMASK_VICSOURCE25 -#define FIQMASK_VICSOURCE26 INTMASK_VICSOURCE26 -#define FIQMASK_VICSOURCE27 INTMASK_VICSOURCE27 -#define FIQMASK_VICSOURCE28 INTMASK_VICSOURCE28 -#define FIQMASK_VICSOURCE29 INTMASK_VICSOURCE29 -#define FIQMASK_VICSOURCE30 INTMASK_VICSOURCE30 -#define FIQMASK_VICSOURCE31 INTMASK_VICSOURCE31 - /* * Secondary interrupt controller */ @@ -188,24 +122,4 @@ #define IRQ_SIC_PCI3 (IRQ_SIC_START + SIC_INT_PCI3) #define IRQ_SIC_END 63 -#define SIC_IRQMASK_MMCI0B SIC_INTMASK_MMCI0B -#define SIC_IRQMASK_MMCI1B SIC_INTMASK_MMCI1B -#define SIC_IRQMASK_KMI0 SIC_INTMASK_KMI0 -#define SIC_IRQMASK_KMI1 SIC_INTMASK_KMI1 -#define SIC_IRQMASK_SCI3 SIC_INTMASK_SCI3 -#define SIC_IRQMASK_UART3 SIC_INTMASK_UART3 -#define SIC_IRQMASK_CLCD SIC_INTMASK_CLCD -#define SIC_IRQMASK_TOUCH SIC_INTMASK_TOUCH -#define SIC_IRQMASK_KEYPAD SIC_INTMASK_KEYPAD -#define SIC_IRQMASK_DoC SIC_INTMASK_DoC -#define SIC_IRQMASK_MMCI0A SIC_INTMASK_MMCI0A -#define SIC_IRQMASK_MMCI1A SIC_INTMASK_MMCI1A -#define SIC_IRQMASK_AACI SIC_INTMASK_AACI -#define SIC_IRQMASK_ETH SIC_INTMASK_ETH -#define SIC_IRQMASK_USB SIC_INTMASK_USB -#define SIC_IRQMASK_PCI0 SIC_INTMASK_PCI0 -#define SIC_IRQMASK_PCI1 SIC_INTMASK_PCI1 -#define SIC_IRQMASK_PCI2 SIC_INTMASK_PCI2 -#define SIC_IRQMASK_PCI3 SIC_INTMASK_PCI3 - #define NR_IRQS 64 diff --git a/arch/arm/mach-versatile/include/mach/memory.h b/arch/arm/mach-versatile/include/mach/memory.h index b6315c0602ac..79aeab86b903 100644 --- a/arch/arm/mach-versatile/include/mach/memory.h +++ b/arch/arm/mach-versatile/include/mach/memory.h @@ -25,14 +25,4 @@ */ #define PHYS_OFFSET UL(0x00000000) -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define __virt_to_bus(x) ((x) - PAGE_OFFSET) -#define __bus_to_virt(x) ((x) + PAGE_OFFSET) - #endif diff --git a/arch/arm/mach-versatile/include/mach/platform.h b/arch/arm/mach-versatile/include/mach/platform.h index f91ba930ca8a..83207395191a 100644 --- a/arch/arm/mach-versatile/include/mach/platform.h +++ b/arch/arm/mach-versatile/include/mach/platform.h @@ -347,44 +347,6 @@ #define INT_VICSOURCE30 30 /* PCI 3 */ #define INT_VICSOURCE31 31 /* SIC source */ -/* - * Interrupt bit positions - * - */ -#define INTMASK_WDOGINT (1 << INT_WDOGINT) -#define INTMASK_SOFTINT (1 << INT_SOFTINT) -#define INTMASK_COMMRx (1 << INT_COMMRx) -#define INTMASK_COMMTx (1 << INT_COMMTx) -#define INTMASK_TIMERINT0_1 (1 << INT_TIMERINT0_1) -#define INTMASK_TIMERINT2_3 (1 << INT_TIMERINT2_3) -#define INTMASK_GPIOINT0 (1 << INT_GPIOINT0) -#define INTMASK_GPIOINT1 (1 << INT_GPIOINT1) -#define INTMASK_GPIOINT2 (1 << INT_GPIOINT2) -#define INTMASK_GPIOINT3 (1 << INT_GPIOINT3) -#define INTMASK_RTCINT (1 << INT_RTCINT) -#define INTMASK_SSPINT (1 << INT_SSPINT) -#define INTMASK_UARTINT0 (1 << INT_UARTINT0) -#define INTMASK_UARTINT1 (1 << INT_UARTINT1) -#define INTMASK_UARTINT2 (1 << INT_UARTINT2) -#define INTMASK_SCIINT (1 << INT_SCIINT) -#define INTMASK_CLCDINT (1 << INT_CLCDINT) -#define INTMASK_DMAINT (1 << INT_DMAINT) -#define INTMASK_PWRFAILINT (1 << INT_PWRFAILINT) -#define INTMASK_MBXINT (1 << INT_MBXINT) -#define INTMASK_GNDINT (1 << INT_GNDINT) -#define INTMASK_VICSOURCE21 (1 << INT_VICSOURCE21) -#define INTMASK_VICSOURCE22 (1 << INT_VICSOURCE22) -#define INTMASK_VICSOURCE23 (1 << INT_VICSOURCE23) -#define INTMASK_VICSOURCE24 (1 << INT_VICSOURCE24) -#define INTMASK_VICSOURCE25 (1 << INT_VICSOURCE25) -#define INTMASK_VICSOURCE26 (1 << INT_VICSOURCE26) -#define INTMASK_VICSOURCE27 (1 << INT_VICSOURCE27) -#define INTMASK_VICSOURCE28 (1 << INT_VICSOURCE28) -#define INTMASK_VICSOURCE29 (1 << INT_VICSOURCE29) -#define INTMASK_VICSOURCE30 (1 << INT_VICSOURCE30) -#define INTMASK_VICSOURCE31 (1 << INT_VICSOURCE31) - - #define VERSATILE_SC_VALID_INT 0x003FFFFF #define MAXIRQNUM 31 @@ -417,26 +379,6 @@ #define SIC_INT_PCI3 30 -#define SIC_INTMASK_MMCI0B (1 << SIC_INT_MMCI0B) -#define SIC_INTMASK_MMCI1B (1 << SIC_INT_MMCI1B) -#define SIC_INTMASK_KMI0 (1 << SIC_INT_KMI0) -#define SIC_INTMASK_KMI1 (1 << SIC_INT_KMI1) -#define SIC_INTMASK_SCI3 (1 << SIC_INT_SCI3) -#define SIC_INTMASK_UART3 (1 << SIC_INT_UART3) -#define SIC_INTMASK_CLCD (1 << SIC_INT_CLCD) -#define SIC_INTMASK_TOUCH (1 << SIC_INT_TOUCH) -#define SIC_INTMASK_KEYPAD (1 << SIC_INT_KEYPAD) -#define SIC_INTMASK_DoC (1 << SIC_INT_DoC) -#define SIC_INTMASK_MMCI0A (1 << SIC_INT_MMCI0A) -#define SIC_INTMASK_MMCI1A (1 << SIC_INT_MMCI1A) -#define SIC_INTMASK_AACI (1 << SIC_INT_AACI) -#define SIC_INTMASK_ETH (1 << SIC_INT_ETH) -#define SIC_INTMASK_USB (1 << SIC_INT_USB) -#define SIC_INTMASK_PCI0 (1 << SIC_INT_PCI0) -#define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1) -#define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2) -#define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3) - /* * Clean base - dummy * diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig new file mode 100644 index 000000000000..8e4178fe5ec2 --- /dev/null +++ b/arch/arm/mach-w90x900/Kconfig @@ -0,0 +1,19 @@ +if ARCH_W90X900 + +config CPU_W90P910 + bool + help + Support for W90P910 of Nuvoton W90X900 CPUs. + +menu "W90P910 Machines" + +config MACH_W90P910EVB + bool "Nuvoton W90P910 Evaluation Board" + default y + select CPU_W90P910 + help + Say Y here if you are using the Nuvoton W90P910EVB + +endmenu + +endif diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile new file mode 100644 index 000000000000..0c0c1d63f1c7 --- /dev/null +++ b/arch/arm/mach-w90x900/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := irq.o time.o + +# W90X900 CPU support files + +obj-$(CONFIG_CPU_W90P910) += w90p910.o + +# machine support + +obj-$(CONFIG_MACH_W90P910EVB) += mach-w90p910evb.o diff --git a/arch/arm/mach-w90x900/Makefile.boot b/arch/arm/mach-w90x900/Makefile.boot new file mode 100644 index 000000000000..a057b546b6e5 --- /dev/null +++ b/arch/arm/mach-w90x900/Makefile.boot @@ -0,0 +1,3 @@ +zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 + diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h new file mode 100644 index 000000000000..40ff40845df0 --- /dev/null +++ b/arch/arm/mach-w90x900/cpu.h @@ -0,0 +1,77 @@ +/* + * arch/arm/mach-w90x900/cpu.h + * + * Based on linux/include/asm-arm/plat-s3c24xx/cpu.h by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Header file for W90X900 CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define IODESC_ENT(y) \ +{ \ + .virtual = (unsigned long)W90X900_VA_##y, \ + .pfn = __phys_to_pfn(W90X900_PA_##y), \ + .length = W90X900_SZ_##y, \ + .type = MT_DEVICE, \ +} + +/*Cpu identifier register*/ + +#define W90X900PDID W90X900_VA_GCR +#define W90P910_CPUID 0x02900910 +#define W90P920_CPUID 0x02900920 +#define W90P950_CPUID 0x02900950 +#define W90N960_CPUID 0x02900960 + +struct w90x900_uartcfg; +struct map_desc; +struct sys_timer; + +/* core initialisation functions */ + +extern void w90x900_init_irq(void); +extern void w90p910_init_io(struct map_desc *mach_desc, int size); +extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no); +extern void w90p910_init_clocks(int xtal); +extern void w90p910_map_io(struct map_desc *mach_desc, int size); +extern struct sys_timer w90x900_timer; + +#define W90X900_RES(name) \ +struct resource w90x900_##name##_resource[] = { \ + [0] = { \ + .start = name##_PA, \ + .end = name##_PA + 0x0ff, \ + .flags = IORESOURCE_MEM, \ + }, \ + [1] = { \ + .start = IRQ_##name, \ + .end = IRQ_##name, \ + .flags = IORESOURCE_IRQ, \ + } \ +} + +#define W90X900_DEVICE(devname, regname, devid, platdevname) \ +struct platform_device w90x900_##devname = { \ + .name = platdevname, \ + .id = devid, \ + .num_resources = ARRAY_SIZE(w90x900_##regname##_resource), \ + .resource = w90x900_##regname##_resource, \ +} + +#define W90X900_UARTCFG(port, flag, uc, ulc, ufc) \ +{ \ + .hwport = port, \ + .flags = flag, \ + .ucon = uc, \ + .ulcon = ulc, \ + .ufcon = ufc, \ +} diff --git a/arch/arm/mach-w90x900/include/mach/entry-macro.S b/arch/arm/mach-w90x900/include/mach/entry-macro.S new file mode 100644 index 000000000000..d39aca5be9ee --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/entry-macro.S @@ -0,0 +1,34 @@ +/* + * arch/arm/mach-w90x900/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for W90P910-based platforms + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + */ + +#include <mach/hardware.h> +#include <mach/regs-irq.h> + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + mov \base, #AIC_BA + + ldr \irqnr, [ \base, #AIC_IPER] + ldr \irqnr, [ \base, #AIC_ISNR] + cmp \irqnr, #0 + + .endm + + /* currently don't need an disable_fiq macro */ + + .macro disable_fiq + .endm diff --git a/arch/arm/mach-w90x900/include/mach/hardware.h b/arch/arm/mach-w90x900/include/mach/hardware.h new file mode 100644 index 000000000000..fe3c6265a466 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/hardware.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-w90x900/include/mach/hardware.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/hardware.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <asm/sizes.h> +#include <mach/map.h> + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-w90x900/include/mach/io.h b/arch/arm/mach-w90x900/include/mach/io.h new file mode 100644 index 000000000000..d96ab99df05b --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/io.h @@ -0,0 +1,30 @@ +/* + * arch/arm/mach-w90x900/include/mach/io.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/io.h + * + * 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. + * + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * 1:1 mapping for ioremapped regions. + */ + +#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) + +#endif diff --git a/arch/arm/mach-w90x900/include/mach/irqs.h b/arch/arm/mach-w90x900/include/mach/irqs.h new file mode 100644 index 000000000000..1c583f9cbcde --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/irqs.h @@ -0,0 +1,45 @@ +/* + * arch/arm/mach-w90x900/include/mach/irqs.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/irqs.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +/* + * we keep the first set of CPU IRQs out of the range of + * the ISA space, so that the PC104 has them to itself + * and we don't end up having to do horrible things to the + * standard ISA drivers.... + * + */ + +#define W90X900_IRQ(x) (x) + +/* Main cpu interrupts */ + +#define IRQ_WDT W90X900_IRQ(1) +#define IRQ_UART0 W90X900_IRQ(7) +#define IRQ_UART1 W90X900_IRQ(8) +#define IRQ_UART2 W90X900_IRQ(9) +#define IRQ_UART3 W90X900_IRQ(10) +#define IRQ_UART4 W90X900_IRQ(11) +#define IRQ_TIMER0 W90X900_IRQ(12) +#define IRQ_TIMER1 W90X900_IRQ(13) +#define IRQ_T_INT_GROUP W90X900_IRQ(14) +#define IRQ_ADC W90X900_IRQ(31) +#define NR_IRQS (IRQ_ADC+1) + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-w90x900/include/mach/map.h b/arch/arm/mach-w90x900/include/mach/map.h new file mode 100644 index 000000000000..79320ebe614b --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/map.h @@ -0,0 +1,76 @@ +/* + * arch/arm/mach-w90x900/include/mach/map.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/map.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H + +#ifndef __ASSEMBLY__ +#define W90X900_ADDR(x) ((void __iomem *)(0xF0000000 + (x))) +#else +#define W90X900_ADDR(x) (0xF0000000 + (x)) +#endif + +#define AHB_IO_BASE 0xB0000000 +#define APB_IO_BASE 0xB8000000 +#define CLOCKPW_BASE (APB_IO_BASE+0x200) +#define AIC_IO_BASE (APB_IO_BASE+0x2000) +#define TIMER_IO_BASE (APB_IO_BASE+0x1000) + +/* + * interrupt controller is the first thing we put in, to make + * the assembly code for the irq detection easier + */ + +#define W90X900_VA_IRQ W90X900_ADDR(0x00000000) +#define W90X900_PA_IRQ (0xB8002000) +#define W90X900_SZ_IRQ SZ_4K + +#define W90X900_VA_GCR W90X900_ADDR(0x08002000) +#define W90X900_PA_GCR (0xB0000000) +#define W90X900_SZ_GCR SZ_4K + +/* Clock and Power management */ + +#define W90X900_VA_CLKPWR (W90X900_VA_GCR+0x200) +#define W90X900_PA_CLKPWR (0xB0000200) +#define W90X900_SZ_CLKPWR SZ_4K + +/* EBI management */ + +#define W90X900_VA_EBI W90X900_ADDR(0x00001000) +#define W90X900_PA_EBI (0xB0001000) +#define W90X900_SZ_EBI SZ_4K + +/* UARTs */ + +#define W90X900_VA_UART W90X900_ADDR(0x08000000) +#define W90X900_PA_UART (0xB8000000) +#define W90X900_SZ_UART SZ_4K + +/* Timers */ + +#define W90X900_VA_TIMER W90X900_ADDR(0x08001000) +#define W90X900_PA_TIMER (0xB8001000) +#define W90X900_SZ_TIMER SZ_4K + +/* GPIO ports */ + +#define W90X900_VA_GPIO W90X900_ADDR(0x08003000) +#define W90X900_PA_GPIO (0xB8003000) +#define W90X900_SZ_GPIO SZ_4K + +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-w90x900/include/mach/memory.h b/arch/arm/mach-w90x900/include/mach/memory.h new file mode 100644 index 000000000000..971b80702c27 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/memory.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-w90x900/include/mach/memory.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/memory.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x00000000) + +#endif diff --git a/arch/arm/mach-w90x900/include/mach/regs-irq.h b/arch/arm/mach-w90x900/include/mach/regs-irq.h new file mode 100644 index 000000000000..8a3185fbc9cf --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/regs-irq.h @@ -0,0 +1,51 @@ +/* + * arch/arm/mach-w90x900/include/mach/regs-irq.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/regs-irq.h + * + * 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. + * + */ + +#ifndef ___ASM_ARCH_REGS_IRQ_H +#define ___ASM_ARCH_REGS_IRQ_H + +/* Advance Interrupt Controller (AIC) Registers */ + +#define AIC_BA W90X900_VA_IRQ + +#define REG_AIC_IRQSC (AIC_BA+0x80) +#define REG_AIC_GEN (AIC_BA+0x84) +#define REG_AIC_GASR (AIC_BA+0x88) +#define REG_AIC_GSCR (AIC_BA+0x8C) +#define REG_AIC_IRSR (AIC_BA+0x100) +#define REG_AIC_IASR (AIC_BA+0x104) +#define REG_AIC_ISR (AIC_BA+0x108) +#define REG_AIC_IPER (AIC_BA+0x10C) +#define REG_AIC_ISNR (AIC_BA+0x110) +#define REG_AIC_IMR (AIC_BA+0x114) +#define REG_AIC_OISR (AIC_BA+0x118) +#define REG_AIC_MECR (AIC_BA+0x120) +#define REG_AIC_MDCR (AIC_BA+0x124) +#define REG_AIC_SSCR (AIC_BA+0x128) +#define REG_AIC_SCCR (AIC_BA+0x12C) +#define REG_AIC_EOSCR (AIC_BA+0x130) +#define AIC_IPER (0x10C) +#define AIC_ISNR (0x110) + +/*16-18 bits of REG_AIC_GEN define irq(2-4) group*/ + +#define TIMER2_IRQ (1 << 16) +#define TIMER3_IRQ (1 << 17) +#define TIMER4_IRQ (1 << 18) +#define TIME_GROUP_IRQ (TIMER2_IRQ|TIMER3_IRQ|TIMER4_IRQ) + +#endif /* ___ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-w90x900/include/mach/regs-serial.h b/arch/arm/mach-w90x900/include/mach/regs-serial.h new file mode 100644 index 000000000000..f08fa0d75e11 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/regs-serial.h @@ -0,0 +1,59 @@ +/* + * arch/arm/mach-w90x900/include/mach/regs-serial.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/regs-serial.h + * + * 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. + * + */ + +#ifndef __ASM_ARM_REGS_SERIAL_H +#define __ASM_ARM_REGS_SERIAL_H + +#define UART0_BA W90X900_VA_UART +#define UART1_BA (W90X900_VA_UART+0x100) +#define UART2_BA (W90X900_VA_UART+0x200) +#define UART3_BA (W90X900_VA_UART+0x300) +#define UART4_BA (W90X900_VA_UART+0x400) + +#define UART0_PA W90X900_PA_UART +#define UART1_PA (W90X900_PA_UART+0x100) +#define UART2_PA (W90X900_PA_UART+0x200) +#define UART3_PA (W90X900_PA_UART+0x300) +#define UART4_PA (W90X900_PA_UART+0x400) + +#ifndef __ASSEMBLY__ + +struct w90x900_uart_clksrc { + const char *name; + unsigned int divisor; + unsigned int min_baud; + unsigned int max_baud; +}; + +struct w90x900_uartcfg { + unsigned char hwport; + unsigned char unused; + unsigned short flags; + unsigned long uart_flags; + + unsigned long ucon; + unsigned long ulcon; + unsigned long ufcon; + + struct w90x900_uart_clksrc *clocks; + unsigned int clocks_size; +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARM_REGS_SERIAL_H */ + diff --git a/arch/arm/mach-w90x900/include/mach/regs-timer.h b/arch/arm/mach-w90x900/include/mach/regs-timer.h new file mode 100644 index 000000000000..8f390620c0e4 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/regs-timer.h @@ -0,0 +1,42 @@ +/* + * arch/arm/mach-w90x900/include/mach/regs-timer.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/regs-timer.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_REGS_TIMER_H +#define __ASM_ARCH_REGS_TIMER_H + +/* Timer Registers */ + +#define TMR_BA W90X900_VA_TIMER +#define REG_TCSR0 (TMR_BA+0x00) +#define REG_TCSR1 (TMR_BA+0x04) +#define REG_TICR0 (TMR_BA+0x08) +#define REG_TICR1 (TMR_BA+0x0C) +#define REG_TDR0 (TMR_BA+0x10) +#define REG_TDR1 (TMR_BA+0x14) +#define REG_TISR (TMR_BA+0x18) +#define REG_WTCR (TMR_BA+0x1C) +#define REG_TCSR2 (TMR_BA+0x20) +#define REG_TCSR3 (TMR_BA+0x24) +#define REG_TICR2 (TMR_BA+0x28) +#define REG_TICR3 (TMR_BA+0x2C) +#define REG_TDR2 (TMR_BA+0x30) +#define REG_TDR3 (TMR_BA+0x34) +#define REG_TCSR4 (TMR_BA+0x40) +#define REG_TICR4 (TMR_BA+0x48) +#define REG_TDR4 (TMR_BA+0x50) + +#endif /* __ASM_ARCH_REGS_TIMER_H */ diff --git a/arch/arm/mach-w90x900/include/mach/system.h b/arch/arm/mach-w90x900/include/mach/system.h new file mode 100644 index 000000000000..93753f922618 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/system.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-w90x900/include/mach/system.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/system.h + * + * 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 <asm/proc-fns.h> + +static void arch_idle(void) +{ +} + +static void arch_reset(char mode) +{ + cpu_reset(0); +} + diff --git a/arch/arm/mach-w90x900/include/mach/timex.h b/arch/arm/mach-w90x900/include/mach/timex.h new file mode 100644 index 000000000000..164dce0b64db --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/timex.h @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-w90x900/include/mach/timex.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/timex.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +/* CLOCK_TICK_RATE Now, I don't use it. */ + +#define CLOCK_TICK_RATE 15000000 + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/arch/arm/mach-w90x900/include/mach/uncompress.h b/arch/arm/mach-w90x900/include/mach/uncompress.h new file mode 100644 index 000000000000..050d9fe5ae1b --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/uncompress.h @@ -0,0 +1,40 @@ +/* + * arch/arm/mach-w90x900/include/mach/uncompress.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +/* Defines for UART registers */ + +#include <mach/regs-serial.h> +#include <mach/map.h> + +#define arch_decomp_wdog() + +static void putc(int ch) +{ +} + +static inline void flush(void) +{ +} + +static void arch_decomp_setup(void) +{ +} + +#endif/* __ASM_W90X900_UNCOMPRESS_H */ diff --git a/arch/arm/mach-w90x900/include/mach/vmalloc.h b/arch/arm/mach-w90x900/include/mach/vmalloc.h new file mode 100644 index 000000000000..2f9dfb928533 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/vmalloc.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-w90x900/include/mach/vmalloc.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/vmalloc.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +#define VMALLOC_END (0xE0000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-w90x900/irq.c b/arch/arm/mach-w90x900/irq.c new file mode 100644 index 000000000000..0b4fc194729c --- /dev/null +++ b/arch/arm/mach-w90x900/irq.c @@ -0,0 +1,76 @@ +/* + * linux/arch/arm/mach-w90x900/irq.c + * + * based on linux/arch/arm/plat-s3c24xx/irq.c by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/ptrace.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <asm/irq.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-irq.h> + +static void w90x900_irq_mask(unsigned int irq) +{ + __raw_writel(1 << irq, REG_AIC_MDCR); +} + +/* + * By the w90p910 spec,any irq,only write 1 + * to REG_AIC_EOSCR for ACK + */ + +static void w90x900_irq_ack(unsigned int irq) +{ + __raw_writel(0x01, REG_AIC_EOSCR); +} + +static void w90x900_irq_unmask(unsigned int irq) +{ + unsigned long mask; + + if (irq == IRQ_T_INT_GROUP) { + mask = __raw_readl(REG_AIC_GEN); + __raw_writel(TIME_GROUP_IRQ | mask, REG_AIC_GEN); + __raw_writel(1 << IRQ_T_INT_GROUP, REG_AIC_MECR); + } + __raw_writel(1 << irq, REG_AIC_MECR); +} + +static struct irq_chip w90x900_irq_chip = { + .ack = w90x900_irq_ack, + .mask = w90x900_irq_mask, + .unmask = w90x900_irq_unmask, +}; + +void __init w90x900_init_irq(void) +{ + int irqno; + + __raw_writel(0xFFFFFFFE, REG_AIC_MDCR); + + for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) { + set_irq_chip(irqno, &w90x900_irq_chip); + set_irq_handler(irqno, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } +} diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c new file mode 100644 index 000000000000..9307a2475438 --- /dev/null +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -0,0 +1,72 @@ +/* + * linux/arch/arm/mach-w90x900/mach-w90p910evb.c + * + * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche + * + * Copyright (C) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach-types.h> + +#include <mach/regs-serial.h> + +#include "cpu.h" + +static struct map_desc w90p910_iodesc[] __initdata = { +}; + +static struct w90x900_uartcfg w90p910_uartcfgs[] = { + W90X900_UARTCFG(0, 0, 0, 0, 0), + W90X900_UARTCFG(1, 0, 0, 0, 0), + W90X900_UARTCFG(2, 0, 0, 0, 0), + W90X900_UARTCFG(3, 0, 0, 0, 0), + W90X900_UARTCFG(4, 0, 0, 0, 0), +}; + +/*Here should be your evb resourse,such as LCD*/ + +static struct platform_device *w90p910evb_dev[] __initdata = { +}; + +static void __init w90p910evb_map_io(void) +{ + w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); + w90p910_init_clocks(0); + w90p910_init_uarts(w90p910_uartcfgs, ARRAY_SIZE(w90p910_uartcfgs)); +} + +static void __init w90p910evb_init(void) +{ + platform_add_devices(w90p910evb_dev, ARRAY_SIZE(w90p910evb_dev)); +} + +MACHINE_START(W90P910EVB, "W90P910EVB") + /* Maintainer: Wan ZongShun */ + .phys_io = W90X900_PA_UART, + .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, + .boot_params = 0, + .map_io = w90p910evb_map_io, + .init_irq = w90x900_init_irq, + .init_machine = w90p910evb_init, + .timer = &w90x900_timer, +MACHINE_END diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c new file mode 100644 index 000000000000..3a69e381f316 --- /dev/null +++ b/arch/arm/mach-w90x900/time.c @@ -0,0 +1,80 @@ +/* + * linux/arch/arm/mach-w90x900/time.c + * + * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/leds.h> + +#include <asm/mach-types.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> + +#include <mach/system.h> +#include <mach/map.h> +#include <mach/regs-timer.h> + +static unsigned long w90x900_gettimeoffset(void) +{ + return 0; +} + +/*IRQ handler for the timer*/ + +static irqreturn_t +w90x900_timer_interrupt(int irq, void *dev_id) +{ + timer_tick(); + __raw_writel(0x01, REG_TISR); /* clear TIF0 */ + return IRQ_HANDLED; +} + +static struct irqaction w90x900_timer_irq = { + .name = "w90x900 Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = w90x900_timer_interrupt, +}; + +/*Set up timer reg.*/ + +static void w90x900_timer_setup(void) +{ + __raw_writel(0, REG_TCSR0); + __raw_writel(0, REG_TCSR1); + __raw_writel(0, REG_TCSR2); + __raw_writel(0, REG_TCSR3); + __raw_writel(0, REG_TCSR4); + __raw_writel(0x1F, REG_TISR); + __raw_writel(15000000/(100 * 100), REG_TICR0); + __raw_writel(0x68000063, REG_TCSR0); +} + +static void __init w90x900_timer_init(void) +{ + w90x900_timer_setup(); + setup_irq(IRQ_TIMER0, &w90x900_timer_irq); +} + +struct sys_timer w90x900_timer = { + .init = w90x900_timer_init, + .offset = w90x900_gettimeoffset, + .resume = w90x900_timer_setup +}; diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c new file mode 100644 index 000000000000..aa783bc94310 --- /dev/null +++ b/arch/arm/mach-w90x900/w90p910.c @@ -0,0 +1,134 @@ +/* + * linux/arch/arm/mach-w90x900/w90p910.c + * + * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * W90P910 cpu support + * + * 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 <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-serial.h> + +#include "cpu.h" + +/*W90P910 has five uarts*/ + +#define MAX_UART_COUNT 5 +static int uart_count; +static struct platform_device *uart_devs[MAX_UART_COUNT-1]; + +/* Initial IO mappings */ + +static struct map_desc w90p910_iodesc[] __initdata = { + IODESC_ENT(IRQ), + IODESC_ENT(GCR), + IODESC_ENT(UART), + IODESC_ENT(TIMER), + IODESC_ENT(EBI), + /*IODESC_ENT(LCD),*/ +}; + +/*Init the dev resource*/ + +static W90X900_RES(UART0); +static W90X900_RES(UART1); +static W90X900_RES(UART2); +static W90X900_RES(UART3); +static W90X900_RES(UART4); +static W90X900_DEVICE(uart0, UART0, 0, "w90x900-uart"); +static W90X900_DEVICE(uart1, UART1, 1, "w90x900-uart"); +static W90X900_DEVICE(uart2, UART2, 2, "w90x900-uart"); +static W90X900_DEVICE(uart3, UART3, 3, "w90x900-uart"); +static W90X900_DEVICE(uart4, UART4, 4, "w90x900-uart"); + +static struct platform_device *uart_devices[] __initdata = { + &w90x900_uart0, + &w90x900_uart1, + &w90x900_uart2, + &w90x900_uart3, + &w90x900_uart4 +}; + +/*Init W90P910 uart device*/ + +void __init w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no) +{ + struct platform_device *platdev; + int uart, uartdev; + + /*By min() to judge count of uart be used indeed*/ + + uartdev = ARRAY_SIZE(uart_devices); + no = min(uartdev, no); + + for (uart = 0; uart < no; uart++, cfg++) { + if (cfg->hwport != uart) + printk(KERN_ERR "w90x900_uartcfg[%d] error\n", uart); + platdev = uart_devices[cfg->hwport]; + uart_devs[uart] = platdev; + platdev->dev.platform_data = cfg; + } + uart_count = uart; +} + +/*Init W90P910 evb io*/ + +void __init w90p910_map_io(struct map_desc *mach_desc, int mach_size) +{ + unsigned long idcode = 0x0; + + iotable_init(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); + + idcode = __raw_readl(W90X900PDID); + if (idcode != W90P910_CPUID) + printk(KERN_ERR "CPU type 0x%08lx is not W90P910\n", idcode); +} + +/*Init W90P910 clock*/ + +void __init w90p910_init_clocks(int xtal) +{ +} + +static int __init w90p910_init_cpu(void) +{ + return 0; +} + +static int __init w90x900_arch_init(void) +{ + int ret; + + ret = w90p910_init_cpu(); + if (ret != 0) + return ret; + + return platform_add_devices(uart_devs, uart_count); + +} +arch_initcall(w90x900_arch_init); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ab5f7a21350b..d490f3773c01 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -10,8 +10,7 @@ config CPU_32 # ARM610 config CPU_ARM610 - bool "Support ARM610 processor" - depends on ARCH_RPC + bool "Support ARM610 processor" if ARCH_RPC select CPU_32v3 select CPU_CACHE_V3 select CPU_CACHE_VIVT @@ -43,8 +42,7 @@ config CPU_ARM7TDMI # ARM710 config CPU_ARM710 - bool "Support ARM710 processor" if !ARCH_CLPS7500 && ARCH_RPC - default y if ARCH_CLPS7500 + bool "Support ARM710 processor" if ARCH_RPC select CPU_32v3 select CPU_CACHE_V3 select CPU_CACHE_VIVT @@ -63,8 +61,7 @@ config CPU_ARM710 # ARM720T config CPU_ARM720T - bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR - default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X + bool "Support ARM720T processor" if ARCH_INTEGRATOR select CPU_32v4T select CPU_ABRT_LV4T select CPU_PABRT_NOIFAR @@ -114,9 +111,7 @@ config CPU_ARM9TDMI # ARM920T config CPU_ARM920T - bool "Support ARM920T processor" - depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 - default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200 + bool "Support ARM920T processor" if ARCH_INTEGRATOR select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -138,8 +133,6 @@ config CPU_ARM920T # ARM922T config CPU_ARM922T bool "Support ARM922T processor" if ARCH_INTEGRATOR - depends on ARCH_LH7A40X || ARCH_INTEGRATOR || ARCH_KS8695 - default y if ARCH_LH7A40X || ARCH_KS8695 select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -159,8 +152,6 @@ config CPU_ARM922T # ARM925T config CPU_ARM925T bool "Support ARM925T processor" if ARCH_OMAP1 - depends on ARCH_OMAP15XX - default y if ARCH_OMAP15XX select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -179,22 +170,7 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T - bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || \ - MACH_VERSATILE_AB || ARCH_OMAP730 || \ - ARCH_OMAP16XX || MACH_REALVIEW_EB || \ - ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \ - ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || \ - ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || \ - ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \ - ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || \ - ARCH_OMAP730 || ARCH_OMAP16XX || \ - ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \ - ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || \ - ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || \ - ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \ - ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2 + bool "Support ARM926T processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_PABRT_NOIFAR @@ -247,8 +223,7 @@ config CPU_ARM946E # ARM1020 - needs validating config CPU_ARM1020 - bool "Support ARM1020T (rev 0) processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1020T (rev 0) processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -266,8 +241,7 @@ config CPU_ARM1020 # ARM1020E - needs validating config CPU_ARM1020E - bool "Support ARM1020E processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1020E processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -280,8 +254,7 @@ config CPU_ARM1020E # ARM1022E config CPU_ARM1022 - bool "Support ARM1022E processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1022E processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -299,8 +272,7 @@ config CPU_ARM1022 # ARM1026EJ-S config CPU_ARM1026 - bool "Support ARM1026EJ-S processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1026EJ-S processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10 select CPU_PABRT_NOIFAR @@ -317,8 +289,7 @@ config CPU_ARM1026 # SA110 config CPU_SA110 - bool "Support StrongARM(R) SA-110 processor" if !ARCH_EBSA110 && !FOOTBRIDGE && !ARCH_TBOX && !ARCH_SHARK && !ARCH_NEXUSPCI && ARCH_RPC - default y if ARCH_EBSA110 || FOOTBRIDGE || ARCH_TBOX || ARCH_SHARK || ARCH_NEXUSPCI + bool "Support StrongARM(R) SA-110 processor" if ARCH_RPC select CPU_32v3 if ARCH_RPC select CPU_32v4 if !ARCH_RPC select CPU_ABRT_EV4 @@ -340,8 +311,6 @@ config CPU_SA110 # SA1100 config CPU_SA1100 bool - depends on ARCH_SA1100 - default y select CPU_32v4 select CPU_ABRT_EV4 select CPU_PABRT_NOIFAR @@ -353,8 +322,6 @@ config CPU_SA1100 # XScale config CPU_XSCALE bool - depends on ARCH_IOP32X || ARCH_IOP33X || PXA25x || PXA27x || ARCH_IXP4XX || ARCH_IXP2000 - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -365,8 +332,6 @@ config CPU_XSCALE # XScale Core Version 3 config CPU_XSC3 bool - depends on ARCH_IXP23XX || ARCH_IOP13XX || PXA3xx - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -378,8 +343,6 @@ config CPU_XSC3 # Feroceon config CPU_FEROCEON bool - depends on ARCH_ORION5X || ARCH_LOKI || ARCH_KIRKWOOD || ARCH_MV78XX0 - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -399,10 +362,7 @@ config CPU_FEROCEON_OLD_ID # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 - default y if ARCH_MX3 - default y if ARCH_MSM + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v6 select CPU_ABRT_EV6 select CPU_PABRT_NOIFAR @@ -427,8 +387,7 @@ config CPU_32v6K # ARMv7 config CPU_V7 - bool "Support ARM V7 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP3 + bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v6K select CPU_32v7 select CPU_ABRT_EV7 @@ -745,7 +704,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" - depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 + depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP default y select OUTER_CACHE help diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 2d5884ce0435..3a398befed41 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -17,6 +17,7 @@ #include <linux/string.h> #include <linux/proc_fs.h> #include <linux/init.h> +#include <linux/sched.h> #include <linux/uaccess.h> #include <asm/unaligned.h> diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index 3b3639eb7ca5..8a4abebc478a 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -9,7 +9,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index 5786adf10040..3668611cb400 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -9,7 +9,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 51a9b0b273b6..c54fa2cc40e6 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -13,7 +13,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index d19c2bec2b1f..be93ff02a98d 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -26,6 +26,7 @@ * - mm - mm_struct describing address space */ ENTRY(v7_flush_dcache_all) + dmb @ ensure ordering with previous memory accesses mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr mov r3, r3, lsr #23 @ left align loc bit field @@ -64,6 +65,7 @@ skip: finished: mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb isb mov pc, lr ENDPROC(v7_flush_dcache_all) diff --git a/arch/arm/mm/copypage-feroceon.S b/arch/arm/mm/copypage-feroceon.S deleted file mode 100644 index 7eb0d320d240..000000000000 --- a/arch/arm/mm/copypage-feroceon.S +++ /dev/null @@ -1,95 +0,0 @@ -/* - * linux/arch/arm/lib/copypage-feroceon.S - * - * Copyright (C) 2008 Marvell Semiconductors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This handles copy_user_page and clear_user_page on Feroceon - * more optimally than the generic implementations. - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - - .text - .align 5 - -ENTRY(feroceon_copy_user_page) - stmfd sp!, {r4-r9, lr} - mov ip, #PAGE_SZ -1: mov lr, r1 - ldmia r1!, {r2 - r9} - pld [lr, #32] - pld [lr, #64] - pld [lr, #96] - pld [lr, #128] - pld [lr, #160] - pld [lr, #192] - pld [lr, #224] - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - subs ip, ip, #(32 * 8) - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - bne 1b - mcr p15, 0, ip, c7, c10, 4 @ drain WB - ldmfd sp!, {r4-r9, pc} - - .align 5 - -ENTRY(feroceon_clear_user_page) - stmfd sp!, {r4-r7, lr} - mov r1, #PAGE_SZ/32 - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov ip, #0 - mov lr, #0 -1: stmia r0, {r2-r7, ip, lr} - subs r1, r1, #1 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - bne 1b - mcr p15, 0, r1, c7, c10, 4 @ drain WB - ldmfd sp!, {r4-r7, pc} - - __INITDATA - - .type feroceon_user_fns, #object -ENTRY(feroceon_user_fns) - .long feroceon_clear_user_page - .long feroceon_copy_user_page - .size feroceon_user_fns, . - feroceon_user_fns diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c new file mode 100644 index 000000000000..c3ba6a94da0c --- /dev/null +++ b/arch/arm/mm/copypage-feroceon.c @@ -0,0 +1,111 @@ +/* + * linux/arch/arm/mm/copypage-feroceon.S + * + * Copyright (C) 2008 Marvell Semiconductors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This handles copy_user_highpage and clear_user_page on Feroceon + * more optimally than the generic implementations. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +static void __attribute__((naked)) +feroceon_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4-r9, lr} \n\ + mov ip, %0 \n\ +1: mov lr, r1 \n\ + ldmia r1!, {r2 - r9} \n\ + pld [lr, #32] \n\ + pld [lr, #64] \n\ + pld [lr, #96] \n\ + pld [lr, #128] \n\ + pld [lr, #160] \n\ + pld [lr, #192] \n\ + pld [lr, #224] \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + subs ip, ip, #(32 * 8) \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + bne 1b \n\ + mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\ + ldmfd sp!, {r4-r9, pc}" + : + : "I" (PAGE_SIZE)); +} + +void feroceon_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + feroceon_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile ("\ + mov r1, %2 \n\ + mov r2, #0 \n\ + mov r3, #0 \n\ + mov r4, #0 \n\ + mov r5, #0 \n\ + mov r6, #0 \n\ + mov r7, #0 \n\ + mov ip, #0 \n\ + mov lr, #0 \n\ +1: stmia %0, {r2-r7, ip, lr} \n\ + subs r1, r1, #1 \n\ + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ + add %0, %0, #32 \n\ + bne 1b \n\ + mcr p15, 0, r1, c7, c10, 4 @ drain WB" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 32) + : "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns feroceon_user_fns __initdata = { + .cpu_clear_user_highpage = feroceon_clear_user_highpage, + .cpu_copy_user_highpage = feroceon_copy_user_highpage, +}; + diff --git a/arch/arm/mm/copypage-v3.S b/arch/arm/mm/copypage-v3.S deleted file mode 100644 index 2ee394b11bcb..000000000000 --- a/arch/arm/mm/copypage-v3.S +++ /dev/null @@ -1,67 +0,0 @@ -/* - * linux/arch/arm/lib/copypage.S - * - * Copyright (C) 1995-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/assembler.h> -#include <asm/asm-offsets.h> - - .text - .align 5 -/* - * ARMv3 optimised copy_user_page - * - * FIXME: do we need to handle cache stuff... - */ -ENTRY(v3_copy_user_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 -1: stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - ldmfd sp!, {r4, pc} @ 3 - - .align 5 -/* - * ARMv3 optimised clear_user_page - * - * FIXME: do we need to handle cache stuff... - */ -ENTRY(v3_clear_user_page) - str lr, [sp, #-4]! - mov r1, #PAGE_SZ/64 @ 1 - mov r2, #0 @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 -1: stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - subs r1, r1, #1 @ 1 - bne 1b @ 1 - ldr pc, [sp], #4 - - __INITDATA - - .type v3_user_fns, #object -ENTRY(v3_user_fns) - .long v3_clear_user_page - .long v3_copy_user_page - .size v3_user_fns, . - v3_user_fns diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c new file mode 100644 index 000000000000..70ed96c8af8e --- /dev/null +++ b/arch/arm/mm/copypage-v3.c @@ -0,0 +1,81 @@ +/* + * linux/arch/arm/mm/copypage-v3.c + * + * Copyright (C) 1995-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +/* + * ARMv3 optimised copy_user_highpage + * + * FIXME: do we need to handle cache stuff... + */ +static void __attribute__((naked)) +v3_copy_user_page(void *kto, const void *kfrom) +{ + asm("\n\ + stmfd sp!, {r4, lr} @ 2\n\ + mov r2, %2 @ 1\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ +1: stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4\n\ + subs r2, r2, #1 @ 1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmneia %0!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ + ldmfd sp!, {r4, pc} @ 3" + : + : "r" (kfrom), "r" (kto), "I" (PAGE_SIZE / 64)); +} + +void v3_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + v3_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * ARMv3 optimised clear_user_page + * + * FIXME: do we need to handle cache stuff... + */ +void v3_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\n\ + mov r1, %2 @ 1\n\ + mov r2, #0 @ 1\n\ + mov r3, #0 @ 1\n\ + mov ip, #0 @ 1\n\ + mov lr, #0 @ 1\n\ +1: stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + subs r1, r1, #1 @ 1\n\ + bne 1b @ 1" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns v3_user_fns __initdata = { + .cpu_clear_user_highpage = v3_clear_user_highpage, + .cpu_copy_user_highpage = v3_copy_user_highpage, +}; diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 8d33e2549344..bdb5fd983b15 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -15,8 +15,8 @@ */ #include <linux/init.h> #include <linux/mm.h> +#include <linux/highmem.h> -#include <asm/page.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> @@ -33,7 +33,7 @@ static DEFINE_SPINLOCK(minicache_lock); /* - * ARMv4 mini-dcache optimised copy_user_page + * ARMv4 mini-dcache optimised copy_user_highpage * * We flush the destination cache lines just before we write the data into the * corresponding address. Since the Dcache is read-allocate, this removes the @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock); * * Note: We rely on all ARMv4 processors implementing the "invalidate D line" * instruction. If your processor does not supply this, you have to write your - * own copy_user_page that does the right thing. + * own copy_user_highpage that does the right thing. */ static void __attribute__((naked)) mc_copy_user_page(void *from, void *to) @@ -68,50 +68,53 @@ mc_copy_user_page(void *from, void *to) : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); } -void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) +void v4_mc_copy_user_highpage(struct page *from, struct page *to, + unsigned long vaddr) { - struct page *page = virt_to_page(kfrom); + void *kto = kmap_atomic(to, KM_USER1); - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - __flush_dcache_page(page_mapping(page), page); + if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + __flush_dcache_page(page_mapping(from), from); spin_lock(&minicache_lock); - set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0); + set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); flush_tlb_kernel_page(0xffff8000); mc_copy_user_page((void *)0xffff8000, kto); spin_unlock(&minicache_lock); + + kunmap_atomic(kto, KM_USER1); } /* * ARMv4 optimised clear_user_page */ -void __attribute__((naked)) -v4_mc_clear_user_page(void *kaddr, unsigned long vaddr) +void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr) { - asm volatile( - "str lr, [sp, #-4]!\n\ - mov r1, %0 @ 1\n\ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\ + mov r1, %2 @ 1\n\ mov r2, #0 @ 1\n\ mov r3, #0 @ 1\n\ mov ip, #0 @ 1\n\ mov lr, #0 @ 1\n\ -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ +1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ subs r1, r1, #1 @ 1\n\ - bne 1b @ 1\n\ - ldr pc, [sp], #4" - : - : "I" (PAGE_SIZE / 64)); + bne 1b @ 1" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); } struct cpu_user_fns v4_mc_user_fns __initdata = { - .cpu_clear_user_page = v4_mc_clear_user_page, - .cpu_copy_user_page = v4_mc_copy_user_page, + .cpu_clear_user_highpage = v4_mc_clear_user_highpage, + .cpu_copy_user_highpage = v4_mc_copy_user_highpage, }; diff --git a/arch/arm/mm/copypage-v4wb.S b/arch/arm/mm/copypage-v4wb.S deleted file mode 100644 index 83117354b1cd..000000000000 --- a/arch/arm/mm/copypage-v4wb.S +++ /dev/null @@ -1,79 +0,0 @@ -/* - * linux/arch/arm/lib/copypage.S - * - * Copyright (C) 1995-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - - .text - .align 5 -/* - * ARMv4 optimised copy_user_page - * - * We flush the destination cache lines just before we write the data into the - * corresponding address. Since the Dcache is read-allocate, this removes the - * Dcache aliasing issue. The writes will be forwarded to the write buffer, - * and merged as appropriate. - * - * Note: We rely on all ARMv4 processors implementing the "invalidate D line" - * instruction. If your processor does not supply this, you have to write your - * own copy_user_page that does the right thing. - */ -ENTRY(v4wb_copy_user_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 - ldmia r1!, {r3, r4, ip, lr} @ 4 -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB - ldmfd sp!, {r4, pc} @ 3 - - .align 5 -/* - * ARMv4 optimised clear_user_page - * - * Same story as above. - */ -ENTRY(v4wb_clear_user_page) - str lr, [sp, #-4]! - mov r1, #PAGE_SZ/64 @ 1 - mov r2, #0 @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - subs r1, r1, #1 @ 1 - bne 1b @ 1 - mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB - ldr pc, [sp], #4 - - __INITDATA - - .type v4wb_user_fns, #object -ENTRY(v4wb_user_fns) - .long v4wb_clear_user_page - .long v4wb_copy_user_page - .size v4wb_user_fns, . - v4wb_user_fns diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c new file mode 100644 index 000000000000..3ec93dab7656 --- /dev/null +++ b/arch/arm/mm/copypage-v4wb.c @@ -0,0 +1,94 @@ +/* + * linux/arch/arm/mm/copypage-v4wb.c + * + * Copyright (C) 1995-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +/* + * ARMv4 optimised copy_user_highpage + * + * We flush the destination cache lines just before we write the data into the + * corresponding address. Since the Dcache is read-allocate, this removes the + * Dcache aliasing issue. The writes will be forwarded to the write buffer, + * and merged as appropriate. + * + * Note: We rely on all ARMv4 processors implementing the "invalidate D line" + * instruction. If your processor does not supply this, you have to write your + * own copy_user_highpage that does the right thing. + */ +static void __attribute__((naked)) +v4wb_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4, lr} @ 2\n\ + mov r2, %0 @ 1\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + subs r2, r2, #1 @ 1\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ + mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\ + ldmfd sp!, {r4, pc} @ 3" + : + : "I" (PAGE_SIZE / 64)); +} + +void v4wb_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + v4wb_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * ARMv4 optimised clear_user_page + * + * Same story as above. + */ +void v4wb_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\ + mov r1, %2 @ 1\n\ + mov r2, #0 @ 1\n\ + mov r3, #0 @ 1\n\ + mov ip, #0 @ 1\n\ + mov lr, #0 @ 1\n\ +1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + subs r1, r1, #1 @ 1\n\ + bne 1b @ 1\n\ + mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns v4wb_user_fns __initdata = { + .cpu_clear_user_highpage = v4wb_clear_user_highpage, + .cpu_copy_user_highpage = v4wb_copy_user_highpage, +}; diff --git a/arch/arm/mm/copypage-v4wt.S b/arch/arm/mm/copypage-v4wt.S deleted file mode 100644 index e1f2af28d549..000000000000 --- a/arch/arm/mm/copypage-v4wt.S +++ /dev/null @@ -1,73 +0,0 @@ -/* - * linux/arch/arm/lib/copypage-v4.S - * - * Copyright (C) 1995-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - * - * This is for CPUs with a writethrough cache and 'flush ID cache' is - * the only supported cache operation. - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - - .text - .align 5 -/* - * ARMv4 optimised copy_user_page - * - * Since we have writethrough caches, we don't have to worry about - * dirty data in the cache. However, we do have to ensure that - * subsequent reads are up to date. - */ -ENTRY(v4wt_copy_user_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 - ldmia r1!, {r3, r4, ip, lr} @ 4 -1: stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - mcr p15, 0, r2, c7, c7, 0 @ flush ID cache - ldmfd sp!, {r4, pc} @ 3 - - .align 5 -/* - * ARMv4 optimised clear_user_page - * - * Same story as above. - */ -ENTRY(v4wt_clear_user_page) - str lr, [sp, #-4]! - mov r1, #PAGE_SZ/64 @ 1 - mov r2, #0 @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 -1: stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - subs r1, r1, #1 @ 1 - bne 1b @ 1 - mcr p15, 0, r2, c7, c7, 0 @ flush ID cache - ldr pc, [sp], #4 - - __INITDATA - - .type v4wt_user_fns, #object -ENTRY(v4wt_user_fns) - .long v4wt_clear_user_page - .long v4wt_copy_user_page - .size v4wt_user_fns, . - v4wt_user_fns diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c new file mode 100644 index 000000000000..0f1188efae45 --- /dev/null +++ b/arch/arm/mm/copypage-v4wt.c @@ -0,0 +1,88 @@ +/* + * linux/arch/arm/mm/copypage-v4wt.S + * + * Copyright (C) 1995-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This is for CPUs with a writethrough cache and 'flush ID cache' is + * the only supported cache operation. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +/* + * ARMv4 optimised copy_user_highpage + * + * Since we have writethrough caches, we don't have to worry about + * dirty data in the cache. However, we do have to ensure that + * subsequent reads are up to date. + */ +static void __attribute__((naked)) +v4wt_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4, lr} @ 2\n\ + mov r2, %0 @ 1\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +1: stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + subs r2, r2, #1 @ 1\n\ + stmia r0!, {r3, r4, ip, lr} @ 4\n\ + ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ + mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\ + ldmfd sp!, {r4, pc} @ 3" + : + : "I" (PAGE_SIZE / 64)); +} + +void v4wt_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + v4wt_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * ARMv4 optimised clear_user_page + * + * Same story as above. + */ +void v4wt_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\ + mov r1, %2 @ 1\n\ + mov r2, #0 @ 1\n\ + mov r3, #0 @ 1\n\ + mov ip, #0 @ 1\n\ + mov lr, #0 @ 1\n\ +1: stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + subs r1, r1, #1 @ 1\n\ + bne 1b @ 1\n\ + mcr p15, 0, r2, c7, c7, 0 @ flush ID cache" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns v4wt_user_fns __initdata = { + .cpu_clear_user_highpage = v4wt_clear_user_highpage, + .cpu_copy_user_highpage = v4wt_copy_user_highpage, +}; diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 0e21c0767580..4127a7bddfe5 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -10,8 +10,8 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/mm.h> +#include <linux/highmem.h> -#include <asm/page.h> #include <asm/pgtable.h> #include <asm/shmparam.h> #include <asm/tlbflush.h> @@ -33,41 +33,56 @@ static DEFINE_SPINLOCK(v6_lock); * Copy the user page. No aliasing to deal with so we can just * attack the kernel's existing mapping of these pages. */ -static void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr) +static void v6_copy_user_highpage_nonaliasing(struct page *to, + struct page *from, unsigned long vaddr) { + void *kto, *kfrom; + + kfrom = kmap_atomic(from, KM_USER0); + kto = kmap_atomic(to, KM_USER1); copy_page(kto, kfrom); + kunmap_atomic(kto, KM_USER1); + kunmap_atomic(kfrom, KM_USER0); } /* * Clear the user page. No aliasing to deal with so we can just * attack the kernel's existing mapping of this page. */ -static void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) +static void v6_clear_user_highpage_nonaliasing(struct page *page, unsigned long vaddr) { + void *kaddr = kmap_atomic(page, KM_USER0); clear_page(kaddr); + kunmap_atomic(kaddr, KM_USER0); } /* - * Copy the page, taking account of the cache colour. + * Discard data in the kernel mapping for the new page. + * FIXME: needs this MCRR to be supported. */ -static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) +static void discard_old_kernel_data(void *kto) { - unsigned int offset = CACHE_COLOUR(vaddr); - unsigned long from, to; - struct page *page = virt_to_page(kfrom); - - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - __flush_dcache_page(page_mapping(page), page); - - /* - * Discard data in the kernel mapping for the new page. - * FIXME: needs this MCRR to be supported. - */ __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" : : "r" (kto), "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES) : "cc"); +} + +/* + * Copy the page, taking account of the cache colour. + */ +static void v6_copy_user_highpage_aliasing(struct page *to, + struct page *from, unsigned long vaddr) +{ + unsigned int offset = CACHE_COLOUR(vaddr); + unsigned long kfrom, kto; + + if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + __flush_dcache_page(page_mapping(from), from); + + /* FIXME: not highmem safe */ + discard_old_kernel_data(page_address(to)); /* * Now copy the page using the same cache colour as the @@ -75,16 +90,16 @@ static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned lo */ spin_lock(&v6_lock); - set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, PAGE_KERNEL), 0); - set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, PAGE_KERNEL), 0); + set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0); + set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0); - from = from_address + (offset << PAGE_SHIFT); - to = to_address + (offset << PAGE_SHIFT); + kfrom = from_address + (offset << PAGE_SHIFT); + kto = to_address + (offset << PAGE_SHIFT); - flush_tlb_kernel_page(from); - flush_tlb_kernel_page(to); + flush_tlb_kernel_page(kfrom); + flush_tlb_kernel_page(kto); - copy_page((void *)to, (void *)from); + copy_page((void *)kto, (void *)kfrom); spin_unlock(&v6_lock); } @@ -94,20 +109,13 @@ static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned lo * so remap the kernel page into the same cache colour as the user * page. */ -static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) +static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr) { unsigned int offset = CACHE_COLOUR(vaddr); unsigned long to = to_address + (offset << PAGE_SHIFT); - /* - * Discard data in the kernel mapping for the new page - * FIXME: needs this MCRR to be supported. - */ - __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" - : - : "r" (kaddr), - "r" ((unsigned long)kaddr + PAGE_SIZE - L1_CACHE_BYTES) - : "cc"); + /* FIXME: not highmem safe */ + discard_old_kernel_data(page_address(page)); /* * Now clear the page using the same cache colour as @@ -115,7 +123,7 @@ static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) */ spin_lock(&v6_lock); - set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, PAGE_KERNEL), 0); + set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0); flush_tlb_kernel_page(to); clear_page((void *)to); @@ -123,15 +131,15 @@ static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) } struct cpu_user_fns v6_user_fns __initdata = { - .cpu_clear_user_page = v6_clear_user_page_nonaliasing, - .cpu_copy_user_page = v6_copy_user_page_nonaliasing, + .cpu_clear_user_highpage = v6_clear_user_highpage_nonaliasing, + .cpu_copy_user_highpage = v6_copy_user_highpage_nonaliasing, }; static int __init v6_userpage_init(void) { if (cache_is_vipt_aliasing()) { - cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing; - cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing; + cpu_user.cpu_clear_user_highpage = v6_clear_user_highpage_aliasing; + cpu_user.cpu_copy_user_highpage = v6_copy_user_highpage_aliasing; } return 0; diff --git a/arch/arm/mm/copypage-xsc3.S b/arch/arm/mm/copypage-xsc3.S deleted file mode 100644 index 9a2cb4332b4c..000000000000 --- a/arch/arm/mm/copypage-xsc3.S +++ /dev/null @@ -1,97 +0,0 @@ -/* - * linux/arch/arm/lib/copypage-xsc3.S - * - * Copyright (C) 2004 Intel Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Adapted for 3rd gen XScale core, no more mini-dcache - * Author: Matt Gilbert (matthew.m.gilbert@intel.com) - */ - -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - -/* - * General note: - * We don't really want write-allocate cache behaviour for these functions - * since that will just eat through 8K of the cache. - */ - - .text - .align 5 -/* - * XSC3 optimised copy_user_page - * r0 = destination - * r1 = source - * r2 = virtual user address of ultimate destination page - * - * The source page may have some clean entries in the cache already, but we - * can safely ignore them - break_cow() will flush them out of the cache - * if we eventually end up using our copied page. - * - */ -ENTRY(xsc3_mc_copy_user_page) - stmfd sp!, {r4, r5, lr} - mov lr, #PAGE_SZ/64-1 - - pld [r1, #0] - pld [r1, #32] -1: pld [r1, #64] - pld [r1, #96] - -2: ldrd r2, [r1], #8 - mov ip, r0 - ldrd r4, [r1], #8 - mcr p15, 0, ip, c7, c6, 1 @ invalidate - strd r2, [r0], #8 - ldrd r2, [r1], #8 - strd r4, [r0], #8 - ldrd r4, [r1], #8 - strd r2, [r0], #8 - strd r4, [r0], #8 - ldrd r2, [r1], #8 - mov ip, r0 - ldrd r4, [r1], #8 - mcr p15, 0, ip, c7, c6, 1 @ invalidate - strd r2, [r0], #8 - ldrd r2, [r1], #8 - subs lr, lr, #1 - strd r4, [r0], #8 - ldrd r4, [r1], #8 - strd r2, [r0], #8 - strd r4, [r0], #8 - bgt 1b - beq 2b - - ldmfd sp!, {r4, r5, pc} - - .align 5 -/* - * XScale optimised clear_user_page - * r0 = destination - * r1 = virtual user address of ultimate destination page - */ -ENTRY(xsc3_mc_clear_user_page) - mov r1, #PAGE_SZ/32 - mov r2, #0 - mov r3, #0 -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate line - strd r2, [r0], #8 - strd r2, [r0], #8 - strd r2, [r0], #8 - strd r2, [r0], #8 - subs r1, r1, #1 - bne 1b - mov pc, lr - - __INITDATA - - .type xsc3_mc_user_fns, #object -ENTRY(xsc3_mc_user_fns) - .long xsc3_mc_clear_user_page - .long xsc3_mc_copy_user_page - .size xsc3_mc_user_fns, . - xsc3_mc_user_fns diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c new file mode 100644 index 000000000000..39a994542cad --- /dev/null +++ b/arch/arm/mm/copypage-xsc3.c @@ -0,0 +1,113 @@ +/* + * linux/arch/arm/mm/copypage-xsc3.S + * + * Copyright (C) 2004 Intel Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Adapted for 3rd gen XScale core, no more mini-dcache + * Author: Matt Gilbert (matthew.m.gilbert@intel.com) + */ +#include <linux/init.h> +#include <linux/highmem.h> + +/* + * General note: + * We don't really want write-allocate cache behaviour for these functions + * since that will just eat through 8K of the cache. + */ + +/* + * XSC3 optimised copy_user_highpage + * r0 = destination + * r1 = source + * + * The source page may have some clean entries in the cache already, but we + * can safely ignore them - break_cow() will flush them out of the cache + * if we eventually end up using our copied page. + * + */ +static void __attribute__((naked)) +xsc3_mc_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4, r5, lr} \n\ + mov lr, %0 \n\ + \n\ + pld [r1, #0] \n\ + pld [r1, #32] \n\ +1: pld [r1, #64] \n\ + pld [r1, #96] \n\ + \n\ +2: ldrd r2, [r1], #8 \n\ + mov ip, r0 \n\ + ldrd r4, [r1], #8 \n\ + mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ + strd r2, [r0], #8 \n\ + ldrd r2, [r1], #8 \n\ + strd r4, [r0], #8 \n\ + ldrd r4, [r1], #8 \n\ + strd r2, [r0], #8 \n\ + strd r4, [r0], #8 \n\ + ldrd r2, [r1], #8 \n\ + mov ip, r0 \n\ + ldrd r4, [r1], #8 \n\ + mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ + strd r2, [r0], #8 \n\ + ldrd r2, [r1], #8 \n\ + subs lr, lr, #1 \n\ + strd r4, [r0], #8 \n\ + ldrd r4, [r1], #8 \n\ + strd r2, [r0], #8 \n\ + strd r4, [r0], #8 \n\ + bgt 1b \n\ + beq 2b \n\ + \n\ + ldmfd sp!, {r4, r5, pc}" + : + : "I" (PAGE_SIZE / 64 - 1)); +} + +void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + xsc3_mc_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * XScale optimised clear_user_page + * r0 = destination + * r1 = virtual user address of ultimate destination page + */ +void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile ("\ + mov r1, %2 \n\ + mov r2, #0 \n\ + mov r3, #0 \n\ +1: mcr p15, 0, %0, c7, c6, 1 @ invalidate line\n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ + subs r1, r1, #1 \n\ + bne 1b" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 32) + : "r1", "r2", "r3"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns xsc3_mc_user_fns __initdata = { + .cpu_clear_user_highpage = xsc3_mc_clear_user_highpage, + .cpu_copy_user_highpage = xsc3_mc_copy_user_highpage, +}; diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index bad49331bbf9..d18f2397ee2d 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -15,8 +15,8 @@ */ #include <linux/init.h> #include <linux/mm.h> +#include <linux/highmem.h> -#include <asm/page.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> @@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(minicache_lock); /* - * XScale mini-dcache optimised copy_user_page + * XScale mini-dcache optimised copy_user_highpage * * We flush the destination cache lines just before we write the data into the * corresponding address. Since the Dcache is read-allocate, this removes the @@ -90,48 +90,53 @@ mc_copy_user_page(void *from, void *to) : "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1)); } -void xscale_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) +void xscale_mc_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) { - struct page *page = virt_to_page(kfrom); + void *kto = kmap_atomic(to, KM_USER1); - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - __flush_dcache_page(page_mapping(page), page); + if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + __flush_dcache_page(page_mapping(from), from); spin_lock(&minicache_lock); - set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0); + set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); flush_tlb_kernel_page(COPYPAGE_MINICACHE); mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); spin_unlock(&minicache_lock); + + kunmap_atomic(kto, KM_USER1); } /* * XScale optimised clear_user_page */ -void __attribute__((naked)) -xscale_mc_clear_user_page(void *kaddr, unsigned long vaddr) +void +xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr) { + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); asm volatile( - "mov r1, %0 \n\ + "mov r1, %2 \n\ mov r2, #0 \n\ mov r3, #0 \n\ -1: mov ip, r0 \n\ - strd r2, [r0], #8 \n\ - strd r2, [r0], #8 \n\ - strd r2, [r0], #8 \n\ - strd r2, [r0], #8 \n\ +1: mov ip, %0 \n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ + strd r2, [%0], #8 \n\ mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ subs r1, r1, #1 \n\ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\ - bne 1b \n\ - mov pc, lr" - : - : "I" (PAGE_SIZE / 32)); + bne 1b" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 32) + : "r1", "r2", "r3", "ip"); + kunmap_atomic(kaddr, KM_USER0); } struct cpu_user_fns xscale_mc_user_fns __initdata = { - .cpu_clear_user_page = xscale_mc_clear_user_page, - .cpu_copy_user_page = xscale_mc_copy_user_page, + .cpu_clear_user_highpage = xscale_mc_clear_user_highpage, + .cpu_copy_user_highpage = xscale_mc_copy_user_highpage, }; diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 22c9530e91e2..0455557a2899 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/kprobes.h> #include <linux/uaccess.h> +#include <linux/page-flags.h> #include <asm/system.h> #include <asm/pgtable.h> @@ -84,13 +85,14 @@ void show_pte(struct mm_struct *mm, unsigned long addr) break; } -#ifndef CONFIG_HIGHMEM /* We must not map this if we have highmem enabled */ + if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT))) + break; + pte = pte_offset_map(pmd, addr); printk(", *pte=%08lx", pte_val(*pte)); printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE])); pte_unmap(pte); -#endif } while(0); printk("\n"); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 82c4b4217989..34df4d9d03a6 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -17,6 +17,7 @@ #include <linux/initrd.h> #include <asm/mach-types.h> +#include <asm/sections.h> #include <asm/setup.h> #include <asm/sizes.h> #include <asm/tlb.h> @@ -64,10 +65,11 @@ static int __init parse_tag_initrd2(const struct tag *tag) __tagtable(ATAG_INITRD2, parse_tag_initrd2); /* - * This is used to pass memory configuration data from paging_init - * to mem_init, and by show_mem() to skip holes in the memory map. + * This keeps memory configuration data used by a couple memory + * initialization functions, as well as show_mem() for the skipping + * of holes in the memory map. It is populated by arm_add_memory(). */ -static struct meminfo meminfo = { 0, }; +struct meminfo meminfo; void show_mem(void) { @@ -128,7 +130,7 @@ find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) { unsigned int start_pfn, i, bootmap_pfn; - start_pfn = PAGE_ALIGN(__pa(&_end)) >> PAGE_SHIFT; + start_pfn = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT; bootmap_pfn = 0; for_each_nodebank(i, mi, node) { @@ -331,13 +333,12 @@ static void __init bootmem_free_node(int node, struct meminfo *mi) free_area_init_node(node, zone_size, start_pfn, zhole_size); } -void __init bootmem_init(struct meminfo *mi) +void __init bootmem_init(void) { + struct meminfo *mi = &meminfo; unsigned long memend_pfn = 0; int node, initrd_node; - memcpy(&meminfo, mi, sizeof(meminfo)); - /* * Locate which node contains the ramdisk image, if any. */ @@ -394,20 +395,22 @@ void __init bootmem_init(struct meminfo *mi) max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET; } -static inline void free_area(unsigned long addr, unsigned long end, char *s) +static inline int free_area(unsigned long pfn, unsigned long end, char *s) { - unsigned int size = (end - addr) >> 10; + unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10); - for (; addr < end; addr += PAGE_SIZE) { - struct page *page = virt_to_page(addr); + for (; pfn < end; pfn++) { + struct page *page = pfn_to_page(pfn); ClearPageReserved(page); init_page_count(page); - free_page(addr); - totalram_pages++; + __free_page(page); + pages++; } if (size && s) printk(KERN_INFO "Freeing %s memory: %dK\n", s, size); + + return pages; } static inline void @@ -478,13 +481,9 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi) */ void __init mem_init(void) { - unsigned int codepages, datapages, initpages; + unsigned int codesize, datasize, initsize; int i, node; - codepages = &_etext - &_text; - datapages = &_end - &__data_start; - initpages = &__init_end - &__init_begin; - #ifndef CONFIG_DISCONTIGMEM max_mapnr = virt_to_page(high_memory) - mem_map; #endif @@ -501,7 +500,8 @@ void __init mem_init(void) #ifdef CONFIG_SA1111 /* now that our DMA memory is actually so designated, we can free it */ - free_area(PAGE_OFFSET, (unsigned long)swapper_pg_dir, NULL); + totalram_pages += free_area(PHYS_PFN_OFFSET, + __phys_to_pfn(__pa(swapper_pg_dir)), NULL); #endif /* @@ -509,18 +509,21 @@ void __init mem_init(void) * real number of pages we have in this system */ printk(KERN_INFO "Memory:"); - num_physpages = 0; for (i = 0; i < meminfo.nr_banks; i++) { num_physpages += bank_pfn_size(&meminfo.bank[i]); printk(" %ldMB", bank_phys_size(&meminfo.bank[i]) >> 20); } - printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); + + codesize = _etext - _text; + datasize = _end - _data; + initsize = __init_end - __init_begin; + printk(KERN_NOTICE "Memory: %luKB available (%dK code, " "%dK data, %dK init)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), - codepages >> 10, datapages >> 10, initpages >> 10); + codesize >> 10, datasize >> 10, initsize >> 10); if (PAGE_SIZE >= 16384 && num_physpages <= 128) { extern int sysctl_overcommit_memory; @@ -535,11 +538,10 @@ void __init mem_init(void) void free_initmem(void) { - if (!machine_is_integrator() && !machine_is_cintegrator()) { - free_area((unsigned long)(&__init_begin), - (unsigned long)(&__init_end), - "init"); - } + if (!machine_is_integrator() && !machine_is_cintegrator()) + totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)), + __phys_to_pfn(__pa(__init_end)), + "init"); } #ifdef CONFIG_BLK_DEV_INITRD @@ -549,7 +551,9 @@ static int keep_initrd; void free_initrd_mem(unsigned long start, unsigned long end) { if (!keep_initrd) - free_area(start, end, "initrd"); + totalram_pages += free_area(__phys_to_pfn(__pa(start)), + __phys_to_pfn(__pa(end)), + "initrd"); } static int __init keepinitrd_setup(char *__unused) diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 5d9f53907b4e..95bbe112965e 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -32,7 +32,5 @@ struct meminfo; struct pglist_data; void __init create_mapping(struct map_desc *md); -void __init bootmem_init(struct meminfo *mi); +void __init bootmem_init(void); void reserve_node_zero(struct pglist_data *pgdat); - -extern void _text, _stext, _etext, __data_start, _end, __init_begin, __init_end; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 7f36c825718d..9b36c5cb5e9f 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -17,6 +17,7 @@ #include <asm/cputype.h> #include <asm/mach-types.h> +#include <asm/sections.h> #include <asm/setup.h> #include <asm/sizes.h> #include <asm/tlb.h> @@ -646,61 +647,79 @@ static void __init early_vmalloc(char **arg) "vmalloc area too small, limiting to %luMB\n", vmalloc_reserve >> 20); } + + if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { + vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); + printk(KERN_WARNING + "vmalloc area is too big, limiting to %luMB\n", + vmalloc_reserve >> 20); + } } __early_param("vmalloc=", early_vmalloc); #define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve) -static int __init check_membank_valid(struct membank *mb) +static void __init sanity_check_meminfo(void) { - /* - * Check whether this memory region has non-zero size or - * invalid node number. - */ - if (mb->size == 0 || mb->node >= MAX_NUMNODES) - return 0; - - /* - * Check whether this memory region would entirely overlap - * the vmalloc area. - */ - if (phys_to_virt(mb->start) >= VMALLOC_MIN) { - printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " - "(vmalloc region overlap).\n", - mb->start, mb->start + mb->size - 1); - return 0; - } - - /* - * Check whether this memory region would partially overlap - * the vmalloc area. - */ - if (phys_to_virt(mb->start + mb->size) < phys_to_virt(mb->start) || - phys_to_virt(mb->start + mb->size) > VMALLOC_MIN) { - unsigned long newsize = VMALLOC_MIN - phys_to_virt(mb->start); - - printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " - "to -%.8lx (vmalloc region overlap).\n", - mb->start, mb->start + mb->size - 1, - mb->start + newsize - 1); - mb->size = newsize; - } + int i, j; - return 1; -} + for (i = 0, j = 0; i < meminfo.nr_banks; i++) { + struct membank *bank = &meminfo.bank[j]; + *bank = meminfo.bank[i]; -static void __init sanity_check_meminfo(struct meminfo *mi) -{ - int i, j; +#ifdef CONFIG_HIGHMEM + /* + * Split those memory banks which are partially overlapping + * the vmalloc area greatly simplifying things later. + */ + if (__va(bank->start) < VMALLOC_MIN && + bank->size > VMALLOC_MIN - __va(bank->start)) { + if (meminfo.nr_banks >= NR_BANKS) { + printk(KERN_CRIT "NR_BANKS too low, " + "ignoring high memory\n"); + } else { + memmove(bank + 1, bank, + (meminfo.nr_banks - i) * sizeof(*bank)); + meminfo.nr_banks++; + i++; + bank[1].size -= VMALLOC_MIN - __va(bank->start); + bank[1].start = __pa(VMALLOC_MIN - 1) + 1; + j++; + } + bank->size = VMALLOC_MIN - __va(bank->start); + } +#else + /* + * Check whether this memory bank would entirely overlap + * the vmalloc area. + */ + if (__va(bank->start) >= VMALLOC_MIN) { + printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " + "(vmalloc region overlap).\n", + bank->start, bank->start + bank->size - 1); + continue; + } - for (i = 0, j = 0; i < mi->nr_banks; i++) { - if (check_membank_valid(&mi->bank[i])) - mi->bank[j++] = mi->bank[i]; + /* + * Check whether this memory bank would partially overlap + * the vmalloc area. + */ + if (__va(bank->start + bank->size) > VMALLOC_MIN || + __va(bank->start + bank->size) < __va(bank->start)) { + unsigned long newsize = VMALLOC_MIN - __va(bank->start); + printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " + "to -%.8lx (vmalloc region overlap).\n", + bank->start, bank->start + bank->size - 1, + bank->start + newsize - 1); + bank->size = newsize; + } +#endif + j++; } - mi->nr_banks = j; + meminfo.nr_banks = j; } -static inline void prepare_page_table(struct meminfo *mi) +static inline void prepare_page_table(void) { unsigned long addr; @@ -712,7 +731,7 @@ static inline void prepare_page_table(struct meminfo *mi) #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ - addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK; + addr = ((unsigned long)_etext + PGDIR_SIZE - 1) & PGDIR_MASK; #endif for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE) pmd_clear(pmd_off_k(addr)); @@ -721,7 +740,7 @@ static inline void prepare_page_table(struct meminfo *mi) * Clear out all the kernel space mappings, except for the first * memory bank, up to the end of the vmalloc region. */ - for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size); + for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); addr < VMALLOC_END; addr += PGDIR_SIZE) pmd_clear(pmd_off_k(addr)); } @@ -738,10 +757,10 @@ void __init reserve_node_zero(pg_data_t *pgdat) * Note that this can only be in node 0. */ #ifdef CONFIG_XIP_KERNEL - reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start, + reserve_bootmem_node(pgdat, __pa(_data), _end - _data, BOOTMEM_DEFAULT); #else - reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext, + reserve_bootmem_node(pgdat, __pa(_stext), _end - _stext, BOOTMEM_DEFAULT); #endif @@ -808,7 +827,6 @@ static void __init devicemaps_init(struct machine_desc *mdesc) * Allocate the vector page early. */ vectors = alloc_bootmem_low_pages(PAGE_SIZE); - BUG_ON(!vectors); for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) pmd_clear(pmd_off_k(addr)); @@ -820,7 +838,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) #ifdef CONFIG_XIP_KERNEL map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); map.virtual = MODULES_VADDR; - map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; + map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; map.type = MT_ROM; create_mapping(&map); #endif @@ -880,23 +898,23 @@ static void __init devicemaps_init(struct machine_desc *mdesc) * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. */ -void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) +void __init paging_init(struct machine_desc *mdesc) { void *zero_page; build_mem_type_table(); - sanity_check_meminfo(mi); - prepare_page_table(mi); - bootmem_init(mi); + sanity_check_meminfo(); + prepare_page_table(); + bootmem_init(); devicemaps_init(mdesc); top_pmd = pmd_off_k(0xffff0000); /* - * allocate the zero page. Note that we count on this going ok. + * allocate the zero page. Note that this always succeeds and + * returns a zeroed result. */ zero_page = alloc_bootmem_low_pages(PAGE_SIZE); - memzero(zero_page, PAGE_SIZE); empty_zero_page = virt_to_page(zero_page); flush_dcache_page(empty_zero_page); } diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 07b62b238979..ad7bacc693b2 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -10,6 +10,7 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/sections.h> #include <asm/page.h> #include <asm/mach/arch.h> @@ -25,10 +26,10 @@ void __init reserve_node_zero(pg_data_t *pgdat) * Note that this can only be in node 0. */ #ifdef CONFIG_XIP_KERNEL - reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start, + reserve_bootmem_node(pgdat, __pa(_data), _end - _data, BOOTMEM_DEFAULT); #else - reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext, + reserve_bootmem_node(pgdat, __pa(_stext), _end - _stext, BOOTMEM_DEFAULT); #endif @@ -41,27 +42,13 @@ void __init reserve_node_zero(pg_data_t *pgdat) BOOTMEM_DEFAULT); } -static void __init sanity_check_meminfo(struct meminfo *mi) -{ - int i, j; - - for (i = 0, j = 0; i < mi->nr_banks; i++) { - struct membank *mb = &mi->bank[i]; - - if (mb->size != 0 && mb->node < MAX_NUMNODES) - mi->bank[j++] = mi->bank[i]; - } - mi->nr_banks = j; -} - /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. */ -void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) +void __init paging_init(struct machine_desc *mdesc) { - sanity_check_meminfo(mi); - bootmem_init(mi); + bootmem_init(); } /* diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index e0f19ab91163..2690146161ba 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c @@ -31,7 +31,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) if (!new_pgd) goto no_pgd; - memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); + memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); /* * Copy over the kernel and IO PGD entries diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index 2b5ba396e3a6..4ad3bf291ad3 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -33,8 +33,8 @@ EXPORT_SYMBOL(cpu_cache); #ifdef CONFIG_MMU #ifndef MULTI_USER -EXPORT_SYMBOL(__cpu_clear_user_page); -EXPORT_SYMBOL(__cpu_copy_user_page); +EXPORT_SYMBOL(__cpu_clear_user_highpage); +EXPORT_SYMBOL(__cpu_copy_user_highpage); #else EXPORT_SYMBOL(cpu_user); #endif diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 294943b85973..f0cc599facb7 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -71,6 +71,8 @@ ENTRY(cpu_v6_reset) * IRQs are already disabled. */ ENTRY(cpu_v6_do_idle) + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt mov pc, lr diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 4d3c0a73e7fb..d1ebec42521d 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -20,9 +20,17 @@ #define TTB_C (1 << 0) #define TTB_S (1 << 1) +#define TTB_RGN_NC (0 << 3) +#define TTB_RGN_OC_WBWA (1 << 3) #define TTB_RGN_OC_WT (2 << 3) #define TTB_RGN_OC_WB (3 << 3) +#ifndef CONFIG_SMP +#define TTB_FLAGS TTB_C|TTB_RGN_OC_WB @ mark PTWs cacheable, outer WB +#else +#define TTB_FLAGS TTB_C|TTB_S|TTB_RGN_OC_WBWA @ mark PTWs cacheable and shared, outer WBWA +#endif + ENTRY(cpu_v7_proc_init) mov pc, lr ENDPROC(cpu_v7_proc_init) @@ -55,6 +63,7 @@ ENDPROC(cpu_v7_reset) * IRQs are already disabled. */ ENTRY(cpu_v7_do_idle) + dsb @ WFI may enter a low-power mode wfi mov pc, lr ENDPROC(cpu_v7_do_idle) @@ -85,7 +94,7 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_MMU mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id - orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB + orr r0, r0, #TTB_FLAGS mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID isb 1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -162,6 +171,11 @@ cpu_v7_name: * - cache type register is implemented */ __v7_setup: +#ifdef CONFIG_SMP + mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode + orr r0, r0, #(0x1 << 6) + mcr p15, 0, r0, c1, c0, 1 +#endif adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} bl v7_flush_dcache_all @@ -174,8 +188,7 @@ __v7_setup: #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r10, c2, c0, 2 @ TTB control register - orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB - mcr p15, 0, r4, c2, c0, 0 @ load TTB0 + orr r4, r4, #TTB_FLAGS mcr p15, 0, r4, c2, c0, 1 @ load TTB1 mov r10, #0x1f @ domains 0, 1 = manager mcr p15, 0, r10, c3, c0, 0 @ load domain access register diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 8f6cf56c11c0..33515c214b92 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -481,3 +481,28 @@ __xsc3_proc_info: .long xsc3_mc_user_fns .long xsc3_cache_fns .size __xsc3_proc_info, . - __xsc3_proc_info + +/* Note: PXA935 changed its implementor ID from Intel to Marvell */ + + .type __xsc3_pxa935_proc_info,#object +__xsc3_pxa935_proc_info: + .long 0x56056000 + .long 0xffffe000 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __xsc3_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_xsc3_name + .long xsc3_processor_functions + .long v4wbi_tlb_fns + .long xsc3_mc_user_fns + .long xsc3_cache_fns + .size __xsc3_pxa935_proc_info, . - __xsc3_pxa935_proc_info diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index b2a7e3fad117..9cc2b16fdf79 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -6,18 +6,27 @@ choice prompt "MXC/iMX Base Type" default ARCH_MX3 +config ARCH_MX1 + bool "MX1-based" + select CPU_ARM920T + help + This enables support for systems based on the Freescale i.MX1 family + config ARCH_MX2 bool "MX2-based" + select CPU_ARM926T help This enables support for systems based on the Freescale i.MX2 family config ARCH_MX3 bool "MX3-based" + select CPU_V6 help This enables support for systems based on the Freescale i.MX3 family endchoice +source "arch/arm/mach-mx1/Kconfig" source "arch/arm/mach-mx2/Kconfig" source "arch/arm/mach-mx3/Kconfig" diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 067556f7c91f..db74a929179d 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -5,4 +5,5 @@ # Common support obj-y := irq.o clock.o gpio.o time.o devices.o +obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index b296f19fd89a..2905ec758758 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -34,7 +34,6 @@ #include <asm/system.h> #include <asm/irq.h> #include <mach/hardware.h> -#include <asm/dma.h> #include <mach/dma-mx1-mx2.h> #define DMA_DCR 0x00 /* Control Register */ @@ -114,7 +113,7 @@ struct imx_dma_channel { void (*err_handler) (int, void *, int errcode); void (*prog_handler) (int, void *, struct scatterlist *); void *data; - dmamode_t dma_mode; + unsigned int dma_mode; struct scatterlist *sg; unsigned int resbytes; int dma_num; @@ -193,7 +192,7 @@ static inline int imx_dma_sg_next(int channel, struct scatterlist *sg) int imx_dma_setup_single(int channel, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode) + unsigned int dmamode) { struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; @@ -288,7 +287,7 @@ int imx_dma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode) + unsigned int dmamode) { struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; @@ -512,6 +511,7 @@ void imx_dma_disable(int channel) } EXPORT_SYMBOL(imx_dma_disable); +#ifdef CONFIG_ARCH_MX2 static void imx_dma_watchdog(unsigned long chno) { struct imx_dma_channel *imxdma = &imx_dma_channels[chno]; @@ -523,6 +523,7 @@ static void imx_dma_watchdog(unsigned long chno) if (imxdma->err_handler) imxdma->err_handler(chno, imxdma->data, IMX_DMA_ERR_TIMEOUT); } +#endif static irqreturn_t dma_err_handler(int irq, void *dev_id) { @@ -675,7 +676,7 @@ int imx_dma_request(int channel, const char *name) { struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; unsigned long flags; - int ret; + int ret = 0; /* basic sanity checks */ if (!name) @@ -697,6 +698,7 @@ int imx_dma_request(int channel, const char *name) ret = request_irq(MXC_INT_DMACH0 + channel, dma_irq_handler, 0, "DMA", NULL); if (ret) { + local_irq_restore(flags); printk(KERN_CRIT "Can't register IRQ %d for DMA channel %d\n", MXC_INT_DMACH0 + channel, channel); return ret; @@ -713,7 +715,7 @@ int imx_dma_request(int channel, const char *name) imxdma->sg = NULL; local_irq_restore(flags); - return 0; + return ret; } EXPORT_SYMBOL(imx_dma_request); diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index de5c4747453f..ccbd94adc668 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -115,8 +115,8 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) } } -#ifdef CONFIG_ARCH_MX3 -/* MX3 has one interrupt *per* gpio port */ +#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1) +/* MX1 and MX3 has one interrupt *per* gpio port */ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) { u32 irq_stat; @@ -237,7 +237,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) /* its a serious configuration bug when it fails */ BUG_ON( gpiochip_add(&port[i].chip) < 0 ); -#ifdef CONFIG_ARCH_MX3 +#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1) /* setup one handler for each entry */ set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); set_irq_data(port[i].irq, &port[i]); diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h index 61e66dac90ef..8f34a05afc87 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h @@ -15,7 +15,7 @@ #define __ASM_ARCH_MXC_BOARD_MX27ADS_H__ /* external interrupt multiplexer */ -#define MXC_EXP_IO_BASE (MXC_GPIO_BASE + MXC_MAX_GPIO_LINES) +#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) #define MXC_VIRTUAL_INTS_BASE (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES) #define MXC_SDIO1_CARD_IRQ MXC_VIRTUAL_INTS_BASE @@ -28,11 +28,6 @@ /* * MXC UART EVB board level configurations */ - -#define MXC_LL_EXTUART_PADDR (CS4_BASE_ADDR + 0x20000) -#define MXC_LL_EXTUART_VADDR (CS4_BASE_ADDR_VIRT + 0x20000) -#define MXC_LL_EXTUART_16BIT_BUS - #define MXC_LL_UART_PADDR UART1_BASE_ADDR #define MXC_LL_UART_VADDR AIPI_IO_ADDRESS(UART1_BASE_ADDR) diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h index 745b48864f93..451d510d08c3 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h @@ -90,7 +90,7 @@ #define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS) #define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_4) -#define MXC_EXP_IO_BASE (MXC_MAX_INT_LINES + MXC_MAX_GPIO_LINES) +#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE) #define EXPIO_INT_LOW_BAT (MXC_EXP_IO_BASE + 0) diff --git a/arch/arm/plat-mxc/include/mach/board-mx31pdk.h b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h new file mode 100644 index 000000000000..2b6b316d0f51 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h @@ -0,0 +1,19 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. 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 version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_MXC_BOARD_MX31PDK_H__ +#define __ASM_ARCH_MXC_BOARD_MX31PDK_H__ + +/* mandatory for CONFIG_LL_DEBUG */ + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) + +#endif /* __ASM_ARCH_MXC_BOARD_MX31PDK_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S index b9907bebba3b..602768b427e2 100644 --- a/arch/arm/plat-mxc/include/mach/debug-macro.S +++ b/arch/arm/plat-mxc/include/mach/debug-macro.S @@ -28,6 +28,9 @@ #ifdef CONFIG_MACH_PCM038 #include <mach/board-pcm038.h> #endif +#ifdef CONFIG_MACH_MX31_3DS +#include <mach/board-mx31pdk.h> +#endif .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? diff --git a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h index e85fd946116c..b3876cc238ca 100644 --- a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h +++ b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h @@ -22,13 +22,15 @@ * MA 02110-1301, USA. */ -#include <asm/dma.h> - #ifndef __ASM_ARCH_MXC_DMA_H #define __ASM_ARCH_MXC_DMA_H #define IMX_DMA_CHANNELS 16 +#define DMA_MODE_READ 0 +#define DMA_MODE_WRITE 1 +#define DMA_MODE_MASK 1 + #define DMA_BASE IO_ADDRESS(DMA_BASE_ADDR) #define IMX_DMA_MEMSIZE_32 (0 << 4) @@ -54,12 +56,12 @@ imx_dma_config_burstlen(int channel, unsigned int burstlen); int imx_dma_setup_single(int channel, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode); + unsigned int dmamode); int imx_dma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, - unsigned int dev_addr, dmamode_t dmamode); + unsigned int dev_addr, unsigned int dmamode); int imx_dma_setup_handlers(int channel, diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h deleted file mode 100644 index c822d569a05e..000000000000 --- a/arch/arm/plat-mxc/include/mach/dma.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2004-2007 Freescale Semiconductor, Inc. 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 version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_MXC_DMA_H__ -#define __ASM_ARCH_MXC_DMA_H__ - -#endif diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index 11632028f7d1..5f01d60da845 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S @@ -9,6 +9,8 @@ * published by the Free Software Foundation. */ +#include <mach/hardware.h> + #define AVIC_NIMASK 0x04 @ this macro disables fast irq (not implemented) diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index 65eedc0d196f..ea509f1090fb 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -27,8 +27,8 @@ #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep -#define gpio_to_irq(gpio) (MXC_MAX_INT_LINES + (gpio)) -#define irq_to_gpio(irq) ((irq) - MXC_MAX_INT_LINES) +#define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio)) +#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START) struct mxc_gpio_port { void __iomem *base; diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index 3caadeeda701..a612d8bb73c8 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -32,6 +32,10 @@ # endif #endif +#ifdef CONFIG_ARCH_MX1 +# include <mach/mx1.h> +#endif + #include <mach/mxc.h> #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/io.h b/arch/arm/plat-mxc/include/mach/io.h index 5d4cb1196441..b4f2de769466 100644 --- a/arch/arm/plat-mxc/include/mach/io.h +++ b/arch/arm/plat-mxc/include/mach/io.h @@ -25,8 +25,8 @@ __mx3_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) /* Access all peripherals below 0x80000000 as nonshared device * but leave l2cc alone. */ - if ((phys_addr < 0x80000000) && ((phys_addr < L2CC_BASE_ADDR) || - (phys_addr >= L2CC_BASE_ADDR + L2CC_SIZE))) + if ((phys_addr < 0x80000000) && ((phys_addr < 0x30000000) || + (phys_addr >= 0x30000000 + SZ_1M))) mtype = MT_DEVICE_NONSHARED; } @@ -35,8 +35,8 @@ __mx3_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) #endif /* io address mapping macro */ -#define __io(a) ((void __iomem *)(a)) +#define __io(a) __typesafe_io(a) -#define __mem_pci(a) (a) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h index 3d09bfd6c53d..95a383be628e 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h @@ -21,12 +21,6 @@ #include <linux/io.h> -#define MXC_GPIO_ALLOC_MODE_NORMAL 0 -#define MXC_GPIO_ALLOC_MODE_NO_ALLOC 1 -#define MXC_GPIO_ALLOC_MODE_TRY_ALLOC 2 -#define MXC_GPIO_ALLOC_MODE_ALLOC_ONLY 4 -#define MXC_GPIO_ALLOC_MODE_RELEASE 8 - /* * GPIO Module and I/O Multiplexer * x = 0..3 for reg_A, reg_B, reg_C, reg_D @@ -103,7 +97,8 @@ extern void mxc_gpio_mode(int gpio_mode); extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, - int alloc_mode, const char *label); + const char *label); +extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count); /*-------------------------------------------------------------------------*/ @@ -113,9 +108,9 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, * missing on some (many) pins */ #ifdef CONFIG_ARCH_MX1 -#define PA0_AIN_SPI2_CLK (GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 0) +#define PA0_AIN_SPI2_CLK (GPIO_PORTA | GPIO_OUT | 0) #define PA0_AF_ETMTRACESYNC (GPIO_PORTA | GPIO_AF | 0) -#define PA1_AOUT_SPI2_RXD (GPIO_GIUS | GPIO_PORTA | GPIO_IN | 1) +#define PA1_AOUT_SPI2_RXD (GPIO_PORTA | GPIO_IN | 1) #define PA1_PF_TIN (GPIO_PORTA | GPIO_PF | 1) #define PA2_PF_PWM0 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 2) #define PA3_PF_CSI_MCLK (GPIO_PORTA | GPIO_PF | 3) @@ -133,7 +128,7 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PA15_PF_I2C_SDA (GPIO_PORTA | GPIO_OUT | GPIO_PF | 15) #define PA16_PF_I2C_SCL (GPIO_PORTA | GPIO_OUT | GPIO_PF | 16) #define PA17_AF_ETMTRACEPKT4 (GPIO_PORTA | GPIO_AF | 17) -#define PA17_AIN_SPI2_SS (GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 17) +#define PA17_AIN_SPI2_SS (GPIO_PORTA | GPIO_OUT | 17) #define PA18_AF_ETMTRACEPKT5 (GPIO_PORTA | GPIO_AF | 18) #define PA19_AF_ETMTRACEPKT6 (GPIO_PORTA | GPIO_AF | 19) #define PA20_AF_ETMTRACEPKT7 (GPIO_PORTA | GPIO_AF | 20) @@ -201,27 +196,27 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PC15_PF_SPI1_SS (GPIO_PORTC | GPIO_PF | 15) #define PC16_PF_SPI1_MISO (GPIO_PORTC | GPIO_PF | 16) #define PC17_PF_SPI1_MOSI (GPIO_PORTC | GPIO_PF | 17) -#define PC24_BIN_UART3_RI (GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24) -#define PC25_BIN_UART3_DSR (GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25) -#define PC26_AOUT_UART3_DTR (GPIO_GIUS | GPIO_PORTC | GPIO_IN | 26) -#define PC27_BIN_UART3_DCD (GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27) -#define PC28_BIN_UART3_CTS (GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28) -#define PC29_AOUT_UART3_RTS (GPIO_GIUS | GPIO_PORTC | GPIO_IN | 29) -#define PC30_BIN_UART3_TX (GPIO_GIUS | GPIO_PORTC | GPIO_BIN | 30) -#define PC31_AOUT_UART3_RX (GPIO_GIUS | GPIO_PORTC | GPIO_IN | 31) +#define PC24_BIN_UART3_RI (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24) +#define PC25_BIN_UART3_DSR (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25) +#define PC26_AOUT_UART3_DTR (GPIO_PORTC | GPIO_IN | 26) +#define PC27_BIN_UART3_DCD (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27) +#define PC28_BIN_UART3_CTS (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28) +#define PC29_AOUT_UART3_RTS (GPIO_PORTC | GPIO_IN | 29) +#define PC30_BIN_UART3_TX (GPIO_PORTC | GPIO_BIN | 30) +#define PC31_AOUT_UART3_RX (GPIO_PORTC | GPIO_IN | 31) #define PD6_PF_LSCLK (GPIO_PORTD | GPIO_OUT | GPIO_PF | 6) #define PD7_PF_REV (GPIO_PORTD | GPIO_PF | 7) -#define PD7_AF_UART2_DTR (GPIO_GIUS | GPIO_PORTD | GPIO_IN | GPIO_AF | 7) -#define PD7_AIN_SPI2_SCLK (GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 7) +#define PD7_AF_UART2_DTR (GPIO_PORTD | GPIO_IN | GPIO_AF | 7) +#define PD7_AIN_SPI2_SCLK (GPIO_PORTD | GPIO_AIN | 7) #define PD8_PF_CLS (GPIO_PORTD | GPIO_PF | 8) #define PD8_AF_UART2_DCD (GPIO_PORTD | GPIO_OUT | GPIO_AF | 8) -#define PD8_AIN_SPI2_SS (GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 8) +#define PD8_AIN_SPI2_SS (GPIO_PORTD | GPIO_AIN | 8) #define PD9_PF_PS (GPIO_PORTD | GPIO_PF | 9) #define PD9_AF_UART2_RI (GPIO_PORTD | GPIO_OUT | GPIO_AF | 9) -#define PD9_AOUT_SPI2_RXD (GPIO_GIUS | GPIO_PORTD | GPIO_IN | 9) +#define PD9_AOUT_SPI2_RXD (GPIO_PORTD | GPIO_IN | 9) #define PD10_PF_SPL_SPR (GPIO_PORTD | GPIO_OUT | GPIO_PF | 10) #define PD10_AF_UART2_DSR (GPIO_PORTD | GPIO_OUT | GPIO_AF | 10) -#define PD10_AIN_SPI2_TXD (GPIO_GIUS | GPIO_PORTD | GPIO_OUT | 10) +#define PD10_AIN_SPI2_TXD (GPIO_PORTD | GPIO_OUT | 10) #define PD11_PF_CONTRAST (GPIO_PORTD | GPIO_OUT | GPIO_PF | 11) #define PD12_PF_ACD_OE (GPIO_PORTD | GPIO_OUT | GPIO_PF | 12) #define PD13_PF_LP_HSYNC (GPIO_PORTD | GPIO_OUT | GPIO_PF | 13) @@ -243,7 +238,7 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PD29_PF_LD14 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 29) #define PD30_PF_LD15 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 30) #define PD31_PF_TMR2OUT (GPIO_PORTD | GPIO_PF | 31) -#define PD31_BIN_SPI2_TXD (GPIO_GIUS | GPIO_PORTD | GPIO_BIN | 31) +#define PD31_BIN_SPI2_TXD (GPIO_PORTD | GPIO_BIN | 31) #endif #ifdef CONFIG_ARCH_MX2 @@ -279,6 +274,12 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PA29_PF_VSYNC (GPIO_PORTA | GPIO_OUT | GPIO_PF | 29) #define PA30_PF_CONTRAST (GPIO_PORTA | GPIO_OUT | GPIO_PF | 30) #define PA31_PF_OE_ACD (GPIO_PORTA | GPIO_OUT | GPIO_PF | 31) +#define PB4_PF_SD2_D0 (GPIO_PORTB | GPIO_PF | 4) +#define PB5_PF_SD2_D1 (GPIO_PORTB | GPIO_PF | 5) +#define PB6_PF_SD2_D2 (GPIO_PORTB | GPIO_PF | 6) +#define PB7_PF_SD2_D3 (GPIO_PORTB | GPIO_PF | 7) +#define PB8_PF_SD2_CMD (GPIO_PORTB | GPIO_PF | 8) +#define PB9_PF_SD2_CLK (GPIO_PORTB | GPIO_PF | 9) #define PB10_PF_CSI_D0 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 10) #define PB10_AF_UART6_TXD (GPIO_PORTB | GPIO_OUT | GPIO_AF | 10) #define PB11_PF_CSI_D1 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 11) @@ -315,6 +316,13 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PB31_AF_UART4_RXD (GPIO_PORTB | GPIO_IN | GPIO_AF | 31) #define PC5_PF_I2C2_SDA (GPIO_PORTC | GPIO_IN | GPIO_PF | 5) #define PC6_PF_I2C2_SCL (GPIO_PORTC | GPIO_IN | GPIO_PF | 6) +#define PC7_PF_USBOTG_DATA5 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 7) +#define PC8_PF_USBOTG_DATA6 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 8) +#define PC9_PF_USBOTG_DATA0 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 9) +#define PC10_PF_USBOTG_DATA2 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 10) +#define PC11_PF_USBOTG_DATA1 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 11) +#define PC12_PF_USBOTG_DATA4 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 12) +#define PC13_PF_USBOTG_DATA3 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 13) #define PC16_PF_SSI4_FS (GPIO_PORTC | GPIO_IN | GPIO_PF | 16) #define PC17_PF_SSI4_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 17) #define PC18_PF_SSI4_TXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 18) @@ -365,6 +373,9 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PD30_PF_CSPI1_MISO (GPIO_PORTD | GPIO_IN | GPIO_PF | 30) #define PD31_PF_CSPI1_MOSI (GPIO_PORTD | GPIO_OUT | GPIO_PF | 31) #define PF23_AIN_FEC_TX_EN (GPIO_PORTF | GPIO_OUT | GPIO_AIN | 23) +#define PE0_PF_USBOTG_NXT (GPIO_PORTE | GPIO_OUT | GPIO_PF | 0) +#define PE1_PF_USBOTG_STP (GPIO_PORTE | GPIO_OUT | GPIO_PF | 1) +#define PE2_PF_USBOTG_DIR (GPIO_PORTE | GPIO_OUT | GPIO_PF | 2) #define PE3_PF_UART2_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 3) #define PE4_PF_UART2_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 4) #define PE6_PF_UART2_TXD (GPIO_PORTE | GPIO_OUT | GPIO_PF | 6) @@ -379,18 +390,27 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, #define PE15_PF_UART1_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 15) #define PE16_AF_RTCK (GPIO_PORTE | GPIO_OUT | GPIO_AF | 16) #define PE16_PF_RTCK (GPIO_PORTE | GPIO_OUT | GPIO_PF | 16) +#define PE18_PF_SDHC1_D0 (GPIO_PORTE | GPIO_PF | 18) #define PE18_AF_CSPI3_MISO (GPIO_PORTE | GPIO_IN | GPIO_AF | 18) +#define PE19_PF_SDHC1_D1 (GPIO_PORTE | GPIO_PF | 19) +#define PE20_PF_SDHC1_D2 (GPIO_PORTE | GPIO_PF | 20) +#define PE21_PF_SDHC1_D3 (GPIO_PORTE | GPIO_PF | 21) #define PE21_AF_CSPI3_SS (GPIO_PORTE | GPIO_OUT | GPIO_AF | 21) +#define PE22_PF_SDHC1_CMD (GPIO_PORTE | GPIO_PF | 22) #define PE22_AF_CSPI3_MOSI (GPIO_PORTE | GPIO_OUT | GPIO_AF | 22) +#define PE22_PF_SDHC1_CLK (GPIO_PORTE | GPIO_PF | 23) #define PE23_AF_CSPI3_SCLK (GPIO_PORTE | GPIO_OUT | GPIO_AF | 23) +#define PE24_PF_USBOTG_CLK (GPIO_PORTE | GPIO_OUT | GPIO_PF | 24) +#define PE25_PF_USBOTG_DATA7 (GPIO_PORTE | GPIO_OUT | GPIO_PF | 25) #endif /* decode irq number to use with IMR(x), ISR(x) and friends */ -#define IRQ_TO_REG(irq) ((irq - MXC_MAX_INT_LINES) >> 5) +#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5) -#define IRQ_GPIOA(x) (MXC_MAX_INT_LINES + x) +#define IRQ_GPIOA(x) (MXC_GPIO_IRQ_START + x) #define IRQ_GPIOB(x) (IRQ_GPIOA(32) + x) #define IRQ_GPIOC(x) (IRQ_GPIOB(32) + x) #define IRQ_GPIOD(x) (IRQ_GPIOC(32) + x) +#define IRQ_GPIOE(x) (IRQ_GPIOD(32) + x) #endif /* _MXC_GPIO_MX1_MX2_H */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index c9f39c2fb8c6..c9198c0aea18 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -141,7 +141,7 @@ void mxc_iomux_set_gpr(enum iomux_gp_func, bool); ((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) #define IOMUX_TO_IRQ(iomux_pin) \ (((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) + \ - MXC_GPIO_INT_BASE) + MXC_GPIO_IRQ_START) /* * This enumeration is constructed based on the Section @@ -491,6 +491,14 @@ enum iomux_pins { #define MX31_PIN_RTS1__RTS1 IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_FUNC) #define MX31_PIN_TXD1__TXD1 IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_FUNC) #define MX31_PIN_RXD1__RXD1 IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CTS2__CTS2 IOMUX_MODE(MX31_PIN_CTS2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_RTS2__RTS2 IOMUX_MODE(MX31_PIN_RTS2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_TXD2__TXD2 IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_RXD2__RXD2 IOMUX_MODE(MX31_PIN_RXD2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_PC_RST__CTS5 IOMUX_MODE(MX31_PIN_PC_RST, IOMUX_CONFIG_ALT2) +#define MX31_PIN_PC_VS2__RTS5 IOMUX_MODE(MX31_PIN_PC_VS2, IOMUX_CONFIG_ALT2) +#define MX31_PIN_PC_BVD2__TXD5 IOMUX_MODE(MX31_PIN_PC_BVD2, IOMUX_CONFIG_ALT2) +#define MX31_PIN_PC_BVD1__RXD5 IOMUX_MODE(MX31_PIN_PC_BVD1, IOMUX_CONFIG_ALT2) #define MX31_PIN_CSPI1_MOSI__MOSI IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI1_MISO__MISO IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI1_SCLK__SCLK IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_FUNC) @@ -509,6 +517,15 @@ enum iomux_pins { #define MX31_PIN_CSPI3_MISO__MISO IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI3_SCLK__SCLK IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI3_SPI_RDY__SPI_RDY IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_FUNC) +#define MX31_PIN_BATT_LINE__OWIRE IOMUX_MODE(MX31_PIN_BATT_LINE, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CS4__CS4 IOMUX_MODE(MX31_PIN_CS4, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_DATA3__SD1_DATA3 IOMUX_MODE(MX31_PIN_SD1_DATA3, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_DATA2__SD1_DATA2 IOMUX_MODE(MX31_PIN_SD1_DATA2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_DATA1__SD1_DATA1 IOMUX_MODE(MX31_PIN_SD1_DATA1, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_DATA0__SD1_DATA0 IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_CLK__SD1_CLK IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC) +#define MX31_PIN_SD1_CMD__SD1_CMD IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC) + /*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0 * cspi1_ss1*/ diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index b55bba35e18a..e06d3cb0ee11 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h @@ -11,7 +11,37 @@ #ifndef __ASM_ARCH_MXC_IRQS_H__ #define __ASM_ARCH_MXC_IRQS_H__ -#include <mach/hardware.h> +/* + * So far all i.MX SoCs have 64 internal interrupts + */ +#define MXC_INTERNAL_IRQS 64 + +#define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS + +#if defined CONFIG_ARCH_MX1 +#define MXC_GPIO_IRQS (32 * 4) +#elif defined CONFIG_ARCH_MX2 +#define MXC_GPIO_IRQS (32 * 6) +#elif defined CONFIG_ARCH_MX3 +#define MXC_GPIO_IRQS (32 * 3) +#endif + +/* + * The next 16 interrupts are for board specific purposes. Since + * the kernel can only run on one machine at a time, we can re-use + * these. If you need more, increase MXC_BOARD_IRQS, but keep it + * within sensible limits. + */ +#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS) +#define MXC_BOARD_IRQS 16 + +#define NR_IRQS (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS) + extern void imx_irq_set_priority(unsigned char irq, unsigned char prio); +/* all normal IRQs can be FIQs */ +#define FIQ_START 0 +/* switch betwean IRQ and FIQ */ +extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type); + #endif /* __ASM_ARCH_MXC_IRQS_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h index d7a8d3ebed57..0b808399097f 100644 --- a/arch/arm/plat-mxc/include/mach/memory.h +++ b/arch/arm/plat-mxc/include/mach/memory.h @@ -11,19 +11,12 @@ #ifndef __ASM_ARCH_MXC_MEMORY_H__ #define __ASM_ARCH_MXC_MEMORY_H__ -#include <mach/hardware.h> - -/* - * Virtual view <-> DMA view memory address translations - * This macro is used to translate the virtual address to an address - * suitable to be passed to set_dma_addr() - */ -#define __virt_to_bus(a) __virt_to_phys(a) - -/* - * Used to convert an address for DMA operations to an address that the - * kernel can use. - */ -#define __bus_to_virt(a) __phys_to_virt(a) +#if defined CONFIG_ARCH_MX1 +#define PHYS_OFFSET UL(0x08000000) +#elif defined CONFIG_ARCH_MX2 +#define PHYS_OFFSET UL(0xA0000000) +#elif defined CONFIG_ARCH_MX3 +#define PHYS_OFFSET UL(0x80000000) +#endif #endif /* __ASM_ARCH_MXC_MEMORY_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mtd-xip.h b/arch/arm/plat-mxc/include/mach/mtd-xip.h new file mode 100644 index 000000000000..1ab1bba5688d --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mtd-xip.h @@ -0,0 +1,34 @@ +/* + * MTD primitives for XIP support. Architecture specific functions + * + * Do not include this file directly. It's included from linux/mtd/xip.h + * + * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>, Teltonika, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <mach/mxc_timer.h> + +#ifndef __ARCH_IMX_MTD_XIP_H__ +#define __ARCH_IMX_MTD_XIP_H__ + +#ifdef CONFIG_ARCH_MX1 +/* AITC registers */ +#define AITC_BASE IO_ADDRESS(AVIC_BASE_ADDR) +#define NIPNDH (AITC_BASE + 0x58) +#define NIPNDL (AITC_BASE + 0x5C) +#define INTENABLEH (AITC_BASE + 0x10) +#define INTENABLEL (AITC_BASE + 0x14) +/* MTD macros */ +#define xip_irqpending() ((__raw_readl(INTENABLEH) & __raw_readl(NIPNDH)) \ + || (__raw_readl(INTENABLEL) & __raw_readl(NIPNDL))) +#define xip_currtime() (__raw_readl(TIMER_BASE + MXC_TCN)) +#define xip_elapsed_since(x) (signed)((__raw_readl(TIMER_BASE + MXC_TCN) - (x)) / 96) +#define xip_cpu_idle() asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (0)) +#endif /* CONFIG_ARCH_MX1 */ + +#endif /* __ARCH_IMX_MTD_XIP_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h new file mode 100644 index 000000000000..b92e02324d8e --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx1.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 1997,1998 Russell King + * Copyright (C) 1999 ARM Limited + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_MXC_MX1_H__ +#define __ASM_ARCH_MXC_MX1_H__ + +#ifndef __ASM_ARCH_MXC_HARDWARE_H__ +#error "Do not include directly." +#endif + +#include <mach/vmalloc.h> + +/* + * Memory map + */ +#define IMX_IO_PHYS 0x00200000 +#define IMX_IO_SIZE 0x00100000 +#define IMX_IO_BASE VMALLOC_END + +#define IMX_CS0_PHYS 0x10000000 +#define IMX_CS0_SIZE 0x02000000 + +#define IMX_CS1_PHYS 0x12000000 +#define IMX_CS1_SIZE 0x01000000 + +#define IMX_CS2_PHYS 0x13000000 +#define IMX_CS2_SIZE 0x01000000 + +#define IMX_CS3_PHYS 0x14000000 +#define IMX_CS3_SIZE 0x01000000 + +#define IMX_CS4_PHYS 0x15000000 +#define IMX_CS4_SIZE 0x01000000 + +#define IMX_CS5_PHYS 0x16000000 +#define IMX_CS5_SIZE 0x01000000 + +/* + * Register BASEs, based on OFFSETs + */ +#define AIPI1_BASE_ADDR (0x00000 + IMX_IO_PHYS) +#define WDT_BASE_ADDR (0x01000 + IMX_IO_PHYS) +#define TIM1_BASE_ADDR (0x02000 + IMX_IO_PHYS) +#define TIM2_BASE_ADDR (0x03000 + IMX_IO_PHYS) +#define RTC_BASE_ADDR (0x04000 + IMX_IO_PHYS) +#define LCDC_BASE_ADDR (0x05000 + IMX_IO_PHYS) +#define UART1_BASE_ADDR (0x06000 + IMX_IO_PHYS) +#define UART2_BASE_ADDR (0x07000 + IMX_IO_PHYS) +#define PWM_BASE_ADDR (0x08000 + IMX_IO_PHYS) +#define DMA_BASE_ADDR (0x09000 + IMX_IO_PHYS) +#define AIPI2_BASE_ADDR (0x10000 + IMX_IO_PHYS) +#define SIM_BASE_ADDR (0x11000 + IMX_IO_PHYS) +#define USBD_BASE_ADDR (0x12000 + IMX_IO_PHYS) +#define SPI1_BASE_ADDR (0x13000 + IMX_IO_PHYS) +#define MMC_BASE_ADDR (0x14000 + IMX_IO_PHYS) +#define ASP_BASE_ADDR (0x15000 + IMX_IO_PHYS) +#define BTA_BASE_ADDR (0x16000 + IMX_IO_PHYS) +#define I2C_BASE_ADDR (0x17000 + IMX_IO_PHYS) +#define SSI_BASE_ADDR (0x18000 + IMX_IO_PHYS) +#define SPI2_BASE_ADDR (0x19000 + IMX_IO_PHYS) +#define MSHC_BASE_ADDR (0x1A000 + IMX_IO_PHYS) +#define CCM_BASE_ADDR (0x1B000 + IMX_IO_PHYS) +#define SCM_BASE_ADDR (0x1B804 + IMX_IO_PHYS) +#define GPIO_BASE_ADDR (0x1C000 + IMX_IO_PHYS) +#define EIM_BASE_ADDR (0x20000 + IMX_IO_PHYS) +#define SDRAMC_BASE_ADDR (0x21000 + IMX_IO_PHYS) +#define MMA_BASE_ADDR (0x22000 + IMX_IO_PHYS) +#define AVIC_BASE_ADDR (0x23000 + IMX_IO_PHYS) +#define CSI_BASE_ADDR (0x24000 + IMX_IO_PHYS) + +/* macro to get at IO space when running virtually */ +#define IO_ADDRESS(x) ((x) - IMX_IO_PHYS + IMX_IO_BASE) + +/* define macros needed for entry-macro.S */ +#define AVIC_IO_ADDRESS(x) IO_ADDRESS(x) + +/* fixed interrput numbers */ +#define INT_SOFTINT 0 +#define CSI_INT 6 +#define DSPA_MAC_INT 7 +#define DSPA_INT 8 +#define COMP_INT 9 +#define MSHC_XINT 10 +#define GPIO_INT_PORTA 11 +#define GPIO_INT_PORTB 12 +#define GPIO_INT_PORTC 13 +#define LCDC_INT 14 +#define SIM_INT 15 +#define SIM_DATA_INT 16 +#define RTC_INT 17 +#define RTC_SAMINT 18 +#define UART2_MINT_PFERR 19 +#define UART2_MINT_RTS 20 +#define UART2_MINT_DTR 21 +#define UART2_MINT_UARTC 22 +#define UART2_MINT_TX 23 +#define UART2_MINT_RX 24 +#define UART1_MINT_PFERR 25 +#define UART1_MINT_RTS 26 +#define UART1_MINT_DTR 27 +#define UART1_MINT_UARTC 28 +#define UART1_MINT_TX 29 +#define UART1_MINT_RX 30 +#define VOICE_DAC_INT 31 +#define VOICE_ADC_INT 32 +#define PEN_DATA_INT 33 +#define PWM_INT 34 +#define SDHC_INT 35 +#define I2C_INT 39 +#define CSPI_INT 41 +#define SSI_TX_INT 42 +#define SSI_TX_ERR_INT 43 +#define SSI_RX_INT 44 +#define SSI_RX_ERR_INT 45 +#define TOUCH_INT 46 +#define USBD_INT0 47 +#define USBD_INT1 48 +#define USBD_INT2 49 +#define USBD_INT3 50 +#define USBD_INT4 51 +#define USBD_INT5 52 +#define USBD_INT6 53 +#define BTSYS_INT 55 +#define BTTIM_INT 56 +#define BTWUI_INT 57 +#define TIM2_INT 58 +#define TIM1_INT 59 +#define DMA_ERR 60 +#define DMA_INT 61 +#define GPIO_INT_PORTD 62 +#define WDT_INT 63 + +/* gpio and gpio based interrupt handling */ +#define GPIO_DR 0x1C +#define GPIO_GDIR 0x00 +#define GPIO_PSR 0x24 +#define GPIO_ICR1 0x28 +#define GPIO_ICR2 0x2C +#define GPIO_IMR 0x30 +#define GPIO_ISR 0x34 +#define GPIO_INT_LOW_LEV 0x3 +#define GPIO_INT_HIGH_LEV 0x2 +#define GPIO_INT_RISE_EDGE 0x0 +#define GPIO_INT_FALL_EDGE 0x1 +#define GPIO_INT_NONE 0x4 + +/* DMA */ +#define DMA_REQ_UART3_T 2 +#define DMA_REQ_UART3_R 3 +#define DMA_REQ_SSI2_T 4 +#define DMA_REQ_SSI2_R 5 +#define DMA_REQ_CSI_STAT 6 +#define DMA_REQ_CSI_R 7 +#define DMA_REQ_MSHC 8 +#define DMA_REQ_DSPA_DCT_DOUT 9 +#define DMA_REQ_DSPA_DCT_DIN 10 +#define DMA_REQ_DSPA_MAC 11 +#define DMA_REQ_EXT 12 +#define DMA_REQ_SDHC 13 +#define DMA_REQ_SPI1_R 14 +#define DMA_REQ_SPI1_T 15 +#define DMA_REQ_SSI_T 16 +#define DMA_REQ_SSI_R 17 +#define DMA_REQ_ASP_DAC 18 +#define DMA_REQ_ASP_ADC 19 +#define DMA_REQ_USP_EP(x) (20 + (x)) +#define DMA_REQ_SPI2_R 26 +#define DMA_REQ_SPI2_T 27 +#define DMA_REQ_UART2_T 28 +#define DMA_REQ_UART2_R 29 +#define DMA_REQ_UART1_T 30 +#define DMA_REQ_UART1_R 31 + +/* mandatory for CONFIG_LL_DEBUG */ +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR IO_ADDRESS(UART1_BASE_ADDR) + +#endif /* __ASM_ARCH_MXC_MX1_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index a86db64744a1..0313be720552 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -72,7 +72,8 @@ /* for mx27*/ #define OTG_BASE_ADDR USBOTG_BASE_ADDR #define SAHARA_BASE_ADDR (AIPI_BASE_ADDR + 0x25000) -#define EMMA_BASE_ADDR (AIPI_BASE_ADDR + 0x26400) +#define EMMA_PP_BASE_ADDR (AIPI_BASE_ADDR + 0x26000) +#define EMMA_PRP_BASE_ADDR (AIPI_BASE_ADDR + 0x26400) #define CCM_BASE_ADDR (AIPI_BASE_ADDR + 0x27000) #define SYSCTRL_BASE_ADDR (AIPI_BASE_ADDR + 0x27800) #define IIM_BASE_ADDR (AIPI_BASE_ADDR + 0x28000) @@ -288,16 +289,4 @@ extern int mx27_revision(void); /* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */ #define ARCH_NR_GPIOS (192 + 16) -/* OS clock tick rate */ -#define CLOCK_TICK_RATE 13300000 - -/* Start of RAM */ -#define PHYS_OFFSET SDRAM_BASE_ADDR - -/* max interrupt lines count */ -#define NR_IRQS 256 - -/* count of internal interrupt sources */ -#define MXC_MAX_INT_LINES 64 - #endif /* __ASM_ARCH_MXC_MX27_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h index 0536f8917bc0..de026654b00e 100644 --- a/arch/arm/plat-mxc/include/mach/mx31.h +++ b/arch/arm/plat-mxc/include/mach/mx31.h @@ -15,11 +15,6 @@ #error "Do not include directly." #endif -/*! - * defines the hardware clock tick rate - */ -#define CLOCK_TICK_RATE 16625000 - /* * MX31 memory map: * @@ -244,9 +239,6 @@ #define PCMCIA_IO_ADDRESS(x) \ (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) -/* Start of physical RAM - On many MX31 platforms, this is the first SDRAM bank (CSD0) */ -#define PHYS_OFFSET CSD0_BASE_ADDR - /* * Interrupt numbers */ @@ -315,23 +307,6 @@ #define MXC_INT_EXT_WDOG 62 #define MXC_INT_EXT_TV 63 -#define MXC_MAX_INT_LINES 64 - -#define MXC_GPIO_INT_BASE MXC_MAX_INT_LINES -#define MXC_MAX_GPIO_LINES (GPIO_NUM_PIN * GPIO_PORT_NUM) -#define MXC_MAX_VIRTUAL_INTS 16 - -#define NR_IRQS (MXC_MAX_INT_LINES + MXC_MAX_GPIO_LINES + MXC_MAX_VIRTUAL_INTS) - -/*! - * Number of GPIO port as defined in the IC Spec - */ -#define GPIO_PORT_NUM 3 -/*! - * Number of GPIO pins per port - */ -#define GPIO_NUM_PIN 32 - #define PROD_SIGNATURE 0x1 /* For MX31 */ /* silicon revisions specific to i.MX31 */ diff --git a/arch/arm/plat-mxc/include/mach/mxc_timer.h b/arch/arm/plat-mxc/include/mach/mxc_timer.h index 130aebfbe168..6c19a134744b 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_timer.h +++ b/arch/arm/plat-mxc/include/mach/mxc_timer.h @@ -26,7 +26,7 @@ #include <linux/clk.h> #include <mach/hardware.h> -#ifdef CONFIG_ARCH_IMX +#ifdef CONFIG_ARCH_MX1 #define TIMER_BASE IO_ADDRESS(TIM1_BASE_ADDR) #define TIMER_INTERRUPT TIM1_INT @@ -65,7 +65,7 @@ static void gpt_irq_acknowledge(void) { __raw_writel(0, TIMER_BASE + MXC_TSTAT); } -#endif /* CONFIG_ARCH_IMX */ +#endif /* CONFIG_ARCH_MX1 */ #ifdef CONFIG_ARCH_MX2 #define TIMER_BASE IO_ADDRESS(GPT1_BASE_ADDR) diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h index 0b0af0253e91..07b4a73c9d2f 100644 --- a/arch/arm/plat-mxc/include/mach/timex.h +++ b/arch/arm/plat-mxc/include/mach/timex.h @@ -20,6 +20,12 @@ #ifndef __ASM_ARCH_MXC_TIMEX_H__ #define __ASM_ARCH_MXC_TIMEX_H__ -#include <mach/hardware.h> /* for CLOCK_TICK_RATE */ +#if defined CONFIG_ARCH_MX1 +#define CLOCK_TICK_RATE 16000000 +#elif defined CONFIG_ARCH_MX2 +#define CLOCK_TICK_RATE 13300000 +#elif defined CONFIG_ARCH_MX3 +#define CLOCK_TICK_RATE 16625000 +#endif #endif /* __ASM_ARCH_MXC_TIMEX_H__ */ diff --git a/arch/arm/plat-mxc/iomux-mx1-mx2.c b/arch/arm/plat-mxc/iomux-mx1-mx2.c index d97387aa9a42..df6f18395686 100644 --- a/arch/arm/plat-mxc/iomux-mx1-mx2.c +++ b/arch/arm/plat-mxc/iomux-mx1-mx2.c @@ -110,12 +110,13 @@ void mxc_gpio_mode(int gpio_mode) EXPORT_SYMBOL(mxc_gpio_mode); int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, - int alloc_mode, const char *label) + const char *label) { const int *p = pin_list; int i; unsigned gpio; unsigned mode; + int ret = -EINVAL; for (i = 0; i < count; i++) { gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK); @@ -124,33 +125,33 @@ int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, if (gpio >= (GPIO_PORT_MAX + 1) * 32) goto setup_error; - if (alloc_mode & MXC_GPIO_ALLOC_MODE_RELEASE) - gpio_free(gpio); - else if (!(alloc_mode & MXC_GPIO_ALLOC_MODE_NO_ALLOC)) - if (gpio_request(gpio, label) - && !(alloc_mode & MXC_GPIO_ALLOC_MODE_TRY_ALLOC)) - goto setup_error; + ret = gpio_request(gpio, label); + if (ret) + goto setup_error; - if (!(alloc_mode & (MXC_GPIO_ALLOC_MODE_ALLOC_ONLY | - MXC_GPIO_ALLOC_MODE_RELEASE))) - mxc_gpio_mode(gpio | mode); + mxc_gpio_mode(gpio | mode); p++; } return 0; setup_error: - if (alloc_mode & (MXC_GPIO_ALLOC_MODE_NO_ALLOC | - MXC_GPIO_ALLOC_MODE_TRY_ALLOC)) - return -EINVAL; + mxc_gpio_release_multiple_pins(pin_list, i); + return ret; +} +EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins); - while (p != pin_list) { - p--; - gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK); +void mxc_gpio_release_multiple_pins(const int *pin_list, int count) +{ + const int *p = pin_list; + int i; + + for (i = 0; i < count; i++) { + unsigned gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK); gpio_free(gpio); + p++; } - return -EINVAL; } -EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins); +EXPORT_SYMBOL(mxc_gpio_release_multiple_pins); diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c index d862c9e5f8db..6e7578a3514b 100644 --- a/arch/arm/plat-mxc/irq.c +++ b/arch/arm/plat-mxc/irq.c @@ -17,9 +17,12 @@ * MA 02110-1301, USA. */ +#include <linux/module.h> #include <linux/irq.h> #include <linux/io.h> #include <mach/common.h> +#include <asm/mach/irq.h> +#include <mach/hardware.h> #define AVIC_BASE IO_ADDRESS(AVIC_BASE_ADDR) #define AVIC_INTCNTL (AVIC_BASE + 0x00) /* int control reg */ @@ -65,6 +68,28 @@ void imx_irq_set_priority(unsigned char irq, unsigned char prio) EXPORT_SYMBOL(imx_irq_set_priority); #endif +#ifdef CONFIG_FIQ +int mxc_set_irq_fiq(unsigned int irq, unsigned int type) +{ + unsigned int irqt; + + if (irq >= MXC_INTERNAL_IRQS) + return -EINVAL; + + if (irq < MXC_INTERNAL_IRQS / 2) { + irqt = __raw_readl(AVIC_INTTYPEL) & ~(1 << irq); + __raw_writel(irqt | (!!type << irq), AVIC_INTTYPEL); + } else { + irq -= MXC_INTERNAL_IRQS / 2; + irqt = __raw_readl(AVIC_INTTYPEH) & ~(1 << irq); + __raw_writel(irqt | (!!type << irq), AVIC_INTTYPEH); + } + + return 0; +} +EXPORT_SYMBOL(mxc_set_irq_fiq); +#endif /* CONFIG_FIQ */ + /* Disable interrupt number "irq" in the AVIC */ static void mxc_mask_irq(unsigned int irq) { @@ -91,7 +116,6 @@ static struct irq_chip mxc_avic_chip = { void __init mxc_init_irq(void) { int i; - u32 reg; /* put the AVIC into the reset value with * all interrupts disabled @@ -106,7 +130,7 @@ void __init mxc_init_irq(void) /* all IRQ no FIQ */ __raw_writel(0, AVIC_INTTYPEH); __raw_writel(0, AVIC_INTTYPEL); - for (i = 0; i < MXC_MAX_INT_LINES; i++) { + for (i = 0; i < MXC_INTERNAL_IRQS; i++) { set_irq_chip(i, &mxc_avic_chip); set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); @@ -119,5 +143,10 @@ void __init mxc_init_irq(void) /* init architectures chained interrupt handler */ mxc_register_gpios(); +#ifdef CONFIG_FIQ + /* Initialize FIQ */ + init_FIQ(); +#endif + printk(KERN_INFO "MXC IRQ initialized\n"); } diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index a94f0c44ebc8..46d3b0b9ce69 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -14,9 +14,11 @@ config ARCH_OMAP1 config ARCH_OMAP2 bool "TI OMAP2" + select CPU_V6 config ARCH_OMAP3 bool "TI OMAP3" + select CPU_V7 endchoice diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c index e31154b15d9e..f6684832ca8f 100644 --- a/arch/arm/plat-omap/debug-devices.c +++ b/arch/arm/plat-omap/debug-devices.c @@ -69,15 +69,15 @@ int __init debug_card_init(u32 addr, unsigned gpio) smc91x_resources[0].start = addr + 0x300; smc91x_resources[0].end = addr + 0x30f; - smc91x_resources[1].start = OMAP_GPIO_IRQ(gpio); - smc91x_resources[1].end = OMAP_GPIO_IRQ(gpio); + smc91x_resources[1].start = gpio_to_irq(gpio); + smc91x_resources[1].end = gpio_to_irq(gpio); - status = omap_request_gpio(gpio); + status = gpio_request(gpio, "SMC91x irq"); if (status < 0) { printk(KERN_ERR "GPIO%d unavailable for smc91x IRQ\n", gpio); return status; } - omap_set_gpio_direction(gpio, 1); + gpio_direction_input(gpio); led_resources[0].start = addr; led_resources[0].end = addr + SZ_4K - 1; diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 2f4c0cabfd34..be4eefda4767 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c @@ -83,8 +83,8 @@ static void h2p2_dbg_leds_event(led_event_t evt) /* all leds off during suspend or shutdown */ if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { - omap_set_gpio_dataout(GPIO_TIMER, 0); - omap_set_gpio_dataout(GPIO_IDLE, 0); + gpio_set_value(GPIO_TIMER, 0); + gpio_set_value(GPIO_IDLE, 0); } __raw_writew(~0, &fpga->leds); @@ -107,7 +107,7 @@ static void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2() || machine_is_omap_h4()) hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; else { - omap_set_gpio_dataout(GPIO_TIMER, + gpio_set_value(GPIO_TIMER, led_state & LED_TIMER_ON); goto done; } @@ -121,7 +121,7 @@ static void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2() || machine_is_omap_h4()) hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; else { - omap_set_gpio_dataout(GPIO_IDLE, 1); + gpio_set_value(GPIO_IDLE, 1); goto done; } @@ -131,7 +131,7 @@ static void h2p2_dbg_leds_event(led_event_t evt) if (machine_is_omap_perseus2() || machine_is_omap_h4()) hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; else { - omap_set_gpio_dataout(GPIO_IDLE, 0); + gpio_set_value(GPIO_IDLE, 0); goto done; } diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 0cb2b22388e9..ac15c23fd5da 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -192,202 +192,48 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -#define OMAP_MMC1_BASE 0x4809c000 -#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x1fc) -#define OMAP_MMC1_INT INT_24XX_MMC_IRQ +#define OMAP_MMC_NR_RES 2 -#define OMAP_MMC2_BASE 0x480b4000 -#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x1fc) -#define OMAP_MMC2_INT INT_24XX_MMC2_IRQ - -#else - -#define OMAP_MMC1_BASE 0xfffb7800 -#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x7f) -#define OMAP_MMC1_INT INT_MMC - -#define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ -#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x7f) -#define OMAP_MMC2_INT INT_1610_MMC2 - -#endif - -static struct omap_mmc_platform_data mmc1_data; - -static u64 mmc1_dmamask = 0xffffffff; - -static struct resource mmc1_resources[] = { - { - .start = OMAP_MMC1_BASE, - .end = OMAP_MMC1_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP_MMC1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mmc_omap_device1 = { - .name = "mmci-omap", - .id = 1, - .dev = { - .dma_mask = &mmc1_dmamask, - .platform_data = &mmc1_data, - }, - .num_resources = ARRAY_SIZE(mmc1_resources), - .resource = mmc1_resources, -}; - -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ - defined(CONFIG_ARCH_OMAP34XX) - -static struct omap_mmc_platform_data mmc2_data; - -static u64 mmc2_dmamask = 0xffffffff; - -static struct resource mmc2_resources[] = { - { - .start = OMAP_MMC2_BASE, - .end = OMAP_MMC2_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP_MMC2_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mmc_omap_device2 = { - .name = "mmci-omap", - .id = 2, - .dev = { - .dma_mask = &mmc2_dmamask, - .platform_data = &mmc2_data, - }, - .num_resources = ARRAY_SIZE(mmc2_resources), - .resource = mmc2_resources, -}; -#endif - -static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf) -{ - if (cpu_is_omap2430() || cpu_is_omap34xx()) - return; - - if (mmc_conf->mmc[0].enabled) { - if (cpu_is_omap24xx()) { - omap_cfg_reg(H18_24XX_MMC_CMD); - omap_cfg_reg(H15_24XX_MMC_CLKI); - omap_cfg_reg(G19_24XX_MMC_CLKO); - omap_cfg_reg(F20_24XX_MMC_DAT0); - omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); - omap_cfg_reg(G18_24XX_MMC_CMD_DIR); - } else { - omap_cfg_reg(MMC_CMD); - omap_cfg_reg(MMC_CLK); - omap_cfg_reg(MMC_DAT0); - if (cpu_is_omap1710()) { - omap_cfg_reg(M15_1710_MMC_CLKI); - omap_cfg_reg(P19_1710_MMC_CMDDIR); - omap_cfg_reg(P20_1710_MMC_DATDIR0); - } - } - if (mmc_conf->mmc[0].wire4) { - if (cpu_is_omap24xx()) { - omap_cfg_reg(H14_24XX_MMC_DAT1); - omap_cfg_reg(E19_24XX_MMC_DAT2); - omap_cfg_reg(D19_24XX_MMC_DAT3); - omap_cfg_reg(E20_24XX_MMC_DAT_DIR1); - omap_cfg_reg(F18_24XX_MMC_DAT_DIR2); - omap_cfg_reg(E18_24XX_MMC_DAT_DIR3); - } else { - omap_cfg_reg(MMC_DAT1); - /* NOTE: DAT2 can be on W10 (here) or M15 */ - if (!mmc_conf->mmc[0].nomux) - omap_cfg_reg(MMC_DAT2); - omap_cfg_reg(MMC_DAT3); - } - } - } - -#ifdef CONFIG_ARCH_OMAP16XX - /* block 2 is on newer chips, and has many pinout options */ - if (mmc_conf->mmc[1].enabled) { - if (!mmc_conf->mmc[1].nomux) { - omap_cfg_reg(Y8_1610_MMC2_CMD); - omap_cfg_reg(Y10_1610_MMC2_CLK); - omap_cfg_reg(R18_1610_MMC2_CLKIN); - omap_cfg_reg(W8_1610_MMC2_DAT0); - if (mmc_conf->mmc[1].wire4) { - omap_cfg_reg(V8_1610_MMC2_DAT1); - omap_cfg_reg(W15_1610_MMC2_DAT2); - omap_cfg_reg(R10_1610_MMC2_DAT3); - } - - /* These are needed for the level shifter */ - omap_cfg_reg(V9_1610_MMC2_CMDDIR); - omap_cfg_reg(V5_1610_MMC2_DATDIR0); - omap_cfg_reg(W19_1610_MMC2_DATDIR1); - } - - /* Feedback clock must be set on OMAP-1710 MMC2 */ - if (cpu_is_omap1710()) - omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), - MOD_CONF_CTRL_1); - } -#endif -} - -static void __init omap_init_mmc(void) +/* + * Register MMC devices. Called from mach-omap1 and mach-omap2 device init. + */ +int __init omap_mmc_add(int id, unsigned long base, unsigned long size, + unsigned int irq, struct omap_mmc_platform_data *data) { - const struct omap_mmc_config *mmc_conf; - - /* NOTE: assumes MMC was never (wrongly) enabled */ - mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); - if (!mmc_conf) - return; - - omap_init_mmc_conf(mmc_conf); - - if (mmc_conf->mmc[0].enabled) { - mmc1_data.conf = mmc_conf->mmc[0]; - (void) platform_device_register(&mmc_omap_device1); - } - -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ - defined(CONFIG_ARCH_OMAP34XX) - if (mmc_conf->mmc[1].enabled) { - mmc2_data.conf = mmc_conf->mmc[1]; - (void) platform_device_register(&mmc_omap_device2); - } -#endif -} + struct platform_device *pdev; + struct resource res[OMAP_MMC_NR_RES]; + int ret; + + pdev = platform_device_alloc("mmci-omap", id); + if (!pdev) + return -ENOMEM; + + memset(res, 0, OMAP_MMC_NR_RES * sizeof(struct resource)); + res[0].start = base; + res[0].end = base + size - 1; + res[0].flags = IORESOURCE_MEM; + res[1].start = res[1].end = irq; + res[1].flags = IORESOURCE_IRQ; + + ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); + if (ret == 0) + ret = platform_device_add_data(pdev, data, sizeof(*data)); + if (ret) + goto fail; + + ret = platform_device_add(pdev); + if (ret) + goto fail; + return 0; -void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) -{ - switch (host) { - case 1: - mmc1_data = *info; - break; -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ - defined(CONFIG_ARCH_OMAP34XX) - case 2: - mmc2_data = *info; - break; -#endif - default: - BUG(); - } +fail: + platform_device_put(pdev); + return ret; } -#else -static inline void omap_init_mmc(void) {} -void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) {} #endif /*-------------------------------------------------------------------------*/ @@ -532,7 +378,6 @@ static int __init omap_init_devices(void) */ omap_init_dsp(); omap_init_kp(); - omap_init_mmc(); omap_init_uwire(); omap_init_wdt(); omap_init_rng(); diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 50f8b4ad9a09..692d2b495af3 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -29,7 +29,7 @@ #include <asm/system.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/tc.h> @@ -1848,9 +1848,22 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA synchronization event drop occurred with device " "%d\n", dma_chan[ch].dev_id); - if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) + if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) { printk(KERN_INFO "DMA transaction error with device %d\n", dma_chan[ch].dev_id); + if (cpu_class_is_omap2()) { + /* Errata: sDMA Channel is not disabled + * after a transaction error. So we explicitely + * disable the channel + */ + u32 ccr; + + ccr = dma_read(CCR(ch)); + ccr &= ~OMAP_DMA_CCR_EN; + dma_write(ccr, CCR(ch)); + dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; + } + } if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ)) printk(KERN_INFO "DMA secure error with device %d\n", dma_chan[ch].dev_id); diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 963c31cd1541..e4f0ce04ba92 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -539,10 +539,6 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); - /* REVISIT: hw feature, ttgr overtaking tldr? */ - while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))) - cpu_relax(); - omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } @@ -553,14 +549,15 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, u32 l; l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - if (autoreload) + if (autoreload) { l |= OMAP_TIMER_CTRL_AR; - else + omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + } else { l &= ~OMAP_TIMER_CTRL_AR; + } l |= OMAP_TIMER_CTRL_ST; omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); - omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 424049d83fbe..07b6968a7d16 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -152,6 +152,7 @@ struct gpio_bank { u32 level_mask; spinlock_t lock; struct gpio_chip chip; + struct clk *dbck; }; #define METHOD_MPUIO 0 @@ -244,6 +245,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) return &gpio_bank[gpio >> 5]; if (cpu_is_omap34xx()) return &gpio_bank[gpio >> 5]; + BUG(); + return NULL; } static inline int get_gpio_index(int gpio) @@ -332,19 +335,6 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) __raw_writel(l, reg); } -void omap_set_gpio_direction(int gpio, int is_input) -{ - struct gpio_bank *bank; - unsigned long flags; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_direction(bank, get_gpio_index(gpio), is_input); - spin_unlock_irqrestore(&bank->lock, flags); -} - static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) { void __iomem *reg = bank->base; @@ -406,20 +396,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) __raw_writel(l, reg); } -void omap_set_gpio_dataout(int gpio, int enable) -{ - struct gpio_bank *bank; - unsigned long flags; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_dataout(bank, get_gpio_index(gpio), enable); - spin_unlock_irqrestore(&bank->lock, flags); -} - -int omap_get_gpio_datain(int gpio) +static int __omap_get_gpio_datain(int gpio) { struct gpio_bank *bank; void __iomem *reg; @@ -473,6 +450,7 @@ void omap_set_gpio_debounce(int gpio, int enable) { struct gpio_bank *bank; void __iomem *reg; + unsigned long flags; u32 val, l = 1 << get_gpio_index(gpio); if (cpu_class_is_omap1()) @@ -480,16 +458,28 @@ void omap_set_gpio_debounce(int gpio, int enable) bank = get_gpio_bank(gpio); reg = bank->base; - reg += OMAP24XX_GPIO_DEBOUNCE_EN; + + spin_lock_irqsave(&bank->lock, flags); val = __raw_readl(reg); - if (enable) + if (enable && !(val & l)) val |= l; - else + else if (!enable && (val & l)) val &= ~l; + else + goto done; + + if (cpu_is_omap34xx()) { + if (enable) + clk_enable(bank->dbck); + else + clk_disable(bank->dbck); + } __raw_writel(val, reg); +done: + spin_unlock_irqrestore(&bank->lock, flags); } EXPORT_SYMBOL(omap_set_gpio_debounce); @@ -906,26 +896,17 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable) return retval; } -int omap_request_gpio(int gpio) +static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; + struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - int status; - - if (check_gpio(gpio) < 0) - return -EINVAL; - status = gpio_request(gpio, NULL); - if (status < 0) - return status; - - bank = get_gpio_bank(gpio); spin_lock_irqsave(&bank->lock, flags); /* Set trigger to none. You need to enable the desired trigger with * request_irq() or set_irq_type(). */ - _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); + _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); #ifdef CONFIG_ARCH_OMAP15XX if (bank->method == METHOD_GPIO_1510) { @@ -933,7 +914,7 @@ int omap_request_gpio(int gpio) /* Claim the pin for MPU */ reg = bank->base + OMAP1510_GPIO_PIN_CONTROL; - __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); + __raw_writel(__raw_readl(reg) | (1 << offset), reg); } #endif spin_unlock_irqrestore(&bank->lock, flags); @@ -941,39 +922,28 @@ int omap_request_gpio(int gpio) return 0; } -void omap_free_gpio(int gpio) +static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; + struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); spin_lock_irqsave(&bank->lock, flags); - if (unlikely(!gpiochip_is_requested(&bank->chip, - get_gpio_index(gpio)))) { - spin_unlock_irqrestore(&bank->lock, flags); - printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); - dump_stack(); - return; - } #ifdef CONFIG_ARCH_OMAP16XX if (bank->method == METHOD_GPIO_1610) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - __raw_writel(1 << get_gpio_index(gpio), reg); + __raw_writel(1 << offset, reg); } #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) if (bank->method == METHOD_GPIO_24XX) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; - __raw_writel(1 << get_gpio_index(gpio), reg); + __raw_writel(1 << offset, reg); } #endif - _reset_gpio(bank, gpio); + _reset_gpio(bank, bank->chip.base + offset); spin_unlock_irqrestore(&bank->lock, flags); - gpio_free(gpio); } /* @@ -1252,7 +1222,7 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset) static int gpio_get(struct gpio_chip *chip, unsigned offset) { - return omap_get_gpio_datain(chip->base + offset); + return __omap_get_gpio_datain(chip->base + offset); } static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) @@ -1279,6 +1249,14 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&bank->lock, flags); } +static int gpio_2irq(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_bank *bank; + + bank = container_of(chip, struct gpio_bank, chip); + return bank->virtual_irq_start + offset; +} + /*---------------------------------------------------------------------*/ static int initialized; @@ -1296,7 +1274,6 @@ static struct clk * gpio5_fck; #endif #if defined(CONFIG_ARCH_OMAP3) -static struct clk *gpio_fclks[OMAP34XX_NR_GPIOS]; static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; #endif @@ -1310,9 +1287,7 @@ static int __init _omap_gpio_init(void) int i; int gpio = 0; struct gpio_bank *bank; -#if defined(CONFIG_ARCH_OMAP3) char clk_name[11]; -#endif initialized = 1; @@ -1367,12 +1342,6 @@ static int __init _omap_gpio_init(void) printk(KERN_ERR "Could not get %s\n", clk_name); else clk_enable(gpio_iclks[i]); - sprintf(clk_name, "gpio%d_fck", i + 1); - gpio_fclks[i] = clk_get(NULL, clk_name); - if (IS_ERR(gpio_fclks[i])) - printk(KERN_ERR "Could not get %s\n", clk_name); - else - clk_enable(gpio_fclks[i]); } } #endif @@ -1479,10 +1448,13 @@ static int __init _omap_gpio_init(void) /* REVISIT eventually switch from OMAP-specific gpio structs * over to the generic ones */ + bank->chip.request = omap_gpio_request; + bank->chip.free = omap_gpio_free; bank->chip.direction_input = gpio_input; bank->chip.get = gpio_get; bank->chip.direction_output = gpio_output; bank->chip.set = gpio_set; + bank->chip.to_irq = gpio_2irq; if (bank_is_mpuio(bank)) { bank->chip.label = "mpuio"; #ifdef CONFIG_ARCH_OMAP16XX @@ -1511,6 +1483,13 @@ static int __init _omap_gpio_init(void) } set_irq_chained_handler(bank->irq, gpio_irq_handler); set_irq_data(bank->irq, bank); + + if (cpu_is_omap34xx()) { + sprintf(clk_name, "gpio%d_dbck", i + 1); + bank->dbck = clk_get(NULL, clk_name); + if (IS_ERR(bank->dbck)) + printk(KERN_ERR "Could not get %s\n", clk_name); + } } /* Enable system clock for GPIO module. @@ -1739,12 +1718,6 @@ static int __init omap_gpio_sysinit(void) return ret; } -EXPORT_SYMBOL(omap_request_gpio); -EXPORT_SYMBOL(omap_free_gpio); -EXPORT_SYMBOL(omap_set_gpio_direction); -EXPORT_SYMBOL(omap_set_gpio_dataout); -EXPORT_SYMBOL(omap_get_gpio_datain); - arch_initcall(omap_gpio_sysinit); @@ -1801,14 +1774,14 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) continue; irq = bank->virtual_irq_start + j; - value = omap_get_gpio_datain(gpio); + value = gpio_get_value(gpio); is_in = gpio_is_input(bank, mask); if (bank_is_mpuio(bank)) seq_printf(s, "MPUIO %2d ", j); else seq_printf(s, "GPIO %3d ", gpio); - seq_printf(s, "(%10s): %s %s", + seq_printf(s, "(%-20.20s): %s %s", label, is_in ? "in " : "out", value ? "hi" : "lo"); diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 0e6d147ab6f8..89a6ab0b7db8 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -79,26 +79,43 @@ static struct platform_device omap_i2c_devices[] = { #endif }; -static void __init omap_i2c_mux_pins(int bus_id) +#if defined(CONFIG_ARCH_OMAP24XX) +static const int omap24xx_pins[][2] = { + { M19_24XX_I2C1_SCL, L15_24XX_I2C1_SDA }, + { J15_24XX_I2C2_SCL, H19_24XX_I2C2_SDA }, +}; +#else +static const int omap24xx_pins[][2] = {}; +#endif +#if defined(CONFIG_ARCH_OMAP34XX) +static const int omap34xx_pins[][2] = { + { K21_34XX_I2C1_SCL, J21_34XX_I2C1_SDA}, + { AF15_34XX_I2C2_SCL, AE15_34XX_I2C2_SDA}, + { AF14_34XX_I2C3_SCL, AG14_34XX_I2C3_SDA}, +}; +#else +static const int omap34xx_pins[][2] = {}; +#endif + +static void __init omap_i2c_mux_pins(int bus) { - /* TODO: Muxing for OMAP3 */ - switch (bus_id) { - case 1: - if (cpu_class_is_omap1()) { - omap_cfg_reg(I2C_SCL); - omap_cfg_reg(I2C_SDA); - } else if (cpu_is_omap24xx()) { - omap_cfg_reg(M19_24XX_I2C1_SCL); - omap_cfg_reg(L15_24XX_I2C1_SDA); - } - break; - case 2: - if (cpu_is_omap24xx()) { - omap_cfg_reg(J15_24XX_I2C2_SCL); - omap_cfg_reg(H19_24XX_I2C2_SDA); - } - break; + int scl, sda; + + if (cpu_class_is_omap1()) { + scl = I2C_SCL; + sda = I2C_SDA; + } else if (cpu_is_omap24xx()) { + scl = omap24xx_pins[bus][0]; + sda = omap24xx_pins[bus][1]; + } else if (cpu_is_omap34xx()) { + scl = omap34xx_pins[bus][0]; + sda = omap34xx_pins[bus][1]; + } else { + return; } + + omap_cfg_reg(sda); + omap_cfg_reg(scl); } int __init omap_register_i2c_bus(int bus_id, u32 clkrate, @@ -142,6 +159,6 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, res[1].start = irq; } - omap_i2c_mux_pins(bus_id); + omap_i2c_mux_pins(bus_id - 1); return platform_device_register(pdev); } diff --git a/arch/arm/plat-omap/include/mach/board-apollon.h b/arch/arm/plat-omap/include/mach/board-apollon.h index 731c858cf3fe..61bd5e8f09b1 100644 --- a/arch/arm/plat-omap/include/mach/board-apollon.h +++ b/arch/arm/plat-omap/include/mach/board-apollon.h @@ -29,12 +29,14 @@ #ifndef __ASM_ARCH_OMAP_APOLLON_H #define __ASM_ARCH_OMAP_APOLLON_H +#include <mach/cpu.h> + extern void apollon_mmc_init(void); static inline int apollon_plus(void) { /* The apollon plus has IDCODE revision 5 */ - return system_rev & 0xc0; + return omap_rev() & 0xc0; } /* Placeholder for APOLLON specific defines */ diff --git a/arch/arm/plat-omap/include/mach/board-h2.h b/arch/arm/plat-omap/include/mach/board-h2.h index 2a050e9be65f..15531c8dc0e6 100644 --- a/arch/arm/plat-omap/include/mach/board-h2.h +++ b/arch/arm/plat-omap/include/mach/board-h2.h @@ -29,13 +29,13 @@ #ifndef __ASM_ARCH_OMAP_H2_H #define __ASM_ARCH_OMAP_H2_H -/* Placeholder for H2 specific defines */ - /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ #define OMAP1610_ETHR_START 0x04000300 +#define H2_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) +# define H2_TPS_GPIO_MMC_PWR_EN (H2_TPS_GPIO_BASE + 3) + extern void h2_mmc_init(void); -extern void h2_mmc_slot_cover_handler(void *arg, int state); #endif /* __ASM_ARCH_OMAP_H2_H */ diff --git a/arch/arm/plat-omap/include/mach/board-ldp.h b/arch/arm/plat-omap/include/mach/board-ldp.h index 66e2746c04ca..f23399665212 100644 --- a/arch/arm/plat-omap/include/mach/board-ldp.h +++ b/arch/arm/plat-omap/include/mach/board-ldp.h @@ -32,5 +32,8 @@ extern void twl4030_bci_battery_init(void); #define TWL4030_IRQNUM INT_34XX_SYS_NIRQ - +#define LDP_SMC911X_CS 1 +#define LDP_SMC911X_GPIO 152 +#define DEBUG_BASE 0x08000000 +#define OMAP34XX_ETHR_START DEBUG_BASE #endif /* __ASM_ARCH_OMAP_LDP_H */ diff --git a/arch/arm/plat-omap/include/mach/board.h b/arch/arm/plat-omap/include/mach/board.h index c23c12ccb353..9466772fc7c8 100644 --- a/arch/arm/plat-omap/include/mach/board.h +++ b/arch/arm/plat-omap/include/mach/board.h @@ -16,7 +16,6 @@ /* Different peripheral ids */ #define OMAP_TAG_CLOCK 0x4f01 -#define OMAP_TAG_MMC 0x4f02 #define OMAP_TAG_SERIAL_CONSOLE 0x4f03 #define OMAP_TAG_USB 0x4f04 #define OMAP_TAG_LCD 0x4f05 @@ -35,27 +34,6 @@ struct omap_clock_config { u8 system_clock_type; }; -struct omap_mmc_conf { - unsigned enabled:1; - /* nomux means "standard" muxing is wrong on this board, and that - * board-specific code handled it before common init logic. - */ - unsigned nomux:1; - /* switch pin can be for card detect (default) or card cover */ - unsigned cover:1; - /* 4 wire signaling is optional, and is only used for SD/SDIO */ - unsigned wire4:1; - /* use the internal clock */ - unsigned internal_clock:1; - s16 power_pin; - s16 switch_pin; - s16 wp_pin; -}; - -struct omap_mmc_config { - struct omap_mmc_conf mmc[2]; -}; - struct omap_serial_console_config { u8 console_uart; u32 console_speed; diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index dc9886760577..269147f3836f 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -74,6 +74,7 @@ #define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) #define OMAP243X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) #define OMAP243X_CONTROL_IVA2_GEMCFG (OMAP2_CONTROL_GENERAL + 0x0198) +#define OMAP243X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x0230) /* 24xx-only CONTROL_GENERAL register offsets */ #define OMAP24XX_CONTROL_DEBOBS (OMAP2_CONTROL_GENERAL + 0x0000) @@ -140,6 +141,7 @@ #define OMAP343X_CONTROL_TEST_KEY_13 (OMAP2_CONTROL_GENERAL + 0x00fc) #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) #define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) +#define OMAP343X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x02b0) #define OMAP343X_CONTROL_TEMP_SENSOR (OMAP2_CONTROL_GENERAL + 0x02b4) /* @@ -154,11 +156,14 @@ * and the security mode (secure, non-secure, don't care) */ /* CONTROL_DEVCONF0 bits */ +#define OMAP2_MMCSDIO1ADPCLKISEL (1 << 24) /* MMC1 loop back clock */ #define OMAP24XX_USBSTANDBYCTRL (1 << 15) #define OMAP2_MCBSP2_CLKS_MASK (1 << 6) #define OMAP2_MCBSP1_CLKS_MASK (1 << 2) /* CONTROL_DEVCONF1 bits */ +#define OMAP243X_MMC1_ACTIVE_OVERWRITE (1 << 31) +#define OMAP2_MMCSDIO2ADPCLKISEL (1 << 6) /* MMC2 loop back clock */ #define OMAP2_MCBSP5_CLKS_MASK (1 << 4) /* > 242x */ #define OMAP2_MCBSP4_CLKS_MASK (1 << 2) /* > 242x */ #define OMAP2_MCBSP3_CLKS_MASK (1 << 0) /* > 242x */ @@ -172,6 +177,18 @@ #define OMAP2_SYSBOOT_1_MASK (1 << 1) #define OMAP2_SYSBOOT_0_MASK (1 << 0) +/* CONTROL_PBIAS_LITE bits */ +#define OMAP343X_PBIASLITESUPPLY_HIGH1 (1 << 15) +#define OMAP343X_PBIASLITEVMODEERROR1 (1 << 11) +#define OMAP343X_PBIASSPEEDCTRL1 (1 << 10) +#define OMAP343X_PBIASLITEPWRDNZ1 (1 << 9) +#define OMAP343X_PBIASLITEVMODE1 (1 << 8) +#define OMAP343X_PBIASLITESUPPLY_HIGH0 (1 << 7) +#define OMAP343X_PBIASLITEVMODEERROR0 (1 << 3) +#define OMAP2_PBIASSPEEDCTRL0 (1 << 2) +#define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) +#define OMAP2_PBIASLITEVMODE0 (1 << 0) + #ifndef __ASSEMBLY__ #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) extern void __iomem *omap_ctrl_base_get(void); diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index e0464187209d..b2062f1175de 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -28,13 +28,18 @@ struct omap_chip_id { u8 oc; + u8 type; }; #define OMAP_CHIP_INIT(x) { .oc = x } -extern unsigned int system_rev; - -#define omap2_cpu_rev() ((system_rev >> 12) & 0x0f) +/* + * omap_rev bits: + * CPU id bits (0730, 1510, 1710, 2422...) [31:16] + * CPU revision (See _REV_ defined in cpu.h) [15:08] + * CPU class bits (15xx, 16xx, 24xx, 34xx...) [07:00] + */ +unsigned int omap_rev(void); /* * Test if multicore OMAP support is needed @@ -108,7 +113,7 @@ extern unsigned int system_rev; * cpu_is_omap243x(): True for OMAP2430 * cpu_is_omap343x(): True for OMAP3430 */ -#define GET_OMAP_CLASS ((system_rev >> 24) & 0xff) +#define GET_OMAP_CLASS (omap_rev() & 0xff) #define IS_OMAP_CLASS(class, id) \ static inline int is_omap ##class (void) \ @@ -116,7 +121,7 @@ static inline int is_omap ##class (void) \ return (GET_OMAP_CLASS == (id)) ? 1 : 0; \ } -#define GET_OMAP_SUBCLASS ((system_rev >> 20) & 0x0fff) +#define GET_OMAP_SUBCLASS ((omap_rev() >> 20) & 0x0fff) #define IS_OMAP_SUBCLASS(subclass, id) \ static inline int is_omap ##subclass (void) \ @@ -226,7 +231,7 @@ IS_OMAP_SUBCLASS(343x, 0x343) * cpu_is_omap2430(): True for OMAP2430 * cpu_is_omap3430(): True for OMAP3430 */ -#define GET_OMAP_TYPE ((system_rev >> 16) & 0xffff) +#define GET_OMAP_TYPE ((omap_rev() >> 16) & 0xffff) #define IS_OMAP_TYPE(type, id) \ static inline int is_omap ##type (void) \ @@ -320,44 +325,20 @@ IS_OMAP_TYPE(3430, 0x3430) #define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx()) #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -/* - * Macros to detect silicon revision of OMAP2/3 processors. - * is_sil_rev_greater_than: true if passed cpu type & its rev is greater. - * is_sil_rev_lesser_than: true if passed cpu type & its rev is lesser. - * is_sil_rev_equal_to: true if passed cpu type & its rev is equal. - * get_sil_rev: return the silicon rev value. - */ -#define get_sil_omap_type(rev) ((rev & 0xffff0000) >> 16) -#define get_sil_revision(rev) ((rev & 0x0000f000) >> 12) -#define is_sil_rev_greater_than(rev) \ - ((get_sil_omap_type(system_rev) == get_sil_omap_type(rev)) && \ - (get_sil_revision(system_rev) > get_sil_revision(rev))) +/* Various silicon revisions for omap2 */ +#define OMAP242X_CLASS 0x24200024 +#define OMAP2420_REV_ES1_0 0x24200024 +#define OMAP2420_REV_ES2_0 0x24201024 -#define is_sil_rev_less_than(rev) \ - ((get_sil_omap_type(system_rev) == get_sil_omap_type(rev)) && \ - (get_sil_revision(system_rev) < get_sil_revision(rev))) +#define OMAP243X_CLASS 0x24300024 +#define OMAP2430_REV_ES1_0 0x24300024 -#define is_sil_rev_equal_to(rev) \ - ((get_sil_omap_type(system_rev) == get_sil_omap_type(rev)) && \ - (get_sil_revision(system_rev) == get_sil_revision(rev))) - -#define get_sil_rev() \ - get_sil_revision(system_rev) - -/* Various silicon macros defined here */ -#define OMAP242X_CLASS 0x24200000 -#define OMAP2420_REV_ES1_0 0x24200000 -#define OMAP2420_REV_ES2_0 0x24201000 - -#define OMAP243X_CLASS 0x24300000 -#define OMAP2430_REV_ES1_0 0x24300000 - -#define OMAP343X_CLASS 0x34300000 -#define OMAP3430_REV_ES1_0 0x34300000 -#define OMAP3430_REV_ES2_0 0x34301000 -#define OMAP3430_REV_ES2_1 0x34302000 -#define OMAP3430_REV_ES2_2 0x34303000 +#define OMAP343X_CLASS 0x34300034 +#define OMAP3430_REV_ES1_0 0x34300034 +#define OMAP3430_REV_ES2_0 0x34301034 +#define OMAP3430_REV_ES2_1 0x34302034 +#define OMAP3430_REV_ES3_0 0x34303034 /* * omap_chip bits @@ -382,23 +363,16 @@ IS_OMAP_TYPE(3430, 0x3430) #define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430) int omap_chip_is(struct omap_chip_id oci); - +int omap_type(void); /* * Macro to detect device type i.e. EMU/HS/TST/GP/BAD */ -#define DEVICE_TYPE_TEST 0 -#define DEVICE_TYPE_EMU 1 -#define DEVICE_TYPE_SEC 2 -#define DEVICE_TYPE_GP 3 -#define DEVICE_TYPE_BAD 4 - -#define get_device_type() ((system_rev & 0x700) >> 8) -#define is_device_type_test() (get_device_type() == DEVICE_TYPE_TEST) -#define is_device_type_emu() (get_device_type() == DEVICE_TYPE_EMU) -#define is_device_type_sec() (get_device_type() == DEVICE_TYPE_SEC) -#define is_device_type_gp() (get_device_type() == DEVICE_TYPE_GP) -#define is_device_type_bad() (get_device_type() == DEVICE_TYPE_BAD) +#define OMAP2_DEVICE_TYPE_TEST 0 +#define OMAP2_DEVICE_TYPE_EMU 1 +#define OMAP2_DEVICE_TYPE_SEC 2 +#define OMAP2_DEVICE_TYPE_GP 3 +#define OMAP2_DEVICE_TYPE_BAD 4 void omap2_check_revision(void); diff --git a/arch/arm/plat-omap/include/mach/gpio.h b/arch/arm/plat-omap/include/mach/gpio.h index 98e9008b7e9d..04e68e88f134 100644 --- a/arch/arm/plat-omap/include/mach/gpio.h +++ b/arch/arm/plat-omap/include/mach/gpio.h @@ -71,11 +71,6 @@ IH_GPIO_BASE + (nr)) extern int omap_gpio_init(void); /* Call from board init only */ -extern int omap_request_gpio(int gpio); -extern void omap_free_gpio(int gpio); -extern void omap_set_gpio_direction(int gpio, int is_input); -extern void omap_set_gpio_dataout(int gpio, int enable); -extern int omap_get_gpio_datain(int gpio); extern void omap2_gpio_prepare_for_retention(void); extern void omap2_gpio_resume_after_retention(void); extern void omap_set_gpio_debounce(int gpio, int enable); @@ -92,6 +87,16 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable); #include <linux/errno.h> #include <asm-generic/gpio.h> +static inline int omap_request_gpio(int gpio) +{ + return gpio_request(gpio, "FIXME"); +} + +static inline void omap_free_gpio(int gpio) +{ + gpio_free(gpio); +} + static inline int gpio_get_value(unsigned gpio) { return __gpio_get_value(gpio); @@ -109,16 +114,24 @@ static inline int gpio_cansleep(unsigned gpio) static inline int gpio_to_irq(unsigned gpio) { - if (gpio < (OMAP_MAX_GPIO_LINES + 16)) - return OMAP_GPIO_IRQ(gpio); - return -EINVAL; + return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned irq) { + int tmp; + + /* omap1 SOC mpuio */ if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16))) return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES; - return irq - IH_GPIO_BASE; + + /* SOC gpio */ + tmp = irq - IH_GPIO_BASE; + if (tmp < OMAP_MAX_GPIO_LINES) + return tmp; + + /* we don't supply reverse mappings for non-SOC gpios */ + return -EIO; } #endif diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h index adc83b7b8205..d92bf7964481 100644 --- a/arch/arm/plat-omap/include/mach/io.h +++ b/arch/arm/plat-omap/include/mach/io.h @@ -42,8 +42,8 @@ * We don't actually have real ISA nor PCI buses, but there is so many * drivers out there that might just work if we fake them... */ -#define __io(a) ((void __iomem *)(PCIO_BASE + (a))) -#define __mem_pci(a) (a) +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) /* * ---------------------------------------------------------------------------- @@ -51,8 +51,6 @@ * ---------------------------------------------------------------------------- */ -#define PCIO_BASE 0 - #if defined(CONFIG_ARCH_OMAP1) #define IO_PHYS 0xFFFB0000 diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h index d40cac60b959..211c9f6619e9 100644 --- a/arch/arm/plat-omap/include/mach/memory.h +++ b/arch/arm/plat-omap/include/mach/memory.h @@ -43,18 +43,7 @@ #endif /* - * Conversion between SDRAM and fake PCI bus, used by USB - * NOTE: Physical address must be converted to Local Bus address - * on OMAP-1510 only - */ - -/* * Bus address is physical address, except for OMAP-1510 Local Bus. - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -/* * OMAP-1510 bus address is translated into a Local Bus address if the * OMAP bus type is lbus. We do the address translation based on the * device overriding the defaults used in the dma-mapping API. @@ -74,16 +63,16 @@ #define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \ (dma_addr_t)virt_to_lbus(page_address(page)) : \ - (dma_addr_t)__virt_to_bus(page_address(page));}) + (dma_addr_t)__virt_to_phys(page_address(page));}) #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ lbus_to_virt(addr) : \ - __bus_to_virt(addr)); }) + __phys_to_virt(addr)); }) #define __arch_virt_to_dma(dev, addr) ({ unsigned long __addr = (unsigned long)(addr); \ (dma_addr_t) (is_lbus_device(dev) ? \ virt_to_lbus(__addr) : \ - __virt_to_bus(__addr)); }) + __virt_to_phys(__addr)); }) #endif /* CONFIG_ARCH_OMAP15XX */ diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index fc15d13058fc..031250f02805 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -17,12 +17,28 @@ #include <mach/board.h> +#define OMAP15XX_NR_MMC 1 +#define OMAP16XX_NR_MMC 2 +#define OMAP1_MMC_SIZE 0x080 +#define OMAP1_MMC1_BASE 0xfffb7800 +#define OMAP1_MMC2_BASE 0xfffb7c00 /* omap16xx only */ + +#define OMAP24XX_NR_MMC 2 +#define OMAP34XX_NR_MMC 3 +#define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE +#define HSMMC_SIZE 0x200 +#define OMAP2_MMC1_BASE 0x4809c000 +#define OMAP2_MMC2_BASE 0x480b4000 +#define OMAP3_MMC3_BASE 0x480ad000 +#define HSMMC3 (1 << 2) +#define HSMMC2 (1 << 1) +#define HSMMC1 (1 << 0) + #define OMAP_MMC_MAX_SLOTS 2 struct omap_mmc_platform_data { - struct omap_mmc_conf conf; - /* number of slots on board */ + /* number of slots per controller */ unsigned nr_slots:2; /* set if your board has components or wiring that limits the @@ -41,7 +57,31 @@ struct omap_mmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); + u64 dma_mask; + struct omap_mmc_slot_data { + + /* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC; + * 8 wire signaling is also optional, and is used with HSMMC + */ + u8 wires; + + /* + * nomux means "standard" muxing is wrong on this board, and + * that board-specific code handled it before common init logic. + */ + unsigned nomux:1; + + /* switch pin can be for card detect (default) or card cover */ + unsigned cover:1; + + /* use the internal clock */ + unsigned internal_clock:1; + s16 power_pin; + + int switch_pin; /* gpio (card detect) */ + int gpio_wp; /* gpio (write protect) */ + int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); int (* set_power)(struct device *dev, int slot, int power_on, int vdd); int (* get_ro)(struct device *dev, int slot); @@ -49,8 +89,8 @@ struct omap_mmc_platform_data { /* return MMC cover switch state, can be NULL if not supported. * * possible return values: - * 0 - open - * 1 - closed + * 0 - closed + * 1 - open */ int (* get_cover_state)(struct device *dev, int slot); @@ -66,9 +106,31 @@ struct omap_mmc_platform_data { } slots[OMAP_MMC_MAX_SLOTS]; }; -extern void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info); - /* called from board-specific card detection service routine */ extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed); +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ + defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) +void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers); +void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers); +int omap_mmc_add(int id, unsigned long base, unsigned long size, + unsigned int irq, struct omap_mmc_platform_data *data); +#else +static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers) +{ +} +static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers) +{ +} +static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, + unsigned int irq, struct omap_mmc_platform_data *data) +{ + return 0; +} + +#endif #endif diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h index 6bbf1789bed5..f4362b8682c7 100644 --- a/arch/arm/plat-omap/include/mach/mux.h +++ b/arch/arm/plat-omap/include/mach/mux.h @@ -632,6 +632,15 @@ enum omap24xx_index { AC7_2430_USB0HS_DATA7, /* 2430 McBSP */ + AD6_2430_MCBSP_CLKS, + + AB2_2430_MCBSP1_CLKR, + AD5_2430_MCBSP1_FSR, + AA1_2430_MCBSP1_DX, + AF3_2430_MCBSP1_DR, + AB3_2430_MCBSP1_FSX, + Y9_2430_MCBSP1_CLKX, + AC10_2430_MCBSP2_FSX, AD16_2430_MCBSP2_CLX, AE13_2430_MCBSP2_DX, @@ -641,6 +650,30 @@ enum omap24xx_index { AE13_2430_MCBSP2_DX_OFF, AD13_2430_MCBSP2_DR_OFF, + AC9_2430_MCBSP3_CLKX, + AE4_2430_MCBSP3_FSX, + AE2_2430_MCBSP3_DR, + AF4_2430_MCBSP3_DX, + + N3_2430_MCBSP4_CLKX, + AD23_2430_MCBSP4_DR, + AB25_2430_MCBSP4_DX, + AC25_2430_MCBSP4_FSX, + + AE16_2430_MCBSP5_CLKX, + AF12_2430_MCBSP5_FSX, + K7_2430_MCBSP5_DX, + M1_2430_MCBSP5_DR, + + /* 2430 McSPI*/ + Y18_2430_MCSPI1_CLK, + AD15_2430_MCSPI1_SIMO, + AE17_2430_MCSPI1_SOMI, + U1_2430_MCSPI1_CS0, + + /* Touchscreen GPIO */ + AF19_2430_GPIO_85, + }; enum omap34xx_index { @@ -749,6 +782,14 @@ enum omap34xx_index { AD2_3430_USB3FS_PHY_MM3_TXDAT, AC1_3430_USB3FS_PHY_MM3_TXEN_N, + /* 34xx GPIO + * - normally these are bidirectional, no internal pullup/pulldown + * - "_UP" suffix (GPIO3_UP) if internal pullup is configured + * - "_DOWN" suffix (GPIO3_DOWN) with internal pulldown + * - "_OUT" suffix (GPIO3_OUT) for output-only pins (unlike 24xx) + */ + AH8_34XX_GPIO29, + J25_34XX_GPIO170, }; struct omap_mux_cfg { diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index dcd9d16da2e9..be7bcaf2b832 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -24,6 +24,7 @@ #include <mach/sram.h> #include <mach/board.h> +#include <mach/cpu.h> #include <mach/control.h> @@ -87,7 +88,7 @@ static int is_sram_locked(void) int type = 0; if (cpu_is_omap242x()) - type = system_rev & OMAP2_DEVICETYPE_MASK; + type = omap_rev() & OMAP2_DEVICETYPE_MASK; if (type == GP_DEVICE) { /* RAMFW: R/W access to all initiators for all qualifier sets */ diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile index 198f3dde2be3..56021a72e10c 100644 --- a/arch/arm/plat-orion/Makefile +++ b/arch/arm/plat-orion/Makefile @@ -6,3 +6,5 @@ obj-y := irq.o pcie.o time.o obj-m := obj-n := obj- := + +obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c new file mode 100644 index 000000000000..967186425ca1 --- /dev/null +++ b/arch/arm/plat-orion/gpio.c @@ -0,0 +1,415 @@ +/* + * arch/arm/plat-orion/gpio.c + * + * Marvell Orion SoC GPIO handling. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <asm/gpio.h> + +static DEFINE_SPINLOCK(gpio_lock); +static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ +static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; + +static inline void __set_direction(unsigned pin, int input) +{ + u32 u; + + u = readl(GPIO_IO_CONF(pin)); + if (input) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_IO_CONF(pin)); +} + +static void __set_level(unsigned pin, int high) +{ + u32 u; + + u = readl(GPIO_OUT(pin)); + if (high) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_OUT(pin)); +} + + +/* + * GENERIC_GPIO primitives. + */ +int gpio_direction_input(unsigned pin) +{ + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might not have used gpio_request(), + * so flag this pin as requested now. + */ + if (gpio_label[pin] == NULL) + gpio_label[pin] = "?"; + + /* + * Configure GPIO direction. + */ + __set_direction(pin, 1); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned pin, int value) +{ + unsigned long flags; + u32 u; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might not have used gpio_request(), + * so flag this pin as requested now. + */ + if (gpio_label[pin] == NULL) + gpio_label[pin] = "?"; + + /* + * Disable blinking. + */ + u = readl(GPIO_BLINK_EN(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + /* + * Configure GPIO output value. + */ + __set_level(pin, value); + + /* + * Configure GPIO direction. + */ + __set_direction(pin, 0); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned pin) +{ + int val; + + if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) + val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); + else + val = readl(GPIO_OUT(pin)); + + return (val >> (pin & 31)) & 1; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned pin, int value) +{ + unsigned long flags; + u32 u; + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Disable blinking. + */ + u = readl(GPIO_BLINK_EN(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + /* + * Configure GPIO output value. + */ + __set_level(pin, value); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_request(unsigned pin, const char *label) +{ + unsigned long flags; + int ret; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + if (gpio_label[pin] == NULL) { + gpio_label[pin] = label ? label : "?"; + ret = 0; + } else { + pr_debug("%s: GPIO %d already used as %s\n", + __func__, pin, gpio_label[pin]); + ret = -EBUSY; + } + spin_unlock_irqrestore(&gpio_lock, flags); + + return ret; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned pin) +{ + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return; + } + + if (gpio_label[pin] == NULL) + pr_warning("%s: GPIO %d already freed\n", __func__, pin); + else + gpio_label[pin] = NULL; +} +EXPORT_SYMBOL(gpio_free); + + +/* + * Orion-specific GPIO API extensions. + */ +void __init orion_gpio_set_unused(unsigned pin) +{ + /* + * Configure as output, drive low. + */ + __set_level(pin, 0); + __set_direction(pin, 0); +} + +void __init orion_gpio_set_valid(unsigned pin, int valid) +{ + if (valid) + __set_bit(pin, gpio_valid); + else + __clear_bit(pin, gpio_valid); +} + +void orion_gpio_set_blink(unsigned pin, int blink) +{ + unsigned long flags; + u32 u; + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Set output value to zero. + */ + __set_level(pin, 0); + + u = readl(GPIO_BLINK_EN(pin)); + if (blink) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(orion_gpio_set_blink); + + +/***************************************************************************** + * Orion GPIO IRQ + * + * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same + * value of the line or the opposite value. + * + * Level IRQ handlers: DATA_IN is used directly as cause register. + * Interrupt are masked by LEVEL_MASK registers. + * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. + * Interrupt are masked by EDGE_MASK registers. + * Both-edge handlers: Similar to regular Edge handlers, but also swaps + * the polarity to catch the next line transaction. + * This is a race condition that might not perfectly + * work on some use cases. + * + * Every eight GPIO lines are grouped (OR'ed) before going up to main + * cause register. + * + * EDGE cause mask + * data-in /--------| |-----| |----\ + * -----| |----- ---- to main cause reg + * X \----------------| |----/ + * polarity LEVEL mask + * + ****************************************************************************/ +static void gpio_irq_edge_ack(u32 irq) +{ + int pin = irq_to_gpio(irq); + + writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); +} + +static void gpio_irq_edge_mask(u32 irq) +{ + int pin = irq_to_gpio(irq); + u32 u; + + u = readl(GPIO_EDGE_MASK(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_EDGE_MASK(pin)); +} + +static void gpio_irq_edge_unmask(u32 irq) +{ + int pin = irq_to_gpio(irq); + u32 u; + + u = readl(GPIO_EDGE_MASK(pin)); + u |= 1 << (pin & 31); + writel(u, GPIO_EDGE_MASK(pin)); +} + +static void gpio_irq_level_mask(u32 irq) +{ + int pin = irq_to_gpio(irq); + u32 u; + + u = readl(GPIO_LEVEL_MASK(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_LEVEL_MASK(pin)); +} + +static void gpio_irq_level_unmask(u32 irq) +{ + int pin = irq_to_gpio(irq); + u32 u; + + u = readl(GPIO_LEVEL_MASK(pin)); + u |= 1 << (pin & 31); + writel(u, GPIO_LEVEL_MASK(pin)); +} + +static int gpio_irq_set_type(u32 irq, u32 type) +{ + int pin = irq_to_gpio(irq); + struct irq_desc *desc; + u32 u; + + u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)); + if (!u) { + printk(KERN_ERR "orion gpio_irq_set_type failed " + "(irq %d, pin %d).\n", irq, pin); + return -EINVAL; + } + + desc = irq_desc + irq; + + /* + * Set edge/level type. + */ + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + desc->chip = &orion_gpio_irq_edge_chip; + } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + desc->chip = &orion_gpio_irq_level_chip; + } else { + printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type); + return -EINVAL; + } + + /* + * Configure interrupt polarity. + */ + if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { + u = readl(GPIO_IN_POL(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_IN_POL(pin)); + } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { + u = readl(GPIO_IN_POL(pin)); + u |= 1 << (pin & 31); + writel(u, GPIO_IN_POL(pin)); + } else if (type == IRQ_TYPE_EDGE_BOTH) { + u32 v; + + v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin)); + + /* + * set initial polarity based on current input level + */ + u = readl(GPIO_IN_POL(pin)); + if (v & (1 << (pin & 31))) + u |= 1 << (pin & 31); /* falling */ + else + u &= ~(1 << (pin & 31)); /* rising */ + writel(u, GPIO_IN_POL(pin)); + } + + desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type; + + return 0; +} + +struct irq_chip orion_gpio_irq_edge_chip = { + .name = "orion_gpio_irq_edge", + .ack = gpio_irq_edge_ack, + .mask = gpio_irq_edge_mask, + .unmask = gpio_irq_edge_unmask, + .set_type = gpio_irq_set_type, +}; + +struct irq_chip orion_gpio_irq_level_chip = { + .name = "orion_gpio_irq_level", + .mask = gpio_irq_level_mask, + .mask_ack = gpio_irq_level_mask, + .unmask = gpio_irq_level_unmask, + .set_type = gpio_irq_set_type, +}; + +void orion_gpio_irq_handler(int pinoff) +{ + u32 cause; + int pin; + + cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff)); + cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff)); + + for (pin = pinoff; pin < pinoff + 8; pin++) { + int irq = gpio_to_irq(pin); + struct irq_desc *desc = irq_desc + irq; + + if (!(cause & (1 << (pin & 31)))) + continue; + + if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + /* Swap polarity (race with GPIO line) */ + u32 polarity; + + polarity = readl(GPIO_IN_POL(pin)); + polarity ^= 1 << (pin & 31); + writel(polarity, GPIO_IN_POL(pin)); + } + desc_handle_irq(irq, desc); + } +} diff --git a/arch/arm/plat-orion/include/plat/ehci-orion.h b/arch/arm/plat-orion/include/plat/ehci-orion.h index 64343051095a..4ec668e77460 100644 --- a/arch/arm/plat-orion/include/plat/ehci-orion.h +++ b/arch/arm/plat-orion/include/plat/ehci-orion.h @@ -11,8 +11,16 @@ #include <linux/mbus.h> +enum orion_ehci_phy_ver { + EHCI_PHY_ORION, + EHCI_PHY_DD, + EHCI_PHY_KW, + EHCI_PHY_NA, +}; + struct orion_ehci_data { struct mbus_dram_target_info *dram; + enum orion_ehci_phy_ver phy_version; }; diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h new file mode 100644 index 000000000000..54deaf274b52 --- /dev/null +++ b/arch/arm/plat-orion/include/plat/gpio.h @@ -0,0 +1,39 @@ +/* + * arch/arm/plat-orion/include/plat/gpio.h + * + * Marvell Orion SoC GPIO handling. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_GPIO_H +#define __PLAT_GPIO_H + +/* + * GENERIC_GPIO primitives. + */ +int gpio_request(unsigned pin, const char *label); +void gpio_free(unsigned pin); +int gpio_direction_input(unsigned pin); +int gpio_direction_output(unsigned pin, int value); +int gpio_get_value(unsigned pin); +void gpio_set_value(unsigned pin, int value); + +/* + * Orion-specific GPIO API extensions. + */ +void orion_gpio_set_unused(unsigned pin); +void orion_gpio_set_valid(unsigned pin, int valid); +void orion_gpio_set_blink(unsigned pin, int blink); + +/* + * GPIO interrupt handling. + */ +extern struct irq_chip orion_gpio_irq_edge_chip; +extern struct irq_chip orion_gpio_irq_level_chip; +void orion_gpio_irq_handler(int irqoff); + + +#endif diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig index 31656c33e05e..de9383814e5e 100644 --- a/arch/arm/plat-s3c/Kconfig +++ b/arch/arm/plat-s3c/Kconfig @@ -6,34 +6,32 @@ config PLAT_S3C bool - depends on ARCH_S3C2410 - default y if ARCH_S3C2410 + depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX + default y select NO_IOPORT help Base platform code for any Samsung S3C device # low-level serial option nodes +if PLAT_S3C + config CPU_LLSERIAL_S3C2410_ONLY bool - depends on ARCH_S3C2410 default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440 config CPU_LLSERIAL_S3C2440_ONLY bool - depends on ARCH_S3C2410 default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410 config CPU_LLSERIAL_S3C2410 bool - depends on ARCH_S3C2410 help Selected if there is an S3C2410 (or register compatible) serial low-level implementation needed config CPU_LLSERIAL_S3C2440 bool - depends on ARCH_S3C2410 help Selected if there is an S3C2440 (or register compatible) serial low-level implementation needed @@ -44,7 +42,7 @@ comment "Boot options" config S3C_BOOT_WATCHDOG bool "S3C Initialisation watchdog" - depends on PLAT_S3C && S3C2410_WATCHDOG + depends on S3C2410_WATCHDOG help Say y to enable the watchdog during the kernel decompression stage. If the kernel fails to uncompress, then the watchdog @@ -52,16 +50,22 @@ config S3C_BOOT_WATCHDOG config S3C_BOOT_ERROR_RESET bool "S3C Reboot on decompression error" - depends on PLAT_S3C help Say y here to use the watchdog to reset the system if the kernel decompressor detects an error during decompression. +config S3C_BOOT_UART_FORCE_FIFO + bool "Force UART FIFO on during boot process" + default y + help + Say Y here to force the UART FIFOs on during the kernel + uncompressor + comment "Power management" config S3C2410_PM_DEBUG bool "S3C2410 PM Suspend debug" - depends on PLAT_S3C && PM + depends on PM help Say Y here if you want verbose debugging from the PM Suspend and Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> @@ -69,7 +73,7 @@ config S3C2410_PM_DEBUG config S3C2410_PM_CHECK bool "S3C2410 PM Suspend Memory CRC" - depends on PLAT_S3C && PM && CRC32 + depends on PM && CRC32 help Enable the PM code's memory area checksum over sleep. This option will generate CRCs of all blocks of memory, and store them before @@ -83,7 +87,7 @@ config S3C2410_PM_CHECK config S3C2410_PM_CHECK_CHUNKSIZE int "S3C2410 PM Suspend CRC Chunksize (KiB)" - depends on PLAT_S3C && PM && S3C2410_PM_CHECK + depends on PM && S3C2410_PM_CHECK default 64 help Set the chunksize in Kilobytes of the CRC for checking memory @@ -95,10 +99,77 @@ config S3C2410_PM_CHECK_CHUNKSIZE config S3C_LOWLEVEL_UART_PORT int "S3C UART to use for low-level messages" - depends on PLAT_S3C default 0 help Choice of which UART port to use for the low-level messages, such as the `Uncompressing...` at start time. The value of this configuration should be between zero and two. The port must have been initialised by the boot-loader before use. + +# options for gpiolib support + +config S3C_GPIO_SPACE + int "Space between gpio banks" + default 0 + help + Add a number of spare GPIO entries between each bank for debugging + purposes. This allows any problems where an counter overflows from + one bank to another to be caught, at the expense of using a little + more memory. + +config S3C_GPIO_TRACK + bool + help + Internal configuration option to enable the s3c specific gpio + chip tracking if the platform requires it. + +config S3C_GPIO_PULL_UPDOWN + bool + help + Internal configuration to enable the correct GPIO pull helper + +config S3C_GPIO_PULL_DOWN + bool + help + Internal configuration to enable the correct GPIO pull helper + +config S3C_GPIO_PULL_UP + bool + help + Internal configuration to enable the correct GPIO pull helper + +config S3C_GPIO_CFG_S3C24XX + bool + help + Internal configuration to enable S3C24XX style GPIO configuration + functions. + +config S3C_GPIO_CFG_S3C64XX + bool + help + Internal configuration to enable S3C64XX style GPIO configuration + functions. + +# device definitions to compile in + +config S3C_DEV_HSMMC + bool + help + Compile in platform device definitions for HSMMC code + +config S3C_DEV_HSMMC1 + bool + help + Compile in platform device definitions for HSMMC channel 1 + +config S3C_DEV_I2C1 + bool + help + Compile in platform device definitions for I2C channel 1 + +config S3C_DEV_FB + bool + help + Compile in platform device definition for framebuffer + +endif diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile index f03d7b35ba37..39195f972d5e 100644 --- a/arch/arm/plat-s3c/Makefile +++ b/arch/arm/plat-s3c/Makefile @@ -1,3 +1,27 @@ -# dummy makefile, currently just including asm/arm/plat-s3c/include/plat +# arch/arm/plat-s3c/Makefile +# +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 -obj-n := dummy.o +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for all Samsung SoCs + +obj-y += init.o +obj-y += time.o +obj-y += clock.o +obj-y += pwm-clock.o +obj-y += gpio.o +obj-y += gpio-config.o + +# devices + +obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o +obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o +obj-y += dev-i2c0.o +obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o +obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o diff --git a/arch/arm/plat-s3c/clock.c b/arch/arm/plat-s3c/clock.c new file mode 100644 index 000000000000..b6be76e2fe51 --- /dev/null +++ b/arch/arm/plat-s3c/clock.c @@ -0,0 +1,368 @@ +/* linux/arch/arm/plat-s3c24xx/clock.c + * + * Copyright (c) 2004-2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX Core clock control support + * + * Based on, and code from linux/arch/arm/mach-versatile/clock.c + ** + ** Copyright (C) 2004 ARM Limited. + ** Written by Deep Blue Solutions Limited. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/clk.h> +#include <linux/spinlock.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <asm/irq.h> + +#include <plat/cpu-freq.h> + +#include <plat/clock.h> +#include <plat/cpu.h> + +/* clock information */ + +static LIST_HEAD(clocks); + +/* We originally used an mutex here, but some contexts (see resume) + * are calling functions such as clk_set_parent() with IRQs disabled + * causing an BUG to be triggered. + */ +DEFINE_SPINLOCK(clocks_lock); + +/* enable and disable calls for use with the clk struct */ + +static int clk_null_enable(struct clk *clk, int enable) +{ + return 0; +} + +/* Clock API calls */ + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *p; + struct clk *clk = ERR_PTR(-ENOENT); + int idno; + + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; + + spin_lock(&clocks_lock); + + list_for_each_entry(p, &clocks, list) { + if (p->id == idno && + strcmp(id, p->name) == 0 && + try_module_get(p->owner)) { + clk = p; + break; + } + } + + /* check for the case where a device was supplied, but the + * clock that was being searched for is not device specific */ + + if (IS_ERR(clk)) { + list_for_each_entry(p, &clocks, list) { + if (p->id == -1 && strcmp(id, p->name) == 0 && + try_module_get(p->owner)) { + clk = p; + break; + } + } + } + + spin_unlock(&clocks_lock); + return clk; +} + +void clk_put(struct clk *clk) +{ + module_put(clk->owner); +} + +int clk_enable(struct clk *clk) +{ + if (IS_ERR(clk) || clk == NULL) + return -EINVAL; + + clk_enable(clk->parent); + + spin_lock(&clocks_lock); + + if ((clk->usage++) == 0) + (clk->enable)(clk, 1); + + spin_unlock(&clocks_lock); + return 0; +} + +void clk_disable(struct clk *clk) +{ + if (IS_ERR(clk) || clk == NULL) + return; + + spin_lock(&clocks_lock); + + if ((--clk->usage) == 0) + (clk->enable)(clk, 0); + + spin_unlock(&clocks_lock); + clk_disable(clk->parent); +} + + +unsigned long clk_get_rate(struct clk *clk) +{ + if (IS_ERR(clk)) + return 0; + + if (clk->rate != 0) + return clk->rate; + + if (clk->get_rate != NULL) + return (clk->get_rate)(clk); + + if (clk->parent != NULL) + return clk_get_rate(clk->parent); + + return clk->rate; +} + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (!IS_ERR(clk) && clk->round_rate) + return (clk->round_rate)(clk, rate); + + return rate; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret; + + if (IS_ERR(clk)) + return -EINVAL; + + /* We do not default just do a clk->rate = rate as + * the clock may have been made this way by choice. + */ + + WARN_ON(clk->set_rate == NULL); + + if (clk->set_rate == NULL) + return -EINVAL; + + spin_lock(&clocks_lock); + ret = (clk->set_rate)(clk, rate); + spin_unlock(&clocks_lock); + + return ret; +} + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = 0; + + if (IS_ERR(clk)) + return -EINVAL; + + spin_lock(&clocks_lock); + + if (clk->set_parent) + ret = (clk->set_parent)(clk, parent); + + spin_unlock(&clocks_lock); + + return ret; +} + +EXPORT_SYMBOL(clk_get); +EXPORT_SYMBOL(clk_put); +EXPORT_SYMBOL(clk_enable); +EXPORT_SYMBOL(clk_disable); +EXPORT_SYMBOL(clk_get_rate); +EXPORT_SYMBOL(clk_round_rate); +EXPORT_SYMBOL(clk_set_rate); +EXPORT_SYMBOL(clk_get_parent); +EXPORT_SYMBOL(clk_set_parent); + +/* base clocks */ + +static int clk_default_setrate(struct clk *clk, unsigned long rate) +{ + clk->rate = rate; + return 0; +} + +struct clk clk_xtal = { + .name = "xtal", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, +}; + +struct clk clk_ext = { + .name = "ext", + .id = -1, +}; + +struct clk clk_epll = { + .name = "epll", + .id = -1, +}; + +struct clk clk_mpll = { + .name = "mpll", + .id = -1, + .set_rate = clk_default_setrate, +}; + +struct clk clk_upll = { + .name = "upll", + .id = -1, + .parent = NULL, + .ctrlbit = 0, +}; + +struct clk clk_f = { + .name = "fclk", + .id = -1, + .rate = 0, + .parent = &clk_mpll, + .ctrlbit = 0, + .set_rate = clk_default_setrate, +}; + +struct clk clk_h = { + .name = "hclk", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, + .set_rate = clk_default_setrate, +}; + +struct clk clk_p = { + .name = "pclk", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, + .set_rate = clk_default_setrate, +}; + +struct clk clk_usb_bus = { + .name = "usb-bus", + .id = -1, + .rate = 0, + .parent = &clk_upll, +}; + + + +struct clk s3c24xx_uclk = { + .name = "uclk", + .id = -1, +}; + +/* initialise the clock system */ + +int s3c24xx_register_clock(struct clk *clk) +{ + clk->owner = THIS_MODULE; + + if (clk->enable == NULL) + clk->enable = clk_null_enable; + + /* add to the list of available clocks */ + + /* Quick check to see if this clock has already been registered. */ + BUG_ON(clk->list.prev != clk->list.next); + + spin_lock(&clocks_lock); + list_add(&clk->list, &clocks); + spin_unlock(&clocks_lock); + + return 0; +} + +int s3c24xx_register_clocks(struct clk **clks, int nr_clks) +{ + int fails = 0; + + for (; nr_clks > 0; nr_clks--, clks++) { + if (s3c24xx_register_clock(*clks) < 0) + fails++; + } + + return fails; +} + +/* initalise all the clocks */ + +int __init s3c24xx_register_baseclocks(unsigned long xtal) +{ + printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); + + clk_xtal.rate = xtal; + + /* register our clocks */ + + if (s3c24xx_register_clock(&clk_xtal) < 0) + printk(KERN_ERR "failed to register master xtal\n"); + + if (s3c24xx_register_clock(&clk_mpll) < 0) + printk(KERN_ERR "failed to register mpll clock\n"); + + if (s3c24xx_register_clock(&clk_upll) < 0) + printk(KERN_ERR "failed to register upll clock\n"); + + if (s3c24xx_register_clock(&clk_f) < 0) + printk(KERN_ERR "failed to register cpu fclk\n"); + + if (s3c24xx_register_clock(&clk_h) < 0) + printk(KERN_ERR "failed to register cpu hclk\n"); + + if (s3c24xx_register_clock(&clk_p) < 0) + printk(KERN_ERR "failed to register cpu pclk\n"); + + return 0; +} + diff --git a/arch/arm/plat-s3c/dev-fb.c b/arch/arm/plat-s3c/dev-fb.c new file mode 100644 index 000000000000..0454b8ec02e2 --- /dev/null +++ b/arch/arm/plat-s3c/dev-fb.c @@ -0,0 +1,72 @@ +/* linux/arch/arm/plat-s3c/dev-fb.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series device definition for framebuffer device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/fb.h> + +#include <mach/map.h> +#include <mach/regs-fb.h> + +#include <plat/fb.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_fb_resource[] = { + [0] = { + .start = S3C_PA_FB, + .end = S3C_PA_FB + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_LCD_VSYNC, + .end = IRQ_LCD_VSYNC, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_LCD_FIFO, + .end = IRQ_LCD_FIFO, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_LCD_SYSTEM, + .end = IRQ_LCD_SYSTEM, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_fb = { + .name = "s3c-fb", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_fb_resource), + .resource = s3c_fb_resource, + .dev.dma_mask = &s3c_device_fb.dev.coherent_dma_mask, + .dev.coherent_dma_mask = 0xffffffffUL, +}; + +void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd) +{ + struct s3c_fb_platdata *npd; + + if (!pd) { + printk(KERN_ERR "%s: no platform data\n", __func__); + return; + } + + npd = kmemdup(pd, sizeof(struct s3c_fb_platdata), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + + s3c_device_fb.dev.platform_data = npd; +} diff --git a/arch/arm/plat-s3c/dev-hsmmc.c b/arch/arm/plat-s3c/dev-hsmmc.c new file mode 100644 index 000000000000..4c05b39810e2 --- /dev/null +++ b/arch/arm/plat-s3c/dev-hsmmc.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-s3c/dev-hsmmc.c + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series device definition for hsmmc devices + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/mmc/host.h> + +#include <mach/map.h> +#include <plat/sdhci.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +#define S3C_SZ_HSMMC (0x1000) + +static struct resource s3c_hsmmc_resource[] = { + [0] = { + .start = S3C_PA_HSMMC0, + .end = S3C_PA_HSMMC0 + S3C_SZ_HSMMC - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_HSMMC0, + .end = IRQ_HSMMC0, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL; + +struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = { + .max_width = 4, + .host_caps = (MMC_CAP_4_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), +}; + +struct platform_device s3c_device_hsmmc0 = { + .name = "s3c-sdhci", + .id = 0, + .num_resources = ARRAY_SIZE(s3c_hsmmc_resource), + .resource = s3c_hsmmc_resource, + .dev = { + .dma_mask = &s3c_device_hsmmc_dmamask, + .coherent_dma_mask = 0xffffffffUL, + .platform_data = &s3c_hsmmc0_def_platdata, + }, +}; + +void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) +{ + struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; + + set->max_width = pd->max_width; + + if (pd->cfg_gpio) + set->cfg_gpio = pd->cfg_gpio; + if (pd->cfg_card) + set->cfg_card = pd->cfg_card; +} diff --git a/arch/arm/plat-s3c/dev-hsmmc1.c b/arch/arm/plat-s3c/dev-hsmmc1.c new file mode 100644 index 000000000000..e49bc4cd0ee6 --- /dev/null +++ b/arch/arm/plat-s3c/dev-hsmmc1.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-s3c/dev-hsmmc1.c + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series device definition for hsmmc device 1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/mmc/host.h> + +#include <mach/map.h> +#include <plat/sdhci.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +#define S3C_SZ_HSMMC (0x1000) + +static struct resource s3c_hsmmc1_resource[] = { + [0] = { + .start = S3C_PA_HSMMC1, + .end = S3C_PA_HSMMC1 + S3C_SZ_HSMMC - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_HSMMC1, + .end = IRQ_HSMMC1, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 s3c_device_hsmmc1_dmamask = 0xffffffffUL; + +struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = { + .max_width = 4, + .host_caps = (MMC_CAP_4_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), +}; + +struct platform_device s3c_device_hsmmc1 = { + .name = "s3c-sdhci", + .id = 1, + .num_resources = ARRAY_SIZE(s3c_hsmmc1_resource), + .resource = s3c_hsmmc1_resource, + .dev = { + .dma_mask = &s3c_device_hsmmc1_dmamask, + .coherent_dma_mask = 0xffffffffUL, + .platform_data = &s3c_hsmmc1_def_platdata, + }, +}; + +void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) +{ + struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; + + set->max_width = pd->max_width; + + if (pd->cfg_gpio) + set->cfg_gpio = pd->cfg_gpio; + if (pd->cfg_card) + set->cfg_card = pd->cfg_card; +} diff --git a/arch/arm/plat-s3c/dev-i2c0.c b/arch/arm/plat-s3c/dev-i2c0.c new file mode 100644 index 000000000000..2c0128c77c6e --- /dev/null +++ b/arch/arm/plat-s3c/dev-i2c0.c @@ -0,0 +1,71 @@ +/* linux/arch/arm/plat-s3c/dev-i2c0.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series device definition for i2c device 0 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC, + .end = S3C_PA_IIC + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC, + .end = IRQ_IIC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c0 = { + .name = "s3c2410-i2c", +#ifdef CONFIG_S3C_DEV_I2C1 + .id = 0, +#else + .id = -1, +#endif + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { + .flags = 0, + .slave_addr = 0x10, + .bus_freq = 100*1000, + .max_freq = 400*1000, + .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON, +}; + +void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data0; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c0_cfg_gpio; + + s3c_device_i2c0.dev.platform_data = npd; +} diff --git a/arch/arm/plat-s3c/dev-i2c1.c b/arch/arm/plat-s3c/dev-i2c1.c new file mode 100644 index 000000000000..9658fb0aec95 --- /dev/null +++ b/arch/arm/plat-s3c/dev-i2c1.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-s3c/dev-i2c1.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series device definition for i2c device 1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC1, + .end = S3C_PA_IIC1 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC1, + .end = IRQ_IIC1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c1 = { + .name = "s3c2410-i2c", + .id = 1, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data1 __initdata = { + .flags = 0, + .bus_num = 1, + .slave_addr = 0x10, + .bus_freq = 100*1000, + .max_freq = 400*1000, + .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON, +}; + +void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data1; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c1_cfg_gpio; + + s3c_device_i2c1.dev.platform_data = npd; +} diff --git a/arch/arm/plat-s3c/gpio-config.c b/arch/arm/plat-s3c/gpio-config.c new file mode 100644 index 000000000000..7642b975a998 --- /dev/null +++ b/arch/arm/plat-s3c/gpio-config.c @@ -0,0 +1,163 @@ +/* linux/arch/arm/plat-s3c/gpio-config.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series GPIO configuration core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/io.h> + +#include <mach/gpio-core.h> +#include <plat/gpio-cfg.h> +#include <plat/gpio-cfg-helpers.h> + +int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned long flags; + int offset; + int ret; + + if (!chip) + return -EINVAL; + + offset = pin - chip->chip.base; + + local_irq_save(flags); + ret = s3c_gpio_do_setcfg(chip, offset, config); + local_irq_restore(flags); + + return ret; +} + +int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned long flags; + int offset, ret; + + if (!chip) + return -EINVAL; + + offset = pin - chip->chip.base; + + local_irq_save(flags); + ret = s3c_gpio_do_setpull(chip, offset, pull); + local_irq_restore(flags); + + return ret; +} + +#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX +int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg) +{ + void __iomem *reg = chip->base; + unsigned int shift = off; + u32 con; + + if (s3c_gpio_is_cfg_special(cfg)) { + cfg &= 0xf; + + /* Map output to 0, and SFN2 to 1 */ + cfg -= 1; + if (cfg > 1) + return -EINVAL; + + cfg <<= shift; + } + + con = __raw_readl(reg); + con &= ~(0x1 << shift); + con |= cfg; + __raw_writel(con, reg); + + return 0; +} + +int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg) +{ + void __iomem *reg = chip->base; + unsigned int shift = off * 2; + u32 con; + + if (s3c_gpio_is_cfg_special(cfg)) { + cfg &= 0xf; + if (cfg > 3) + return -EINVAL; + + cfg <<= shift; + } + + con = __raw_readl(reg); + con &= ~(0x3 << shift); + con |= cfg; + __raw_writel(con, reg); + + return 0; +} +#endif + +#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX +int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg) +{ + void __iomem *reg = chip->base; + unsigned int shift = (off & 7) * 4; + u32 con; + + if (off < 8 && chip->chip.ngpio >= 8) + reg -= 4; + + if (s3c_gpio_is_cfg_special(cfg)) { + cfg &= 0xf; + cfg <<= shift; + } + + con = __raw_readl(reg); + con &= ~(0xf << shift); + con |= cfg; + __raw_writel(con, reg); + + return 0; +} +#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ + +#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN +int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + void __iomem *reg = chip->base + 0x08; + int shift = off * 2; + u32 pup; + + pup = __raw_readl(reg); + pup &= ~(3 << shift); + pup |= pull << shift; + __raw_writel(pup, reg); + + return 0; +} + +s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, + unsigned int off) +{ + void __iomem *reg = chip->base + 0x08; + int shift = off * 2; + u32 pup = __raw_readl(reg); + + pup >>= shift; + pup &= 0x3; + return (__force s3c_gpio_pull_t)pup; +} +#endif diff --git a/arch/arm/plat-s3c/gpio.c b/arch/arm/plat-s3c/gpio.c new file mode 100644 index 000000000000..d71dd6d9ce5c --- /dev/null +++ b/arch/arm/plat-s3c/gpio.c @@ -0,0 +1,147 @@ +/* linux/arch/arm/plat-s3c/gpio.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series GPIO core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <plat/gpio-core.h> + +#ifdef CONFIG_S3C_GPIO_TRACK +struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; + +static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip) +{ + unsigned int gpn; + int i; + + gpn = chip->chip.base; + for (i = 0; i < chip->chip.ngpio; i++, gpn++) { + BUG_ON(gpn > ARRAY_SIZE(s3c_gpios)); + s3c_gpios[gpn] = chip; + } +} +#endif /* CONFIG_S3C_GPIO_TRACK */ + +/* Default routines for controlling GPIO, based on the original S3C24XX + * GPIO functions which deal with the case where each gpio bank of the + * chip is as following: + * + * base + 0x00: Control register, 2 bits per gpio + * gpio n: 2 bits starting at (2*n) + * 00 = input, 01 = output, others mean special-function + * base + 0x04: Data register, 1 bit per gpio + * bit n: data bit n +*/ + +static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long con; + + local_irq_save(flags); + + con = __raw_readl(base + 0x00); + con &= ~(3 << (offset * 2)); + + __raw_writel(con, base + 0x00); + + local_irq_restore(flags); + return 0; +} + +static int s3c_gpiolib_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long dat; + unsigned long con; + + local_irq_save(flags); + + dat = __raw_readl(base + 0x04); + dat &= ~(1 << offset); + if (value) + dat |= 1 << offset; + __raw_writel(dat, base + 0x04); + + con = __raw_readl(base + 0x00); + con &= ~(3 << (offset * 2)); + con |= 1 << (offset * 2); + + __raw_writel(con, base + 0x00); + __raw_writel(dat, base + 0x04); + + local_irq_restore(flags); + return 0; +} + +static void s3c_gpiolib_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long flags; + unsigned long dat; + + local_irq_save(flags); + + dat = __raw_readl(base + 0x04); + dat &= ~(1 << offset); + if (value) + dat |= 1 << offset; + __raw_writel(dat, base + 0x04); + + local_irq_restore(flags); +} + +static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + unsigned long val; + + val = __raw_readl(ourchip->base + 0x04); + val >>= offset; + val &= 1; + + return val; +} + +__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) +{ + struct gpio_chip *gc = &chip->chip; + int ret; + + BUG_ON(!chip->base); + BUG_ON(!gc->label); + BUG_ON(!gc->ngpio); + + if (!gc->direction_input) + gc->direction_input = s3c_gpiolib_input; + if (!gc->direction_output) + gc->direction_output = s3c_gpiolib_output; + if (!gc->set) + gc->set = s3c_gpiolib_set; + if (!gc->get) + gc->get = s3c_gpiolib_get; + + /* gpiochip_add() prints own failure message on error. */ + ret = gpiochip_add(gc); + if (ret >= 0) + s3c_gpiolib_track(chip); +} diff --git a/arch/arm/plat-s3c/include/mach/io.h b/arch/arm/plat-s3c/include/mach/io.h new file mode 100644 index 000000000000..f6a53631b665 --- /dev/null +++ b/arch/arm/plat-s3c/include/mach/io.h @@ -0,0 +1,18 @@ +/* arch/arm/plat-s3c/include/mach/io.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben-linux@fluff.org> + * + * Default IO routines for plat-s3c based systems, such as S3C24A0 + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* No current ISA/PCI bus support. */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#define IO_SPACE_LIMIT (0xFFFFFFFF) + +#endif diff --git a/arch/arm/mach-s3c2410/include/mach/timex.h b/arch/arm/plat-s3c/include/mach/timex.h index 2a425ed0a7e0..2a425ed0a7e0 100644 --- a/arch/arm/mach-s3c2410/include/mach/timex.h +++ b/arch/arm/plat-s3c/include/mach/timex.h diff --git a/arch/arm/mach-s3c2410/include/mach/vmalloc.h b/arch/arm/plat-s3c/include/mach/vmalloc.h index 315b0078a34d..bfd2ca6e3074 100644 --- a/arch/arm/mach-s3c2410/include/mach/vmalloc.h +++ b/arch/arm/plat-s3c/include/mach/vmalloc.h @@ -1,4 +1,4 @@ -/* arch/arm/mach-s3c2410/include/mach/vmalloc.h +/* arch/arm/plat-s3c/include/mach/vmalloc.h * * from arch/arm/mach-iop3xx/include/mach/vmalloc.h * diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h new file mode 100644 index 000000000000..43df2a404b0b --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/adc.h @@ -0,0 +1,29 @@ +/* arch/arm/plat-s3c/include/plat/adc.h + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simnte.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX ADC driver information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_PLAT_ADC_H +#define __ASM_PLAT_ADC_H __FILE__ + +struct s3c_adc_client; + +extern int s3c_adc_start(struct s3c_adc_client *client, + unsigned int channel, unsigned int nr_samples); + +extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, + void (*select)(unsigned selected), + void (*conv)(unsigned d0, unsigned d1), + unsigned int is_ts); + +extern void s3c_adc_release(struct s3c_adc_client *client); + +#endif /* __ASM_PLAT_ADC_H */ diff --git a/arch/arm/plat-s3c24xx/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h index 235b753cd877..a10622eed43a 100644 --- a/arch/arm/plat-s3c24xx/include/plat/clock.h +++ b/arch/arm/plat-s3c/include/plat/clock.h @@ -1,5 +1,4 @@ -/* linux/include/asm-arm/plat-s3c24xx/clock.h - * linux/arch/arm/mach-s3c2410/clock.h +/* linux/arch/arm/plat-s3c/include/plat/clock.h * * Copyright (c) 2004-2005 Simtec Electronics * http://www.simtec.co.uk/products/SWLINUX/ @@ -10,6 +9,8 @@ * published by the Free Software Foundation. */ +#include <linux/spinlock.h> + struct clk { struct list_head list; struct module *owner; @@ -44,21 +45,44 @@ extern struct clk clk_h; extern struct clk clk_p; extern struct clk clk_mpll; extern struct clk clk_upll; +extern struct clk clk_epll; extern struct clk clk_xtal; +extern struct clk clk_ext; + +/* S3C64XX specific clocks */ +extern struct clk clk_27m; +extern struct clk clk_48m; /* exports for arch/arm/mach-s3c2410 * * Please DO NOT use these outside of arch/arm/mach-s3c2410 */ -extern struct mutex clocks_mutex; +extern spinlock_t clocks_lock; extern int s3c2410_clkcon_enable(struct clk *clk, int enable); extern int s3c24xx_register_clock(struct clk *clk); extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks); -extern int s3c24xx_setup_clocks(unsigned long xtal, - unsigned long fclk, - unsigned long hclk, - unsigned long pclk); +extern int s3c24xx_register_baseclocks(unsigned long xtal); + +extern void s3c64xx_register_clocks(void); + +extern void s3c24xx_setup_clocks(unsigned long fclk, + unsigned long hclk, + unsigned long pclk); + +extern void s3c2410_setup_clocks(void); +extern void s3c2412_setup_clocks(void); +extern void s3c244x_setup_clocks(void); +extern void s3c2443_setup_clocks(void); + +/* S3C64XX specific functions and clocks */ + +extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); + +/* Init for pwm clock code */ + +extern void s3c_pwmclk_init(void); + diff --git a/arch/arm/plat-s3c/include/plat/cpu-freq.h b/arch/arm/plat-s3c/include/plat/cpu-freq.h new file mode 100644 index 000000000000..c86a13307e90 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/cpu-freq.h @@ -0,0 +1,94 @@ +/* arch/arm/plat-s3c/include/plat/cpu-freq.h + * + * Copyright (c) 2006,2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C CPU frequency scaling support - driver and board + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/cpufreq.h> + +struct s3c_cpufreq_info; +struct s3c_cpufreq_board; +struct s3c_iotimings; + +struct s3c_freq { + unsigned long fclk; + unsigned long armclk; + unsigned long hclk_tns; /* in 10ths of ns */ + unsigned long hclk; + unsigned long pclk; +}; + +/* wrapper 'struct cpufreq_freqs' so that any drivers receiving the + * notification can use this information that is not provided by just + * having the core frequency alone. + */ + +struct s3c_cpufreq_freqs { + struct cpufreq_freqs freqs; + struct s3c_freq old; + struct s3c_freq new; +}; + +#define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs) + +struct s3c_clkdivs { + int p_divisor; /* fclk / pclk */ + int h_divisor; /* fclk / hclk */ + int arm_divisor; /* not all cpus have this. */ + unsigned char dvs; /* using dvs mode to arm. */ +}; + +#define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s)) + +struct s3c_pllval { + unsigned long freq; + unsigned long pll_reg; +}; + +struct s3c_cpufreq_config { + struct s3c_freq freq; + struct s3c_pllval pll; + struct s3c_clkdivs divs; + struct s3c_cpufreq_info *info; /* for core, not drivers */ + struct s3c_cpufreq_board *board; +}; + +/* s3c_cpufreq_board + * + * per-board configuraton information, such as memory refresh and + * how to initialise IO timings. + */ +struct s3c_cpufreq_board { + unsigned int refresh; /* refresh period in ns */ + unsigned int auto_io:1; /* automatically init io timings. */ + unsigned int need_io:1; /* set if needs io timing support. */ + + /* any non-zero field in here is taken as an upper limit. */ + struct s3c_freq max; /* frequency limits */ +}; + +/* Things depending on frequency scaling. */ +#ifdef CONFIG_CPU_FREQ_S3C +#define __init_or_cpufreq +#else +#define __init_or_cpufreq __init +#endif + +/* Board functions */ + +#ifdef CONFIG_CPU_FREQ_S3C +extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board); +#else + +static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) +{ + return 0; +} +#endif /* CONFIG_CPU_FREQ_S3C */ diff --git a/arch/arm/plat-s3c24xx/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h index 23e420e8bd5b..e62ae0fcfe56 100644 --- a/arch/arm/plat-s3c24xx/include/plat/cpu.h +++ b/arch/arm/plat-s3c/include/plat/cpu.h @@ -1,4 +1,4 @@ -/* linux/include/asm-arm/plat-s3c24xx/cpu.h +/* linux/arch/arm/plat-s3c/include/plat/cpu.h * * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> @@ -18,7 +18,7 @@ #define MHZ (1000*1000) #endif -#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000) +#define print_mhz(m) ((m) / MHZ), (((m) / 1000) % 1000) /* forward declaration */ struct s3c24xx_uart_resources; @@ -26,11 +26,28 @@ struct platform_device; struct s3c2410_uartcfg; struct map_desc; +/* per-cpu initialisation function table. */ + +struct cpu_table { + unsigned long idcode; + unsigned long idmask; + void (*map_io)(void); + void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no); + void (*init_clocks)(int xtal); + int (*init)(void); + const char *name; +}; + +extern void s3c_init_cpu(unsigned long idcode, + struct cpu_table *cpus, unsigned int cputab_size); + /* core initialisation functions */ extern void s3c24xx_init_irq(void); +extern void s3c64xx_init_irq(u32 vic0, u32 vic1); extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); +extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c/include/plat/debug-macro.S b/arch/arm/plat-s3c/include/plat/debug-macro.S index 4aa7e2e6c001..3634d4e3708b 100644 --- a/arch/arm/plat-s3c/include/plat/debug-macro.S +++ b/arch/arm/plat-s3c/include/plat/debug-macro.S @@ -20,7 +20,7 @@ .endm #ifndef fifo_level -#define fifo_level fifo_level_s3c2410 +#define fifo_level fifo_level_s3c2440 #endif .macro fifo_full_s3c2440 rd, rx diff --git a/arch/arm/plat-s3c24xx/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index badaac9d64a8..6b1b5231511c 100644 --- a/arch/arm/plat-s3c24xx/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -17,21 +17,26 @@ struct s3c24xx_uart_resources { }; extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; +extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; extern struct platform_device *s3c24xx_uart_devs[]; extern struct platform_device *s3c24xx_uart_src[]; extern struct platform_device s3c_device_timer[]; +extern struct platform_device s3c_device_fb; extern struct platform_device s3c_device_usb; extern struct platform_device s3c_device_lcd; extern struct platform_device s3c_device_wdt; -extern struct platform_device s3c_device_i2c; +extern struct platform_device s3c_device_i2c0; +extern struct platform_device s3c_device_i2c1; extern struct platform_device s3c_device_iis; extern struct platform_device s3c_device_rtc; extern struct platform_device s3c_device_adc; extern struct platform_device s3c_device_sdi; -extern struct platform_device s3c_device_hsmmc; +extern struct platform_device s3c_device_hsmmc0; +extern struct platform_device s3c_device_hsmmc1; +extern struct platform_device s3c_device_hsmmc2; extern struct platform_device s3c_device_spi0; extern struct platform_device s3c_device_spi1; diff --git a/arch/arm/plat-s3c/include/plat/fb.h b/arch/arm/plat-s3c/include/plat/fb.h new file mode 100644 index 000000000000..214ff561b0dd --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/fb.h @@ -0,0 +1,73 @@ +/* linux/arch/arm/plat-s3c/include/plat/fb.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C - FB platform data definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_S3C_FB_H +#define __PLAT_S3C_FB_H __FILE__ + +/** + * struct s3c_fb_pd_win - per window setup data + * @win_mode: The display parameters to initialise (not for window 0) + * @virtual_x: The virtual X size. + * @virtual_y: The virtual Y size. + */ +struct s3c_fb_pd_win { + struct fb_videomode win_mode; + + unsigned short default_bpp; + unsigned short max_bpp; + unsigned short virtual_x; + unsigned short virtual_y; +}; + +/** + * struct s3c_fb_platdata - S3C driver platform specific information + * @setup_gpio: Setup the external GPIO pins to the right state to transfer + * the data from the display system to the connected display + * device. + * @vidcon0: The base vidcon0 values to control the panel data format. + * @vidcon1: The base vidcon1 values to control the panel data output. + * @win: The setup data for each hardware window, or NULL for unused. + * @display_mode: The LCD output display mode. + * + * The platform data supplies the video driver with all the information + * it requires to work with the display(s) attached to the machine. It + * controls the initial mode, the number of display windows (0 is always + * the base framebuffer) that are initialised etc. + * + */ +struct s3c_fb_platdata { + void (*setup_gpio)(void); + + struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; + + u32 vidcon0; + u32 vidcon1; +}; + +/** + * s3c_fb_set_platdata() - Setup the FB device with platform data. + * @pd: The platform data to set. The data is copied from the passed structure + * so the machine data can mark the data __initdata so that any unused + * machines will end up dumping their data at runtime. + */ +extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd); + +/** + * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD + * + * Initialise the GPIO for an 24bpp LCD display on the RGB interface. + */ +extern void s3c64xx_fb_gpio_setup_24bpp(void); + +#endif /* __PLAT_S3C_FB_H */ diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h new file mode 100644 index 000000000000..652e2bbdaa20 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h @@ -0,0 +1,176 @@ +/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - GPIO pin configuration helper definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* This is meant for core cpu support, machine or other driver files + * should not be including this header. + */ + +#ifndef __PLAT_GPIO_CFG_HELPERS_H +#define __PLAT_GPIO_CFG_HELPERS_H __FILE__ + +/* As a note, all gpio configuration functions are entered exclusively, either + * with the relevant lock held or the system prevented from doing anything else + * by disabling interrupts. +*/ + +static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int config) +{ + return (chip->config->set_config)(chip, off, config); +} + +static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + return (chip->config->set_pull)(chip, off, pull); +} + +/** + * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @cfg: The configuration value to set. + * + * This helper deal with the GPIO cases where the control register + * has two bits of configuration per gpio, which have the following + * functions: + * 00 = input + * 01 = output + * 1x = special function +*/ +extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg); + +/** + * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A) + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @cfg: The configuration value to set. + * + * This helper deal with the GPIO cases where the control register + * has one bit of configuration for the gpio, where setting the bit + * means the pin is in special function mode and unset means output. +*/ +extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg); + +/** + * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @cfg: The configuration value to set. + * + * This helper deal with the GPIO cases where the control register has 4 bits + * of control per GPIO, generally in the form of: + * 0000 = Input + * 0001 = Output + * others = Special functions (dependant on bank) + * + * Note, since the code to deal with the case where there are two control + * registers instead of one, we do not have a seperate set of functions for + * each case. +*/ +extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg); + + +/* Pull-{up,down} resistor controls. + * + * S3C2410,S3C2440,S3C24A0 = Pull-UP, + * S3C2412,S3C2413 = Pull-Down + * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef] + * S3C2443 = Pull-Both [not same as S3C6400] + */ + +/** + * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @param: pull: The pull mode being requested. + * + * This is a helper function for the case where we have GPIOs with one + * bit configuring the presence of a pull-up resistor. + */ +extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull); + +/** + * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none + * @chip: The gpio chip that is being configured + * @off: The offset for the GPIO being configured + * @param: pull: The pull mode being requested + * + * This is a helper function for the case where we have GPIOs with one + * bit configuring the presence of a pull-down resistor. + */ +extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull); + +/** + * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @param: pull: The pull mode being requested. + * + * This is a helper function for the case where we have GPIOs with two + * bits configuring the presence of a pull resistor, in the following + * order: + * 00 = No pull resistor connected + * 01 = Pull-up resistor connected + * 10 = Pull-down resistor connected + */ +extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull); + + +/** + * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none + * @chip: The gpio chip that the GPIO pin belongs to + * @off: The offset to the pin to get the configuration of. + * + * This helper function reads the state of the pull-{up,down} resistor for the + * given GPIO in the same case as s3c_gpio_setpull_upown. +*/ +extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, + unsigned int off); + +/** + * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @param: pull: The pull mode being requested. + * + * This is a helper function for the case where we have GPIOs with two + * bits configuring the presence of a pull resistor, in the following + * order: + * 00 = Pull-up resistor connected + * 10 = Pull-down resistor connected + * x1 = No pull up resistor + */ +extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull); + +/** + * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors + * @chip: The gpio chip that the GPIO pin belongs to. + * @off: The offset to the pin to get the configuration of. + * + * This helper function reads the state of the pull-{up,down} resistor for the + * given GPIO in the same case as s3c_gpio_setpull_upown. +*/ +extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip, + unsigned int off); + +#endif /* __PLAT_GPIO_CFG_HELPERS_H */ + diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg.h b/arch/arm/plat-s3c/include/plat/gpio-cfg.h new file mode 100644 index 000000000000..29cd6a86cade --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/gpio-cfg.h @@ -0,0 +1,110 @@ +/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - GPIO pin configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* This file contains the necessary definitions to get the basic gpio + * pin configuration done such as setting a pin to input or output or + * changing the pull-{up,down} configurations. + */ + +/* Note, this interface is being added to the s3c64xx arch first and will + * be added to the s3c24xx systems later. + */ + +#ifndef __PLAT_GPIO_CFG_H +#define __PLAT_GPIO_CFG_H __FILE__ + +typedef unsigned int __bitwise__ s3c_gpio_pull_t; + +/* forward declaration if gpio-core.h hasn't been included */ +struct s3c_gpio_chip; + +/** + * struct s3c_gpio_cfg GPIO configuration + * @cfg_eint: Configuration setting when used for external interrupt source + * @get_pull: Read the current pull configuration for the GPIO + * @set_pull: Set the current pull configuraiton for the GPIO + * @set_config: Set the current configuration for the GPIO + * @get_config: Read the current configuration for the GPIO + * + * Each chip can have more than one type of GPIO bank available and some + * have different capabilites even when they have the same control register + * layouts. Provide an point to vector control routine and provide any + * per-bank configuration information that other systems such as the + * external interrupt code will need. + */ +struct s3c_gpio_cfg { + unsigned int cfg_eint; + + s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs); + int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs, + s3c_gpio_pull_t pull); + + unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs); + int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs, + unsigned config); +}; + +#define S3C_GPIO_SPECIAL_MARK (0xfffffff0) +#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x)) + +/* Defines for generic pin configurations */ +#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0)) +#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1)) +#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x)) + +#define s3c_gpio_is_cfg_special(_cfg) \ + (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK) + +/** + * s3c_gpio_cfgpin() - Change the GPIO function of a pin. + * @pin pin The pin number to configure. + * @pin to The configuration for the pin's function. + * + * Configure which function is actually connected to the external + * pin, such as an gpio input, output or some form of special function + * connected to an internal peripheral block. + */ +extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); + +/* Define values for the pull-{up,down} available for each gpio pin. + * + * These values control the state of the weak pull-{up,down} resistors + * available on most pins on the S3C series. Not all chips support both + * up or down settings, and it may be dependant on the chip that is being + * used to whether the particular mode is available. + */ +#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) +#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01) +#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02) + +/** + * s3c_gpio_setpull() - set the state of a gpio pin pull resistor + * @pin: The pin number to configure the pull resistor. + * @pull: The configuration for the pull resistor. + * + * This function sets the state of the pull-{up,down} resistor for the + * specified pin. It will return 0 if successfull, or a negative error + * code if the pin cannot support the requested pull setting. +*/ +extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); + +/** + * s3c_gpio_getpull() - get the pull resistor state of a gpio pin + * @pin: The pin number to get the settings for + * + * Read the pull resistor value for the specified pin. +*/ +extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); + +#endif /* __PLAT_GPIO_CFG_H */ diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h new file mode 100644 index 000000000000..2fc60a580ac8 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/gpio-core.h @@ -0,0 +1,77 @@ +/* linux/arch/arm/plat-s3c/include/plat/gpio-core.h + * + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - GPIO core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Define the core gpiolib support functions that the s3c platforms may + * need to extend or change depending on the hardware and the s3c chip + * selected at build or found at run time. + * + * These definitions are not intended for driver inclusion, there is + * nothing here that should not live outside the platform and core + * specific code. +*/ + +struct s3c_gpio_cfg; + +/** + * struct s3c_gpio_chip - wrapper for specific implementation of gpio + * @chip: The chip structure to be exported via gpiolib. + * @base: The base pointer to the gpio configuration registers. + * @config: special function and pull-resistor control information. + * + * This wrapper provides the necessary information for the Samsung + * specific gpios being registered with gpiolib. + */ +struct s3c_gpio_chip { + struct gpio_chip chip; + struct s3c_gpio_cfg *config; + void __iomem *base; +}; + +static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc) +{ + return container_of(gpc, struct s3c_gpio_chip, chip); +} + +/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip. + * @chip: The chip to register + * + * This is a wrapper to gpiochip_add() that takes our specific gpio chip + * information and makes the necessary alterations for the platform and + * notes the information for use with the configuration systems and any + * other parts of the system. + */ +extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip); + +/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios + * for use with the configuration calls, and other parts of the s3c gpiolib + * support code. + * + * Not all s3c support code will need this, as some configurations of cpu + * may only support one or two different configuration options and have an + * easy gpio to s3c_gpio_chip mapping function. If this is the case, then + * the machine support file should provide its own s3c_gpiolib_getchip() + * and any other necessary functions. + */ + +#ifdef CONFIG_S3C_GPIO_TRACK +extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; + +static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) +{ + return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL; +} +#else +/* machine specific code should provide s3c_gpiolib_getchip */ + +static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } +#endif diff --git a/arch/arm/plat-s3c/include/plat/iic-core.h b/arch/arm/plat-s3c/include/plat/iic-core.h new file mode 100644 index 000000000000..36397ca20962 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/iic-core.h @@ -0,0 +1,35 @@ +/* arch/arm/mach-s3c2410/include/mach/iic-core.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C - I2C Controller core functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_IIC_CORE_H +#define __ASM_ARCH_IIC_CORE_H __FILE__ + +/* These functions are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void s3c_i2c0_setname(char *name) +{ + /* currently this device is always compiled in */ + s3c_device_i2c0.name = name; +} + +static inline void s3c_i2c1_setname(char *name) +{ +#ifdef CONFIG_S3C_DEV_I2C1 + s3c_device_i2c1.name = name; +#endif +} + +#endif /* __ASM_ARCH_IIC_H */ diff --git a/include/asm-arm/plat-s3c/iic.h b/arch/arm/plat-s3c/include/plat/iic.h index 5106acaa1d0e..dc1dfcb9bc6c 100644 --- a/include/asm-arm/plat-s3c/iic.h +++ b/arch/arm/plat-s3c/include/plat/iic.h @@ -28,6 +28,30 @@ struct s3c2410_platform_i2c { unsigned long max_freq; /* max frequency for the bus */ unsigned long min_freq; /* min frequency for the bus */ unsigned int sda_delay; /* pclks (s3c2440 only) */ + + void (*cfg_gpio)(struct platform_device *dev); }; +/** + * s3c_i2c0_set_platdata - set platform data for i2c0 device + * @i2c: The platform data to set, or NULL for default data. + * + * Register the given platform data for use with the i2c0 device. This + * call copies the platform data, so the caller can use __initdata for + * their copy. + * + * This call will set cfg_gpio if is null to the default platform + * implementation. + * + * Any user of s3c_device_i2c0 should call this, even if it is with + * NULL to ensure that the device is given the default platform data + * as the driver will no longer carry defaults. + */ +extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); + +/* defined by architecture to configure gpio */ +extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); + #endif /* __ASM_ARCH_IIC_H */ diff --git a/arch/arm/plat-s3c/include/plat/map.h b/arch/arm/plat-s3c/include/plat/map-base.h index b84289d32a54..b84289d32a54 100644 --- a/arch/arm/plat-s3c/include/plat/map.h +++ b/arch/arm/plat-s3c/include/plat/map-base.h diff --git a/include/asm-arm/plat-s3c/nand.h b/arch/arm/plat-s3c/include/plat/nand.h index f4dcd14af059..f4dcd14af059 100644 --- a/include/asm-arm/plat-s3c/nand.h +++ b/arch/arm/plat-s3c/include/plat/nand.h diff --git a/include/asm-arm/plat-s3c/regs-ac97.h b/arch/arm/plat-s3c/include/plat/regs-ac97.h index c3878f7acb83..c3878f7acb83 100644 --- a/include/asm-arm/plat-s3c/regs-ac97.h +++ b/arch/arm/plat-s3c/include/plat/regs-ac97.h diff --git a/arch/arm/plat-s3c/include/plat/regs-fb.h b/arch/arm/plat-s3c/include/plat/regs-fb.h new file mode 100644 index 000000000000..e9ee599d430e --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/regs-fb.h @@ -0,0 +1,366 @@ +/* arch/arm/plat-s3c/include/plat/regs-fb.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - new-style framebuffer register definitions + * + * This is the register set for the new style framebuffer interface + * found from the S3C2443 onwards into the S3C2416, S3C2450 and the + * S3C64XX series such as the S3C6400 and S3C6410. + * + * The file does not contain the cpu specific items which are based on + * whichever architecture is selected, it only contains the core of the + * register set. See <mach/regs-fb.h> to get the specifics. + * + * Note, we changed to using regs-fb.h as it avoids any clashes with + * the original regs-lcd.h so out of the way of regs-lcd.h as well as + * indicating the newer block is much more than just an LCD interface. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Please do not include this file directly, use <mach/regs-fb.h> to + * ensure all the localised SoC support is included as necessary. +*/ + +/* VIDCON0 */ + +#define VIDCON0 (0x00) +#define VIDCON0_INTERLACE (1 << 29) +#define VIDCON0_VIDOUT_MASK (0x3 << 26) +#define VIDCON0_VIDOUT_SHIFT (26) +#define VIDCON0_VIDOUT_RGB (0x0 << 26) +#define VIDCON0_VIDOUT_TV (0x1 << 26) +#define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) +#define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) + +#define VIDCON0_L1_DATA_MASK (0x7 << 23) +#define VIDCON0_L1_DATA_SHIFT (23) +#define VIDCON0_L1_DATA_16BPP (0x0 << 23) +#define VIDCON0_L1_DATA_18BPP16 (0x1 << 23) +#define VIDCON0_L1_DATA_18BPP9 (0x2 << 23) +#define VIDCON0_L1_DATA_24BPP (0x3 << 23) +#define VIDCON0_L1_DATA_18BPP (0x4 << 23) +#define VIDCON0_L1_DATA_16BPP8 (0x5 << 23) + +#define VIDCON0_L0_DATA_MASK (0x7 << 20) +#define VIDCON0_L0_DATA_SHIFT (20) +#define VIDCON0_L0_DATA_16BPP (0x0 << 20) +#define VIDCON0_L0_DATA_18BPP16 (0x1 << 20) +#define VIDCON0_L0_DATA_18BPP9 (0x2 << 20) +#define VIDCON0_L0_DATA_24BPP (0x3 << 20) +#define VIDCON0_L0_DATA_18BPP (0x4 << 20) +#define VIDCON0_L0_DATA_16BPP8 (0x5 << 20) + +#define VIDCON0_PNRMODE_MASK (0x3 << 17) +#define VIDCON0_PNRMODE_SHIFT (17) +#define VIDCON0_PNRMODE_RGB (0x0 << 17) +#define VIDCON0_PNRMODE_BGR (0x1 << 17) +#define VIDCON0_PNRMODE_SERIAL_RGB (0x2 << 17) +#define VIDCON0_PNRMODE_SERIAL_BGR (0x3 << 17) + +#define VIDCON0_CLKVALUP (1 << 16) +#define VIDCON0_CLKVAL_F_MASK (0xff << 6) +#define VIDCON0_CLKVAL_F_SHIFT (6) +#define VIDCON0_CLKVAL_F_LIMIT (0xff) +#define VIDCON0_CLKVAL_F(_x) ((_x) << 6) +#define VIDCON0_VLCKFREE (1 << 5) +#define VIDCON0_CLKDIR (1 << 4) + +#define VIDCON0_CLKSEL_MASK (0x3 << 2) +#define VIDCON0_CLKSEL_SHIFT (2) +#define VIDCON0_CLKSEL_HCLK (0x0 << 2) +#define VIDCON0_CLKSEL_LCD (0x1 << 2) +#define VIDCON0_CLKSEL_27M (0x3 << 2) + +#define VIDCON0_ENVID (1 << 1) +#define VIDCON0_ENVID_F (1 << 0) + +#define VIDCON1 (0x04) +#define VIDCON1_LINECNT_MASK (0x7ff << 16) +#define VIDCON1_LINECNT_SHIFT (16) +#define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff) +#define VIDCON1_VSTATUS_MASK (0x3 << 13) +#define VIDCON1_VSTATUS_SHIFT (13) +#define VIDCON1_VSTATUS_VSYNC (0x0 << 13) +#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13) +#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13) +#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13) + +#define VIDCON1_INV_VCLK (1 << 7) +#define VIDCON1_INV_HSYNC (1 << 6) +#define VIDCON1_INV_VSYNC (1 << 5) +#define VIDCON1_INV_VDEN (1 << 4) + +/* VIDCON2 */ + +#define VIDCON2 (0x08) +#define VIDCON2_EN601 (1 << 23) +#define VIDCON2_TVFMTSEL_SW (1 << 14) + +#define VIDCON2_TVFMTSEL1_MASK (0x3 << 12) +#define VIDCON2_TVFMTSEL1_SHIFT (12) +#define VIDCON2_TVFMTSEL1_RGB (0x0 << 12) +#define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12) +#define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12) + +#define VIDCON2_ORGYCbCr (1 << 8) +#define VIDCON2_YUVORDCrCb (1 << 7) + +/* VIDTCON0 */ + +#define VIDTCON0_VBPDE_MASK (0xff << 24) +#define VIDTCON0_VBPDE_SHIFT (24) +#define VIDTCON0_VBPDE_LIMIT (0xff) +#define VIDTCON0_VBPDE(_x) ((_x) << 24) + +#define VIDTCON0_VBPD_MASK (0xff << 16) +#define VIDTCON0_VBPD_SHIFT (16) +#define VIDTCON0_VBPD_LIMIT (0xff) +#define VIDTCON0_VBPD(_x) ((_x) << 16) + +#define VIDTCON0_VFPD_MASK (0xff << 8) +#define VIDTCON0_VFPD_SHIFT (8) +#define VIDTCON0_VFPD_LIMIT (0xff) +#define VIDTCON0_VFPD(_x) ((_x) << 8) + +#define VIDTCON0_VSPW_MASK (0xff << 0) +#define VIDTCON0_VSPW_SHIFT (0) +#define VIDTCON0_VSPW_LIMIT (0xff) +#define VIDTCON0_VSPW(_x) ((_x) << 0) + +/* VIDTCON1 */ + +#define VIDTCON1_VFPDE_MASK (0xff << 24) +#define VIDTCON1_VFPDE_SHIFT (24) +#define VIDTCON1_VFPDE_LIMIT (0xff) +#define VIDTCON1_VFPDE(_x) ((_x) << 24) + +#define VIDTCON1_HBPD_MASK (0xff << 16) +#define VIDTCON1_HBPD_SHIFT (16) +#define VIDTCON1_HBPD_LIMIT (0xff) +#define VIDTCON1_HBPD(_x) ((_x) << 16) + +#define VIDTCON1_HFPD_MASK (0xff << 8) +#define VIDTCON1_HFPD_SHIFT (8) +#define VIDTCON1_HFPD_LIMIT (0xff) +#define VIDTCON1_HFPD(_x) ((_x) << 8) + +#define VIDTCON1_HSPW_MASK (0xff << 0) +#define VIDTCON1_HSPW_SHIFT (0) +#define VIDTCON1_HSPW_LIMIT (0xff) +#define VIDTCON1_HSPW(_x) ((_x) << 0) + +#define VIDTCON2 (0x18) +#define VIDTCON2_LINEVAL_MASK (0x7ff << 11) +#define VIDTCON2_LINEVAL_SHIFT (11) +#define VIDTCON2_LINEVAL_LIMIT (0x7ff) +#define VIDTCON2_LINEVAL(_x) ((_x) << 11) + +#define VIDTCON2_HOZVAL_MASK (0x7ff << 0) +#define VIDTCON2_HOZVAL_SHIFT (0) +#define VIDTCON2_HOZVAL_LIMIT (0x7ff) +#define VIDTCON2_HOZVAL(_x) ((_x) << 0) + +/* WINCONx */ + + +#define WINCONx_BITSWP (1 << 18) +#define WINCONx_BYTSWP (1 << 17) +#define WINCONx_HAWSWP (1 << 16) +#define WINCONx_BURSTLEN_MASK (0x3 << 9) +#define WINCONx_BURSTLEN_SHIFT (9) +#define WINCONx_BURSTLEN_16WORD (0x0 << 9) +#define WINCONx_BURSTLEN_8WORD (0x1 << 9) +#define WINCONx_BURSTLEN_4WORD (0x2 << 9) + +#define WINCONx_ENWIN (1 << 0) +#define WINCON0_BPPMODE_MASK (0xf << 2) +#define WINCON0_BPPMODE_SHIFT (2) +#define WINCON0_BPPMODE_1BPP (0x0 << 2) +#define WINCON0_BPPMODE_2BPP (0x1 << 2) +#define WINCON0_BPPMODE_4BPP (0x2 << 2) +#define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2) +#define WINCON0_BPPMODE_16BPP_565 (0x5 << 2) +#define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2) +#define WINCON0_BPPMODE_18BPP_666 (0x8 << 2) +#define WINCON0_BPPMODE_24BPP_888 (0xb << 2) + +#define WINCON1_BLD_PIX (1 << 6) + +#define WINCON1_ALPHA_SEL (1 << 1) +#define WINCON1_BPPMODE_MASK (0xf << 2) +#define WINCON1_BPPMODE_SHIFT (2) +#define WINCON1_BPPMODE_1BPP (0x0 << 2) +#define WINCON1_BPPMODE_2BPP (0x1 << 2) +#define WINCON1_BPPMODE_4BPP (0x2 << 2) +#define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2) +#define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2) +#define WINCON1_BPPMODE_16BPP_565 (0x5 << 2) +#define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2) +#define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2) +#define WINCON1_BPPMODE_18BPP_666 (0x8 << 2) +#define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2) +#define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2) +#define WINCON1_BPPMODE_24BPP_888 (0xb << 2) +#define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2) +#define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2) +#define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2) + + +#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) +#define VIDOSDxA_TOPLEFT_X_SHIFT (11) +#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) +#define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) + +#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) +#define VIDOSDxA_TOPLEFT_Y_SHIFT (0) +#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) +#define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) + +#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) +#define VIDOSDxB_BOTRIGHT_X_SHIFT (11) +#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) +#define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) + +#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) +#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) +#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) +#define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) + +/* For VIDOSD[1..4]C */ +#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) +#define VIDISD14C_ALPHA0_G_MASK (0xf << 16) +#define VIDISD14C_ALPHA0_G_SHIFT (16) +#define VIDISD14C_ALPHA0_G_LIMIT (0xf) +#define VIDISD14C_ALPHA0_G(_x) ((_x) << 16) +#define VIDISD14C_ALPHA0_B_MASK (0xf << 12) +#define VIDISD14C_ALPHA0_B_SHIFT (12) +#define VIDISD14C_ALPHA0_B_LIMIT (0xf) +#define VIDISD14C_ALPHA0_B(_x) ((_x) << 12) +#define VIDISD14C_ALPHA1_R_MASK (0xf << 8) +#define VIDISD14C_ALPHA1_R_SHIFT (8) +#define VIDISD14C_ALPHA1_R_LIMIT (0xf) +#define VIDISD14C_ALPHA1_R(_x) ((_x) << 8) +#define VIDISD14C_ALPHA1_G_MASK (0xf << 4) +#define VIDISD14C_ALPHA1_G_SHIFT (4) +#define VIDISD14C_ALPHA1_G_LIMIT (0xf) +#define VIDISD14C_ALPHA1_G(_x) ((_x) << 4) +#define VIDISD14C_ALPHA1_B_MASK (0xf << 0) +#define VIDISD14C_ALPHA1_B_SHIFT (0) +#define VIDISD14C_ALPHA1_B_LIMIT (0xf) +#define VIDISD14C_ALPHA1_B(_x) ((_x) << 0) + +/* Video buffer addresses */ +#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) +#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) +#define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8)) +#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) +#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) + +#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) +#define VIDW_BUF_SIZE_OFFSET_SHIFT (13) +#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) +#define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) + +#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) +#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) +#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) +#define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) + +/* Interrupt controls and status */ + +#define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20) +#define VIDINTCON0_FIFOINTERVAL_SHIFT (20) +#define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f) +#define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20) + +#define VIDINTCON0_INT_SYSMAINCON (1 << 19) +#define VIDINTCON0_INT_SYSSUBCON (1 << 18) +#define VIDINTCON0_INT_I80IFDONE (1 << 17) + +#define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15) +#define VIDINTCON0_FRAMESEL0_SHIFT (15) +#define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15) +#define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15) +#define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15) +#define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15) + +#define VIDINTCON0_FRAMESEL1 (1 << 14) +#define VIDINTCON0_FRAMESEL1_NONE (0x0 << 14) +#define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 14) +#define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 14) +#define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 14) + +#define VIDINTCON0_INT_FRAME (1 << 12) +#define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5) +#define VIDINTCON0_FIFIOSEL_SHIFT (5) +#define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5) +#define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5) + +#define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2) +#define VIDINTCON0_FIFOLEVEL_SHIFT (2) +#define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2) +#define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2) +#define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2) +#define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2) +#define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2) + +#define VIDINTCON0_INT_FIFO_MASK (0x3 << 0) +#define VIDINTCON0_INT_FIFO_SHIFT (0) +#define VIDINTCON0_INT_ENABLE (1 << 0) + +#define VIDINTCON1 (0x134) +#define VIDINTCON1_INT_I180 (1 << 2) +#define VIDINTCON1_INT_FRAME (1 << 1) +#define VIDINTCON1_INT_FIFO (1 << 0) + +/* Window colour-key control registers */ + +#define WxKEYCON0_KEYBL_EN (1 << 26) +#define WxKEYCON0_KEYEN_F (1 << 25) +#define WxKEYCON0_DIRCON (1 << 24) +#define WxKEYCON0_COMPKEY_MASK (0xffffff << 0) +#define WxKEYCON0_COMPKEY_SHIFT (0) +#define WxKEYCON0_COMPKEY_LIMIT (0xffffff) +#define WxKEYCON0_COMPKEY(_x) ((_x) << 0) +#define WxKEYCON1_COLVAL_MASK (0xffffff << 0) +#define WxKEYCON1_COLVAL_SHIFT (0) +#define WxKEYCON1_COLVAL_LIMIT (0xffffff) +#define WxKEYCON1_COLVAL(_x) ((_x) << 0) + + +/* Window blanking (MAP) */ + +#define WINxMAP_MAP (1 << 24) +#define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0) +#define WINxMAP_MAP_COLOUR_SHIFT (0) +#define WINxMAP_MAP_COLOUR_LIMIT (0xffffff) +#define WINxMAP_MAP_COLOUR(_x) ((_x) << 0) + +#define WPALCON_PAL_UPDATE (1 << 9) +#define WPALCON_W1PAL_MASK (0x7 << 3) +#define WPALCON_W1PAL_SHIFT (3) +#define WPALCON_W1PAL_25BPP_A888 (0x0 << 3) +#define WPALCON_W1PAL_24BPP (0x1 << 3) +#define WPALCON_W1PAL_19BPP_A666 (0x2 << 3) +#define WPALCON_W1PAL_18BPP_A665 (0x3 << 3) +#define WPALCON_W1PAL_18BPP (0x4 << 3) +#define WPALCON_W1PAL_16BPP_A555 (0x5 << 3) +#define WPALCON_W1PAL_16BPP_565 (0x6 << 3) + +#define WPALCON_W0PAL_MASK (0x7 << 0) +#define WPALCON_W0PAL_SHIFT (0) +#define WPALCON_W0PAL_25BPP_A888 (0x0 << 0) +#define WPALCON_W0PAL_24BPP (0x1 << 0) +#define WPALCON_W0PAL_19BPP_A666 (0x2 << 0) +#define WPALCON_W0PAL_18BPP_A665 (0x3 << 0) +#define WPALCON_W0PAL_18BPP (0x4 << 0) +#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) +#define WPALCON_W0PAL_16BPP_565 (0x6 << 0) + diff --git a/include/asm-arm/plat-s3c/regs-iic.h b/arch/arm/plat-s3c/include/plat/regs-iic.h index 2f7c17de8ac8..2f7c17de8ac8 100644 --- a/include/asm-arm/plat-s3c/regs-iic.h +++ b/arch/arm/plat-s3c/include/plat/regs-iic.h diff --git a/arch/arm/plat-s3c/include/plat/regs-irqtype.h b/arch/arm/plat-s3c/include/plat/regs-irqtype.h new file mode 100644 index 000000000000..c63cd3fc5ad3 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/regs-irqtype.h @@ -0,0 +1,21 @@ +/* arch/arm/plat-s3c/include/plat/regs-irqtype.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C - IRQ detection types. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* values for S3C2410_EXTINT0/1/2 and other cpus in the series, including + * the S3C64XX +*/ +#define S3C2410_EXTINT_LOWLEV (0x00) +#define S3C2410_EXTINT_HILEV (0x01) +#define S3C2410_EXTINT_FALLEDGE (0x02) +#define S3C2410_EXTINT_RISEEDGE (0x04) +#define S3C2410_EXTINT_BOTHEDGE (0x06) diff --git a/include/asm-arm/plat-s3c/regs-nand.h b/arch/arm/plat-s3c/include/plat/regs-nand.h index b2caa4bca270..b2caa4bca270 100644 --- a/include/asm-arm/plat-s3c/regs-nand.h +++ b/arch/arm/plat-s3c/include/plat/regs-nand.h diff --git a/include/asm-arm/plat-s3c/regs-rtc.h b/arch/arm/plat-s3c/include/plat/regs-rtc.h index d5837cf8e402..d5837cf8e402 100644 --- a/include/asm-arm/plat-s3c/regs-rtc.h +++ b/arch/arm/plat-s3c/include/plat/regs-rtc.h diff --git a/arch/arm/plat-s3c/include/plat/regs-sdhci.h b/arch/arm/plat-s3c/include/plat/regs-sdhci.h new file mode 100644 index 000000000000..e34049ad44cc --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/regs-sdhci.h @@ -0,0 +1,87 @@ +/* linux/arch/arm/plat-s3c/include/plat/regs-sdhci.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - SDHCI (HSMMC) register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_S3C_SDHCI_REGS_H +#define __PLAT_S3C_SDHCI_REGS_H __FILE__ + +#define S3C_SDHCI_CONTROL2 (0x80) +#define S3C_SDHCI_CONTROL3 (0x84) +#define S3C64XX_SDHCI_CONTROL4 (0x8C) + +#define S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR (1 << 31) +#define S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK (1 << 30) +#define S3C_SDHCI_CTRL2_CDINVRXD3 (1 << 29) +#define S3C_SDHCI_CTRL2_SLCARDOUT (1 << 28) + +#define S3C_SDHCI_CTRL2_FLTCLKSEL_MASK (0xf << 24) +#define S3C_SDHCI_CTRL2_FLTCLKSEL_SHIFT (24) +#define S3C_SDHCI_CTRL2_FLTCLKSEL(_x) ((_x) << 24) + +#define S3C_SDHCI_CTRL2_LVLDAT_MASK (0xff << 16) +#define S3C_SDHCI_CTRL2_LVLDAT_SHIFT (16) +#define S3C_SDHCI_CTRL2_LVLDAT(_x) ((_x) << 16) + +#define S3C_SDHCI_CTRL2_ENFBCLKTX (1 << 15) +#define S3C_SDHCI_CTRL2_ENFBCLKRX (1 << 14) +#define S3C_SDHCI_CTRL2_SDCDSEL (1 << 13) +#define S3C_SDHCI_CTRL2_SDSIGPC (1 << 12) +#define S3C_SDHCI_CTRL2_ENBUSYCHKTXSTART (1 << 11) + +#define S3C_SDHCI_CTRL2_DFCNT_MASK (0x3 << 9) +#define S3C_SDHCI_CTRL2_DFCNT_SHIFT (9) +#define S3C_SDHCI_CTRL2_DFCNT_NONE (0x0 << 9) +#define S3C_SDHCI_CTRL2_DFCNT_4SDCLK (0x1 << 9) +#define S3C_SDHCI_CTRL2_DFCNT_16SDCLK (0x2 << 9) +#define S3C_SDHCI_CTRL2_DFCNT_64SDCLK (0x3 << 9) + +#define S3C_SDHCI_CTRL2_ENCLKOUTHOLD (1 << 8) +#define S3C_SDHCI_CTRL2_RWAITMODE (1 << 7) +#define S3C_SDHCI_CTRL2_DISBUFRD (1 << 6) +#define S3C_SDHCI_CTRL2_SELBASECLK_MASK (0x3 << 4) +#define S3C_SDHCI_CTRL2_SELBASECLK_SHIFT (4) +#define S3C_SDHCI_CTRL2_PWRSYNC (1 << 3) +#define S3C_SDHCI_CTRL2_ENCLKOUTMSKCON (1 << 1) +#define S3C_SDHCI_CTRL2_HWINITFIN (1 << 0) + +#define S3C_SDHCI_CTRL3_FCSEL3 (1 << 31) +#define S3C_SDHCI_CTRL3_FCSEL2 (1 << 23) +#define S3C_SDHCI_CTRL3_FCSEL1 (1 << 15) +#define S3C_SDHCI_CTRL3_FCSEL0 (1 << 7) + +#define S3C_SDHCI_CTRL3_FIA3_MASK (0x7f << 24) +#define S3C_SDHCI_CTRL3_FIA3_SHIFT (24) +#define S3C_SDHCI_CTRL3_FIA3(_x) ((_x) << 24) + +#define S3C_SDHCI_CTRL3_FIA2_MASK (0x7f << 16) +#define S3C_SDHCI_CTRL3_FIA2_SHIFT (16) +#define S3C_SDHCI_CTRL3_FIA2(_x) ((_x) << 16) + +#define S3C_SDHCI_CTRL3_FIA1_MASK (0x7f << 8) +#define S3C_SDHCI_CTRL3_FIA1_SHIFT (8) +#define S3C_SDHCI_CTRL3_FIA1(_x) ((_x) << 8) + +#define S3C_SDHCI_CTRL3_FIA0_MASK (0x7f << 0) +#define S3C_SDHCI_CTRL3_FIA0_SHIFT (0) +#define S3C_SDHCI_CTRL3_FIA0(_x) ((_x) << 0) + +#define S3C64XX_SDHCI_CONTROL4_DRIVE_MASK (0x3 << 16) +#define S3C64XX_SDHCI_CONTROL4_DRIVE_SHIFT (16) +#define S3C64XX_SDHCI_CONTROL4_DRIVE_2mA (0x0 << 16) +#define S3C64XX_SDHCI_CONTROL4_DRIVE_4mA (0x1 << 16) +#define S3C64XX_SDHCI_CONTROL4_DRIVE_7mA (0x2 << 16) +#define S3C64XX_SDHCI_CONTROL4_DRIVE_9mA (0x3 << 16) + +#define S3C64XX_SDHCI_CONTROL4_BUSY (1) + +#endif /* __PLAT_S3C_SDHCI_REGS_H */ diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h index a0daa647b92c..487d7d2a7e1d 100644 --- a/arch/arm/plat-s3c/include/plat/regs-serial.h +++ b/arch/arm/plat-s3c/include/plat/regs-serial.h @@ -77,6 +77,12 @@ #define S3C2440_UCON_FCLK (3<<10) #define S3C2443_UCON_EPLL (3<<10) +#define S3C6400_UCON_CLKMASK (3<<10) +#define S3C6400_UCON_PCLK (0<<10) +#define S3C6400_UCON_PCLK2 (2<<10) +#define S3C6400_UCON_UCLK0 (1<<10) +#define S3C6400_UCON_UCLK1 (3<<10) + #define S3C2440_UCON2_FCLK_EN (1<<15) #define S3C2440_UCON0_DIVMASK (15 << 12) #define S3C2440_UCON1_DIVMASK (15 << 12) @@ -149,6 +155,14 @@ #define S3C2410_UFSTAT_RXMASK (15<<0) #define S3C2410_UFSTAT_RXSHIFT (0) +/* UFSTAT S3C24A0 */ +#define S3C24A0_UFSTAT_TXFULL (1 << 14) +#define S3C24A0_UFSTAT_RXFULL (1 << 6) +#define S3C24A0_UFSTAT_TXMASK (63 << 8) +#define S3C24A0_UFSTAT_TXSHIFT (8) +#define S3C24A0_UFSTAT_RXMASK (63) +#define S3C24A0_UFSTAT_RXSHIFT (0) + /* UFSTAT S3C2443 same as S3C2440 */ #define S3C2440_UFSTAT_TXFULL (1<<14) #define S3C2440_UFSTAT_RXFULL (1<<6) @@ -224,7 +238,7 @@ struct s3c2410_uartcfg { * or platform_add_device() before the console_initcall() */ -extern struct platform_device *s3c24xx_uart_devs[3]; +extern struct platform_device *s3c24xx_uart_devs[4]; #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-s3c/include/plat/regs-timer.h index cc0eedd53e38..d097d92f8cc7 100644 --- a/arch/arm/plat-s3c/include/plat/regs-timer.h +++ b/arch/arm/plat-s3c/include/plat/regs-timer.h @@ -10,7 +10,6 @@ * S3C2410 Timer configuration */ - #ifndef __ASM_ARCH_REGS_TIMER_H #define __ASM_ARCH_REGS_TIMER_H @@ -21,6 +20,8 @@ #define S3C2410_TCFG1 S3C_TIMERREG(0x04) #define S3C2410_TCON S3C_TIMERREG(0x08) +#define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44) + #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) #define S3C2410_TCFG_PRESCALER1_SHIFT (8) @@ -72,6 +73,14 @@ #define S3C2410_TCFG1_MUX_TCLK (4<<0) #define S3C2410_TCFG1_MUX_MASK (15<<0) +#define S3C64XX_TCFG1_MUX_DIV1 (0<<0) +#define S3C64XX_TCFG1_MUX_DIV2 (1<<0) +#define S3C64XX_TCFG1_MUX_DIV4 (2<<0) +#define S3C64XX_TCFG1_MUX_DIV8 (3<<0) +#define S3C64XX_TCFG1_MUX_DIV16 (4<<0) +#define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */ +#define S3C64XX_TCFG1_MUX_MASK (15<<0) + #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) /* for each timer, we have an count buffer, an compare buffer and diff --git a/include/asm-arm/plat-s3c/regs-watchdog.h b/arch/arm/plat-s3c/include/plat/regs-watchdog.h index 4938492470f7..4938492470f7 100644 --- a/include/asm-arm/plat-s3c/regs-watchdog.h +++ b/arch/arm/plat-s3c/include/plat/regs-watchdog.h diff --git a/arch/arm/plat-s3c/include/plat/sdhci.h b/arch/arm/plat-s3c/include/plat/sdhci.h new file mode 100644 index 000000000000..c4ca3920ca4b --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/sdhci.h @@ -0,0 +1,108 @@ +/* linux/arch/arm/plat-s3c/include/plat/sdhci.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C Platform - SDHCI (HSMMC) platform data definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_S3C_SDHCI_H +#define __PLAT_S3C_SDHCI_H __FILE__ + +struct platform_device; +struct mmc_host; +struct mmc_card; +struct mmc_ios; + +/** + * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI + * @max_width: The maximum number of data bits supported. + * @host_caps: Standard MMC host capabilities bit field. + * @cfg_gpio: Configure the GPIO for a specific card bit-width + * @cfg_card: Configure the interface for a specific card and speed. This + * is necessary the controllers and/or GPIO blocks require the + * changing of driver-strength and other controls dependant on + * the card and speed of operation. + * + * Initialisation data specific to either the machine or the platform + * for the device driver to use or call-back when configuring gpio or + * card speed information. +*/ +struct s3c_sdhci_platdata { + unsigned int max_width; + unsigned int host_caps; + + char **clocks; /* set of clock sources */ + + void (*cfg_gpio)(struct platform_device *dev, int width); + void (*cfg_card)(struct platform_device *dev, + void __iomem *regbase, + struct mmc_ios *ios, + struct mmc_card *card); +}; + +/** + * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device. + * @pd: Platform data to register to device. + * + * Register the given platform data for use withe S3C SDHCI device. + * The call will copy the platform data, so the board definitions can + * make the structure itself __initdata. + */ +extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd); +extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd); + +/* Default platform data, exported so that per-cpu initialisation can + * set the correct one when there are more than one cpu type selected. +*/ + +extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata; +extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata; + +/* Helper function availablity */ + +#ifdef CONFIG_S3C6410_SETUP_SDHCI +extern char *s3c6410_hsmmc_clksrcs[4]; + +extern void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *, int w); + +extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +#ifdef CONFIG_S3C_DEV_HSMMC +static inline void s3c6410_default_sdhci0(void) +{ + s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs; + s3c_hsmmc0_def_platdata.cfg_gpio = s3c6410_setup_sdhci0_cfg_gpio; + s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card; +} +#else +static inline void s3c6410_default_sdhci0(void) { } +#endif /* CONFIG_S3C_DEV_HSMMC */ + +#ifdef CONFIG_S3C_DEV_HSMMC1 +static inline void s3c6410_default_sdhci1(void) +{ + s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs; + s3c_hsmmc1_def_platdata.cfg_gpio = s3c6410_setup_sdhci1_cfg_gpio; + s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card; +} +#else +static inline void s3c6410_default_sdhci1(void) { } +#endif /* CONFIG_S3C_DEV_HSMMC1 */ + +#else +static inline void s3c6410_default_sdhci0(void) { } +static inline void s3c6410_default_sdhci1(void) { } +#endif /* CONFIG_S3C6410_SETUP_SDHCI */ + +#endif /* __PLAT_S3C_SDHCI_H */ diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h index 4df006b9cc10..6061de87f225 100644 --- a/arch/arm/plat-s3c/include/plat/uncompress.h +++ b/arch/arm/plat-s3c/include/plat/uncompress.h @@ -28,7 +28,7 @@ static void arch_detect_cpu(void); /* defines for UART registers */ #include <plat/regs-serial.h> -#include <asm/plat-s3c/regs-watchdog.h> +#include <plat/regs-watchdog.h> /* working in physical space... */ #undef S3C2410_WDOGREG @@ -37,7 +37,7 @@ static void arch_detect_cpu(void); /* how many bytes we allow into the FIFO at a time in FIFO mode */ #define FIFO_MAX (14) -#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT) +#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT) static __inline__ void uart_wr(unsigned int reg, unsigned int val) @@ -139,6 +139,28 @@ static void arch_decomp_error(const char *x) static void error(char *err); +#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO +static inline void arch_enable_uart_fifo(void) +{ + u32 fifocon = uart_rd(S3C2410_UFCON); + + if (!(fifocon & S3C2410_UFCON_FIFOMODE)) { + fifocon |= S3C2410_UFCON_RESETBOTH; + uart_wr(S3C2410_UFCON, fifocon); + + /* wait for fifo reset to complete */ + while (1) { + fifocon = uart_rd(S3C2410_UFCON); + if (!(fifocon & S3C2410_UFCON_RESETBOTH)) + break; + } + } +} +#else +#define arch_enable_uart_fifo() do { } while(0) +#endif + + static void arch_decomp_setup(void) { @@ -149,6 +171,12 @@ arch_decomp_setup(void) arch_detect_cpu(); arch_decomp_wdog_start(); + + /* Enable the UART FIFOs if they where not enabled and our + * configuration says we should turn them on. + */ + + arch_enable_uart_fifo(); } diff --git a/arch/arm/plat-s3c/init.c b/arch/arm/plat-s3c/init.c new file mode 100644 index 000000000000..6790edfaca6f --- /dev/null +++ b/arch/arm/plat-s3c/init.c @@ -0,0 +1,160 @@ +/* linux/arch/arm/plat-s3c/init.c + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C series CPU initialisation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> + +#include <mach/hardware.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +#include <plat/regs-serial.h> + +static struct cpu_table *cpu; + +static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, + struct cpu_table *tab, + unsigned int count) +{ + for (; count != 0; count--, tab++) { + if ((idcode & tab->idmask) == tab->idcode) + return tab; + } + + return NULL; +} + +void __init s3c_init_cpu(unsigned long idcode, + struct cpu_table *cputab, unsigned int cputab_size) +{ + cpu = s3c_lookup_cpu(idcode, cputab, cputab_size); + + if (cpu == NULL) { + printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode); + panic("Unknown S3C24XX CPU"); + } + + printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); + + if (cpu->map_io == NULL || cpu->init == NULL) { + printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); + panic("Unsupported Samsung CPU"); + } + + cpu->map_io(); +} + +/* s3c24xx_init_clocks + * + * Initialise the clock subsystem and associated information from the + * given master crystal value. + * + * xtal = 0 -> use default PLL crystal value (normally 12MHz) + * != 0 -> PLL crystal value in Hz +*/ + +void __init s3c24xx_init_clocks(int xtal) +{ + if (xtal == 0) + xtal = 12*1000*1000; + + if (cpu == NULL) + panic("s3c24xx_init_clocks: no cpu setup?\n"); + + if (cpu->init_clocks == NULL) + panic("s3c24xx_init_clocks: cpu has no clock init\n"); + else + (cpu->init_clocks)(xtal); +} + +/* uart management */ + +static int nr_uarts __initdata = 0; + +static struct s3c2410_uartcfg uart_cfgs[CONFIG_SERIAL_SAMSUNG_UARTS]; + +/* s3c24xx_init_uartdevs + * + * copy the specified platform data and configuration into our central + * set of devices, before the data is thrown away after the init process. + * + * This also fills in the array passed to the serial driver for the + * early initialisation of the console. +*/ + +void __init s3c24xx_init_uartdevs(char *name, + struct s3c24xx_uart_resources *res, + struct s3c2410_uartcfg *cfg, int no) +{ + struct platform_device *platdev; + struct s3c2410_uartcfg *cfgptr = uart_cfgs; + struct s3c24xx_uart_resources *resp; + int uart; + + memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); + + for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { + platdev = s3c24xx_uart_src[cfgptr->hwport]; + + resp = res + cfgptr->hwport; + + s3c24xx_uart_devs[uart] = platdev; + + platdev->name = name; + platdev->resource = resp->resources; + platdev->num_resources = resp->nr_resources; + + platdev->dev.platform_data = cfgptr; + } + + nr_uarts = no; +} + +void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + if (cpu == NULL) + return; + + if (cpu->init_uarts == NULL) { + printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); + } else + (cpu->init_uarts)(cfg, no); +} + +static int __init s3c_arch_init(void) +{ + int ret; + + // do the correct init for cpu + + if (cpu == NULL) + panic("s3c_arch_init: NULL cpu\n"); + + ret = (cpu->init)(); + if (ret != 0) + return ret; + + ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); + return ret; +} + +arch_initcall(s3c_arch_init); diff --git a/arch/arm/plat-s3c24xx/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c index 3fad68a1e6bc..a318215ab535 100644 --- a/arch/arm/plat-s3c24xx/pwm-clock.c +++ b/arch/arm/plat-s3c/pwm-clock.c @@ -14,20 +14,20 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/errno.h> +#include <linux/log2.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> #include <mach/hardware.h> +#include <mach/map.h> #include <asm/irq.h> -#include <mach/regs-clock.h> -#include <mach/regs-gpio.h> - #include <plat/clock.h> #include <plat/cpu.h> #include <plat/regs-timer.h> +#include <mach/pwm-clock.h> /* Each of the timers 0 through 5 go through the following * clock tree, with the inputs depending on the timers. @@ -73,11 +73,13 @@ * tclk -------------------------/ */ -static unsigned long clk_pwm_scaler_getrate(struct clk *clk) +static struct clk clk_timer_scaler[]; + +static unsigned long clk_pwm_scaler_get_rate(struct clk *clk) { unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); - if (clk->id == 1) { + if (clk == &clk_timer_scaler[1]) { tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK; tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT; } else { @@ -87,18 +89,61 @@ static unsigned long clk_pwm_scaler_getrate(struct clk *clk) return clk_get_rate(clk->parent) / (tcfg0 + 1); } -/* TODO - add set rate calls. */ +static unsigned long clk_pwm_scaler_round_rate(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long divisor = parent_rate / rate; + + if (divisor > 256) + divisor = 256; + else if (divisor < 2) + divisor = 2; + + return parent_rate / divisor; +} + +static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long round = clk_pwm_scaler_round_rate(clk, rate); + unsigned long tcfg0; + unsigned long divisor; + unsigned long flags; + + divisor = clk_get_rate(clk->parent) / round; + divisor--; + + local_irq_save(flags); + tcfg0 = __raw_readl(S3C2410_TCFG0); + + if (clk == &clk_timer_scaler[1]) { + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; + tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT; + } else { + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; + tcfg0 |= divisor; + } + + __raw_writel(tcfg0, S3C2410_TCFG0); + local_irq_restore(flags); + + return 0; +} static struct clk clk_timer_scaler[] = { [0] = { .name = "pwm-scaler0", .id = -1, - .get_rate = clk_pwm_scaler_getrate, + .get_rate = clk_pwm_scaler_get_rate, + .set_rate = clk_pwm_scaler_set_rate, + .round_rate = clk_pwm_scaler_round_rate, }, [1] = { .name = "pwm-scaler1", .id = -1, - .get_rate = clk_pwm_scaler_getrate, + .get_rate = clk_pwm_scaler_get_rate, + .set_rate = clk_pwm_scaler_set_rate, + .round_rate = clk_pwm_scaler_round_rate, }, }; @@ -123,11 +168,6 @@ static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) return container_of(clk, struct pwm_tdiv_clk, clk); } -static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) -{ - return 1 << (1 + tcfg1); -} - static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) { unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); @@ -136,7 +176,7 @@ static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); tcfg1 &= S3C2410_TCFG1_MUX_MASK; - if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) + if (pwm_cfg_src_is_tclk(tcfg1)) divisor = to_tdiv(clk)->divisor; else divisor = tcfg_to_divisor(tcfg1); @@ -153,7 +193,9 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, parent_rate = clk_get_rate(clk->parent); divisor = parent_rate / rate; - if (divisor <= 2) + if (divisor <= 1 && pwm_tdiv_has_div1()) + divisor = 1; + else if (divisor <= 2) divisor = 2; else if (divisor <= 4) divisor = 4; @@ -167,25 +209,7 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) { - unsigned long bits; - - switch (divclk->divisor) { - case 2: - bits = S3C2410_TCFG1_MUX_DIV2; - break; - case 4: - bits = S3C2410_TCFG1_MUX_DIV4; - break; - case 8: - bits = S3C2410_TCFG1_MUX_DIV8; - break; - case 16: - default: - bits = S3C2410_TCFG1_MUX_DIV16; - break; - } - - return bits; + return pwm_tdiv_div_bits(divclk->divisor); } static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) @@ -226,7 +250,7 @@ static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) /* Update the current MUX settings if we are currently * selected as the clock source for this clock. */ - if (tcfg1 != S3C2410_TCFG1_MUX_TCLK) + if (!pwm_cfg_src_is_tclk(tcfg1)) clk_pwm_tdiv_update(divclk); return 0; @@ -313,7 +337,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) unsigned long shift = S3C2410_TCFG1_SHIFT(id); if (parent == s3c24xx_pwmclk_tclk(id)) - bits = S3C2410_TCFG1_MUX_TCLK << shift; + bits = S3C_TCFG1_MUX_TCLK << shift; else if (parent == s3c24xx_pwmclk_tdiv(id)) bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; else @@ -375,7 +399,7 @@ static __init int clk_pwm_tin_register(struct clk *pwm) tcfg1 >>= S3C2410_TCFG1_SHIFT(id); tcfg1 &= S3C2410_TCFG1_MUX_MASK; - if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) + if (pwm_cfg_src_is_tclk(tcfg1)) parent = s3c24xx_pwmclk_tclk(id); else parent = s3c24xx_pwmclk_tdiv(id); @@ -383,7 +407,16 @@ static __init int clk_pwm_tin_register(struct clk *pwm) return clk_set_parent(pwm, parent); } -static __init int s3c24xx_pwmclk_init(void) +/** + * s3c_pwmclk_init() - initialise pwm clocks + * + * Initialise and register the clocks which provide the inputs for the + * pwm timer blocks. + * + * Note, this call is required by the time core, so must be called after + * the base clocks are added and before any of the initcalls are run. + */ +__init void s3c_pwmclk_init(void) { struct clk *clk_timers; unsigned int clk; @@ -392,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void) clk_timers = clk_get(NULL, "timers"); if (IS_ERR(clk_timers)) { printk(KERN_ERR "%s: no parent clock\n", __func__); - return -EINVAL; + return; } for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { @@ -400,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); if (ret < 0) { printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); - goto err; + return; } } @@ -408,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); if (ret < 0) { printk(KERN_ERR "error adding pww tclk%d\n", clk); - goto err; + return; } } @@ -416,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = clk_pwm_tdiv_register(clk); if (ret < 0) { printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); - goto err; + return; } } @@ -424,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = clk_pwm_tin_register(&clk_tin[clk]); if (ret < 0) { printk(KERN_ERR "error adding pwm%d tin clock\n", clk); - goto err; + return; } } - - return 0; - - err: - return ret; } - -arch_initcall(s3c24xx_pwmclk_init); diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c/time.c index c51916236ac0..3b27b29da478 100644 --- a/arch/arm/plat-s3c24xx/time.c +++ b/arch/arm/plat-s3c/time.c @@ -26,6 +26,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <asm/system.h> #include <asm/leds.h> @@ -36,6 +37,7 @@ #include <plat/regs-timer.h> #include <mach/regs-irq.h> #include <asm/mach/time.h> +#include <mach/tick.h> #include <plat/clock.h> #include <plat/cpu.h> @@ -43,6 +45,10 @@ static unsigned long timer_startval; static unsigned long timer_usec_ticks; +#ifndef TICK_MAX +#define TICK_MAX (0xffff) +#endif + #define TIMER_USEC_SHIFT 16 /* we use the shifted arithmetic to work out the ratio of timer ticks @@ -91,23 +97,19 @@ static inline unsigned long timer_ticks_to_usec(unsigned long ticks) * IRQs are disabled before entering here from do_gettimeofday() */ -#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) - static unsigned long s3c2410_gettimeoffset (void) { unsigned long tdone; - unsigned long irqpend; unsigned long tval; /* work out how many ticks have gone since last timer interrupt */ - tval = __raw_readl(S3C2410_TCNTO(4)); + tval = __raw_readl(S3C2410_TCNTO(4)); tdone = timer_startval - tval; /* check to see if there is an interrupt pending */ - irqpend = __raw_readl(S3C2410_SRCPND); - if (irqpend & SRCPND_TIMER4) { + if (s3c24xx_ostimer_pending()) { /* re-read the timer, and try and fix up for the missed * interrupt. Note, the interrupt may go off before the * timer has re-loaded from wrapping. @@ -144,7 +146,11 @@ static struct irqaction s3c2410_timer_irq = { machine_is_bast() || \ machine_is_vr1000() || \ machine_is_anubis() || \ - machine_is_osiris() ) + machine_is_osiris()) + +static struct clk *tin; +static struct clk *tdiv; +static struct clk *timerclk; /* * Set up timer interrupt, and return the current time in seconds. @@ -159,13 +165,7 @@ static void s3c2410_timer_setup (void) unsigned long tcfg1; unsigned long tcfg0; - tcnt = 0xffff; /* default value for tcnt */ - - /* read the current timer configuration bits */ - - tcon = __raw_readl(S3C2410_TCON); - tcfg1 = __raw_readl(S3C2410_TCFG1); - tcfg0 = __raw_readl(S3C2410_TCFG0); + tcnt = TICK_MAX; /* default value for tcnt */ /* configure the system for whichever machine is in use */ @@ -174,11 +174,13 @@ static void s3c2410_timer_setup (void) timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); tcnt = 12000000 / HZ; + tcfg1 = __raw_readl(S3C2410_TCFG1); tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; + __raw_writel(tcfg1, S3C2410_TCFG1); } else { unsigned long pclk; - struct clk *clk; + struct clk *tscaler; /* for the h1940 (and others), we use the pclk from the core * to generate the timer values. since values around 50 to @@ -189,38 +191,34 @@ static void s3c2410_timer_setup (void) * (8.45 ticks per usec) */ - /* this is used as default if no other timer can be found */ - - clk = clk_get(NULL, "timers"); - if (IS_ERR(clk)) - panic("failed to get clock for system timer"); - - clk_enable(clk); - - pclk = clk_get_rate(clk); + pclk = clk_get_rate(timerclk); /* configure clock tick */ timer_usec_ticks = timer_mask_usec_ticks(6, pclk); - tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; - tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; + tscaler = clk_get_parent(tdiv); - tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; - tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; + clk_set_rate(tscaler, pclk / 3); + clk_set_rate(tdiv, pclk / 6); + clk_set_parent(tin, tdiv); - tcnt = (pclk / 6) / HZ; + tcnt = clk_get_rate(tin) / HZ; } + tcon = __raw_readl(S3C2410_TCON); + tcfg0 = __raw_readl(S3C2410_TCFG0); + tcfg1 = __raw_readl(S3C2410_TCFG1); + /* timers reload after counting zero, so reduce the count by 1 */ tcnt--; - printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", + printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); /* check to see if timer is within 16bit range... */ - if (tcnt > 0xffff) { + if (tcnt > TICK_MAX) { panic("setup_timer: HZ is too small, cannot configure timer!"); return; } @@ -247,8 +245,35 @@ static void s3c2410_timer_setup (void) __raw_writel(tcon, S3C2410_TCON); } -static void __init s3c2410_timer_init (void) +static void __init s3c2410_timer_resources(void) +{ + struct platform_device tmpdev; + + tmpdev.dev.bus = &platform_bus_type; + tmpdev.id = 4; + + timerclk = clk_get(NULL, "timers"); + if (IS_ERR(timerclk)) + panic("failed to get clock for system timer"); + + clk_enable(timerclk); + + if (!use_tclk1_12()) { + tin = clk_get(&tmpdev.dev, "pwm-tin"); + if (IS_ERR(tin)) + panic("failed to get pwm-tin clock for system timer"); + + tdiv = clk_get(&tmpdev.dev, "pwm-tdiv"); + if (IS_ERR(tdiv)) + panic("failed to get pwm-tdiv clock for system timer"); + } + + clk_enable(tin); +} + +static void __init s3c2410_timer_init(void) { + s3c2410_timer_resources(); s3c2410_timer_setup(); setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); } diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 0af3872fb763..2c8a2f5d75ff 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -6,8 +6,8 @@ config PLAT_S3C24XX bool - depends on ARCH_S3C2410 - default y if ARCH_S3C2410 + depends on ARCH_S3C2410 || ARCH_S3C24A0 + default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB help @@ -15,6 +15,19 @@ config PLAT_S3C24XX if PLAT_S3C24XX +# code that is shared between a number of the s3c24xx implementations + +config S3C2410_CLOCK + bool + help + Clock code for the S3C2410, and similar processors which + is currently includes the S3C2410, S3C2440, S3C2442. + +config S3C24XX_DCLK + bool + help + Clock code for supporting DCLK/CLKOUT on S3C24XX architectures + config CPU_S3C244X bool depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442) @@ -28,6 +41,27 @@ config S3C24XX_PWM Support for exporting the PWM timer blocks via the pwm device system. + +# gpio configurations + +config S3C24XX_GPIO_EXTRA + int + default 128 if S3C24XX_GPIO_EXTRA128 + default 64 if S3C24XX_GPIO_EXTRA64 + default 0 + +config S3C24XX_GPIO_EXTRA64 + bool + help + Add an extra 64 gpio numbers to the available GPIO pool. This is + available for boards that need extra gpios for external devices. + +config S3C24XX_GPIO_EXTRA128 + bool + help + Add an extra 128 gpio numbers to the available GPIO pool. This is + available for boards that need extra gpios for external devices. + config PM_SIMTEC bool help @@ -49,6 +83,29 @@ config S3C2410_DMA_DEBUG Enable debugging output for the DMA code. This option sends info to the kernel log, at priority KERN_DEBUG. +config S3C24XX_ADC + bool "ADC common driver support" + help + Core support for the ADC block found in the S3C24XX SoC systems + for drivers such as the touchscreen and hwmon to use to share + this resource. + +# SPI default pin configuration code + +config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13 + bool + help + SPI GPIO configuration code for BUS0 when connected to + GPE11, GPE12 and GPE13. + +config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7 + bool + help + SPI GPIO configuration code for BUS 1 when connected to + GPG5, GPG6 and GPG7. + +# common code for s3c24xx based machines, such as the SMDKs. + config MACH_SMDK bool help diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index d82767b2b833..1e0767b266b8 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -17,9 +17,8 @@ obj-y += irq.o obj-y += devs.o obj-y += gpio.o obj-y += gpiolib.o -obj-y += time.o obj-y += clock.o -obj-y += pwm-clock.o +obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o # Architecture dependant builds @@ -30,5 +29,18 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += sleep.o obj-$(CONFIG_HAVE_PWM) += pwm.o +obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o obj-$(CONFIG_S3C2410_DMA) += dma.o +obj-$(CONFIG_S3C24XX_ADC) += adc.o + +# device specific setup and/or initialisation +obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o + +# SPI gpio central GPIO functions + +obj-$(CONFIG_S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13) += spi-bus0-gpe11_12_13.o +obj-$(CONFIG_S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7) += spi-bus1-gpg5_6_7.o + +# machine common support + obj-$(CONFIG_MACH_SMDK) += common-smdk.o diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c new file mode 100644 index 000000000000..9a5c767e0a42 --- /dev/null +++ b/arch/arm/plat-s3c24xx/adc.c @@ -0,0 +1,372 @@ +/* arch/arm/plat-s3c24xx/adc.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> + * + * S3C24XX ADC device core + * + * 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. +*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/io.h> + +#include <plat/regs-adc.h> +#include <plat/adc.h> + +/* This driver is designed to control the usage of the ADC block between + * the touchscreen and any other drivers that may need to use it, such as + * the hwmon driver. + * + * Priority will be given to the touchscreen driver, but as this itself is + * rate limited it should not starve other requests which are processed in + * order that they are received. + * + * Each user registers to get a client block which uniquely identifies it + * and stores information such as the necessary functions to callback when + * action is required. + */ + +struct s3c_adc_client { + struct platform_device *pdev; + struct list_head pend; + + unsigned int nr_samples; + unsigned char is_ts; + unsigned char channel; + + void (*select_cb)(unsigned selected); + void (*convert_cb)(unsigned val1, unsigned val2); +}; + +struct adc_device { + struct platform_device *pdev; + struct platform_device *owner; + struct clk *clk; + struct s3c_adc_client *cur; + struct s3c_adc_client *ts_pend; + void __iomem *regs; + + unsigned int prescale; + + int irq; +}; + +static struct adc_device *adc_dev; + +static LIST_HEAD(adc_pending); + +#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg) + +static inline void s3c_adc_convert(struct adc_device *adc) +{ + unsigned con = readl(adc->regs + S3C2410_ADCCON); + + con |= S3C2410_ADCCON_ENABLE_START; + writel(con, adc->regs + S3C2410_ADCCON); +} + +static inline void s3c_adc_select(struct adc_device *adc, + struct s3c_adc_client *client) +{ + unsigned con = readl(adc->regs + S3C2410_ADCCON); + + client->select_cb(1); + + con &= ~S3C2410_ADCCON_MUXMASK; + con &= ~S3C2410_ADCCON_STDBM; + con &= ~S3C2410_ADCCON_STARTMASK; + + if (!client->is_ts) + con |= S3C2410_ADCCON_SELMUX(client->channel); + + writel(con, adc->regs + S3C2410_ADCCON); +} + +static void s3c_adc_dbgshow(struct adc_device *adc) +{ + adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n", + readl(adc->regs + S3C2410_ADCCON), + readl(adc->regs + S3C2410_ADCTSC), + readl(adc->regs + S3C2410_ADCDLY)); +} + +void s3c_adc_try(struct adc_device *adc) +{ + struct s3c_adc_client *next = adc->ts_pend; + + if (!next && !list_empty(&adc_pending)) { + next = list_first_entry(&adc_pending, + struct s3c_adc_client, pend); + list_del(&next->pend); + } else + adc->ts_pend = NULL; + + if (next) { + adc_dbg(adc, "new client is %p\n", next); + adc->cur = next; + s3c_adc_select(adc, next); + s3c_adc_convert(adc); + s3c_adc_dbgshow(adc); + } +} + +int s3c_adc_start(struct s3c_adc_client *client, + unsigned int channel, unsigned int nr_samples) +{ + struct adc_device *adc = adc_dev; + unsigned long flags; + + if (!adc) { + printk(KERN_ERR "%s: failed to find adc\n", __func__); + return -EINVAL; + } + + if (client->is_ts && adc->ts_pend) + return -EAGAIN; + + local_irq_save(flags); + + client->channel = channel; + client->nr_samples = nr_samples; + + if (client->is_ts) + adc->ts_pend = client; + else + list_add_tail(&client->pend, &adc_pending); + + if (!adc->cur) + s3c_adc_try(adc); + local_irq_restore(flags); + + return 0; +} +EXPORT_SYMBOL_GPL(s3c_adc_start); + +static void s3c_adc_default_select(unsigned select) +{ +} + +struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, + void (*select)(unsigned int selected), + void (*conv)(unsigned d0, unsigned d1), + unsigned int is_ts) +{ + struct s3c_adc_client *client; + + WARN_ON(!pdev); + WARN_ON(!conv); + + if (!select) + select = s3c_adc_default_select; + + if (!conv || !pdev) + return ERR_PTR(-EINVAL); + + client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); + if (!client) { + dev_err(&pdev->dev, "no memory for adc client\n"); + return ERR_PTR(-ENOMEM); + } + + client->pdev = pdev; + client->is_ts = is_ts; + client->select_cb = select; + client->convert_cb = conv; + + return client; +} +EXPORT_SYMBOL_GPL(s3c_adc_register); + +void s3c_adc_release(struct s3c_adc_client *client) +{ + /* We should really check that nothing is in progress. */ + kfree(client); +} +EXPORT_SYMBOL_GPL(s3c_adc_release); + +static irqreturn_t s3c_adc_irq(int irq, void *pw) +{ + struct adc_device *adc = pw; + struct s3c_adc_client *client = adc->cur; + unsigned long flags; + unsigned data0, data1; + + if (!client) { + dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__); + return IRQ_HANDLED; + } + + data0 = readl(adc->regs + S3C2410_ADCDAT0); + data1 = readl(adc->regs + S3C2410_ADCDAT1); + adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); + + (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff); + + if (--client->nr_samples > 0) { + /* fire another conversion for this */ + + client->select_cb(1); + s3c_adc_convert(adc); + } else { + local_irq_save(flags); + (client->select_cb)(0); + adc->cur = NULL; + + s3c_adc_try(adc); + local_irq_restore(flags); + } + + return IRQ_HANDLED; +} + +static int s3c_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct adc_device *adc; + struct resource *regs; + int ret; + + adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL); + if (adc == NULL) { + dev_err(dev, "failed to allocate adc_device\n"); + return -ENOMEM; + } + + adc->pdev = pdev; + adc->prescale = S3C2410_ADCCON_PRSCVL(49); + + adc->irq = platform_get_irq(pdev, 1); + if (adc->irq <= 0) { + dev_err(dev, "failed to get adc irq\n"); + ret = -ENOENT; + goto err_alloc; + } + + ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); + if (ret < 0) { + dev_err(dev, "failed to attach adc irq\n"); + goto err_alloc; + } + + adc->clk = clk_get(dev, "adc"); + if (IS_ERR(adc->clk)) { + dev_err(dev, "failed to get adc clock\n"); + ret = PTR_ERR(adc->clk); + goto err_irq; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(dev, "failed to find registers\n"); + ret = -ENXIO; + goto err_clk; + } + + adc->regs = ioremap(regs->start, resource_size(regs)); + if (!adc->regs) { + dev_err(dev, "failed to map registers\n"); + ret = -ENXIO; + goto err_clk; + } + + clk_enable(adc->clk); + + writel(adc->prescale | S3C2410_ADCCON_PRSCEN, + adc->regs + S3C2410_ADCCON); + + dev_info(dev, "attached adc driver\n"); + + platform_set_drvdata(pdev, adc); + adc_dev = adc; + + return 0; + + err_clk: + clk_put(adc->clk); + + err_irq: + free_irq(adc->irq, adc); + + err_alloc: + kfree(adc); + return ret; +} + +static int s3c_adc_remove(struct platform_device *pdev) +{ + struct adc_device *adc = platform_get_drvdata(pdev); + + iounmap(adc->regs); + free_irq(adc->irq, adc); + clk_disable(adc->clk); + clk_put(adc->clk); + kfree(adc); + + return 0; +} + +#ifdef CONFIG_PM +static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct adc_device *adc = platform_get_drvdata(pdev); + u32 con; + + con = readl(adc->regs + S3C2410_ADCCON); + con |= S3C2410_ADCCON_STDBM; + writel(con, adc->regs + S3C2410_ADCCON); + + clk_disable(adc->clk); + + return 0; +} + +static int s3c_adc_resume(struct platform_device *pdev) +{ + struct adc_device *adc = platform_get_drvdata(pdev); + + clk_enable(adc->clk); + + writel(adc->prescale | S3C2410_ADCCON_PRSCEN, + adc->regs + S3C2410_ADCCON); + + return 0; +} + +#else +#define s3c_adc_suspend NULL +#define s3c_adc_resume NULL +#endif + +static struct platform_driver s3c_adc_driver = { + .driver = { + .name = "s3c24xx-adc", + .owner = THIS_MODULE, + }, + .probe = s3c_adc_probe, + .remove = __devexit_p(s3c_adc_remove), + .suspend = s3c_adc_suspend, + .resume = s3c_adc_resume, +}; + +static int __init adc_init(void) +{ + int ret; + + ret = platform_driver_register(&s3c_adc_driver); + if (ret) + printk(KERN_ERR "%s: failed to add adc driver\n", __func__); + + return ret; +} + +arch_initcall(adc_init); diff --git a/arch/arm/plat-s3c24xx/clock-dclk.c b/arch/arm/plat-s3c24xx/clock-dclk.c new file mode 100644 index 000000000000..5b75a797b5ab --- /dev/null +++ b/arch/arm/plat-s3c24xx/clock-dclk.c @@ -0,0 +1,194 @@ +/* linux/arch/arm/plat-s3c24xx/clock-dclk.c + * + * Copyright (c) 2004,2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C24XX - definitions for DCLK and CLKOUT registers + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <mach/regs-clock.h> +#include <mach/regs-gpio.h> + +#include <plat/clock.h> +#include <plat/cpu.h> + +/* clocks that could be registered by external code */ + +static int s3c24xx_dclk_enable(struct clk *clk, int enable) +{ + unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); + + if (enable) + dclkcon |= clk->ctrlbit; + else + dclkcon &= ~clk->ctrlbit; + + __raw_writel(dclkcon, S3C24XX_DCLKCON); + + return 0; +} + +static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) +{ + unsigned long dclkcon; + unsigned int uclk; + + if (parent == &clk_upll) + uclk = 1; + else if (parent == &clk_p) + uclk = 0; + else + return -EINVAL; + + clk->parent = parent; + + dclkcon = __raw_readl(S3C24XX_DCLKCON); + + if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { + if (uclk) + dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; + else + dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; + } else { + if (uclk) + dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; + else + dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; + } + + __raw_writel(dclkcon, S3C24XX_DCLKCON); + + return 0; +} +static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate) +{ + unsigned long div; + + if ((rate == 0) || !clk->parent) + return 0; + + div = clk_get_rate(clk->parent) / rate; + if (div < 2) + div = 2; + else if (div > 16) + div = 16; + + return div; +} + +static unsigned long s3c24xx_round_dclk_rate(struct clk *clk, + unsigned long rate) +{ + unsigned long div = s3c24xx_calc_div(clk, rate); + + if (div == 0) + return 0; + + return clk_get_rate(clk->parent) / div; +} + +static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate) +{ + unsigned long mask, data, div = s3c24xx_calc_div(clk, rate); + + if (div == 0) + return -EINVAL; + + if (clk == &s3c24xx_dclk0) { + mask = S3C2410_DCLKCON_DCLK0_DIV_MASK | + S3C2410_DCLKCON_DCLK0_CMP_MASK; + data = S3C2410_DCLKCON_DCLK0_DIV(div) | + S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2); + } else if (clk == &s3c24xx_dclk1) { + mask = S3C2410_DCLKCON_DCLK1_DIV_MASK | + S3C2410_DCLKCON_DCLK1_CMP_MASK; + data = S3C2410_DCLKCON_DCLK1_DIV(div) | + S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2); + } else + return -EINVAL; + + clk->rate = clk_get_rate(clk->parent) / div; + __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data), + S3C24XX_DCLKCON); + return clk->rate; +} +static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) +{ + unsigned long mask; + unsigned long source; + + /* calculate the MISCCR setting for the clock */ + + if (parent == &clk_xtal) + source = S3C2410_MISCCR_CLK0_MPLL; + else if (parent == &clk_upll) + source = S3C2410_MISCCR_CLK0_UPLL; + else if (parent == &clk_f) + source = S3C2410_MISCCR_CLK0_FCLK; + else if (parent == &clk_h) + source = S3C2410_MISCCR_CLK0_HCLK; + else if (parent == &clk_p) + source = S3C2410_MISCCR_CLK0_PCLK; + else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) + source = S3C2410_MISCCR_CLK0_DCLK0; + else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) + source = S3C2410_MISCCR_CLK0_DCLK0; + else + return -EINVAL; + + clk->parent = parent; + + if (clk == &s3c24xx_clkout0) + mask = S3C2410_MISCCR_CLK0_MASK; + else { + source <<= 4; + mask = S3C2410_MISCCR_CLK1_MASK; + } + + s3c2410_modify_misccr(mask, source); + return 0; +} + +/* external clock definitions */ + +struct clk s3c24xx_dclk0 = { + .name = "dclk0", + .id = -1, + .ctrlbit = S3C2410_DCLKCON_DCLK0EN, + .enable = s3c24xx_dclk_enable, + .set_parent = s3c24xx_dclk_setparent, + .set_rate = s3c24xx_set_dclk_rate, + .round_rate = s3c24xx_round_dclk_rate, +}; + +struct clk s3c24xx_dclk1 = { + .name = "dclk1", + .id = -1, + .ctrlbit = S3C2410_DCLKCON_DCLK1EN, + .enable = s3c24xx_dclk_enable, + .set_parent = s3c24xx_dclk_setparent, + .set_rate = s3c24xx_set_dclk_rate, + .round_rate = s3c24xx_round_dclk_rate, +}; + +struct clk s3c24xx_clkout0 = { + .name = "clkout0", + .id = -1, + .set_parent = s3c24xx_clkout_setparent, +}; + +struct clk s3c24xx_clkout1 = { + .name = "clkout1", + .id = -1, + .set_parent = s3c24xx_clkout_setparent, +}; diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c index a005ddbd9ef3..8474d05274bd 100644 --- a/arch/arm/plat-s3c24xx/clock.c +++ b/arch/arm/plat-s3c24xx/clock.c @@ -27,18 +27,8 @@ */ #include <linux/init.h> -#include <linux/module.h> #include <linux/kernel.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/sysdev.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> #include <linux/clk.h> -#include <linux/mutex.h> -#include <linux/delay.h> #include <linux/io.h> #include <mach/hardware.h> @@ -47,490 +37,23 @@ #include <mach/regs-clock.h> #include <mach/regs-gpio.h> +#include <plat/cpu-freq.h> + #include <plat/clock.h> #include <plat/cpu.h> - -/* clock information */ - -static LIST_HEAD(clocks); - -DEFINE_MUTEX(clocks_mutex); - -/* enable and disable calls for use with the clk struct */ - -static int clk_null_enable(struct clk *clk, int enable) -{ - return 0; -} - -/* Clock API calls */ - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p; - struct clk *clk = ERR_PTR(-ENOENT); - int idno; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - list_for_each_entry(p, &clocks, list) { - if (p->id == idno && - strcmp(id, p->name) == 0 && - try_module_get(p->owner)) { - clk = p; - break; - } - } - - /* check for the case where a device was supplied, but the - * clock that was being searched for is not device specific */ - - if (IS_ERR(clk)) { - list_for_each_entry(p, &clocks, list) { - if (p->id == -1 && strcmp(id, p->name) == 0 && - try_module_get(p->owner)) { - clk = p; - break; - } - } - } - - mutex_unlock(&clocks_mutex); - return clk; -} - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} - -int clk_enable(struct clk *clk) -{ - if (IS_ERR(clk) || clk == NULL) - return -EINVAL; - - clk_enable(clk->parent); - - mutex_lock(&clocks_mutex); - - if ((clk->usage++) == 0) - (clk->enable)(clk, 1); - - mutex_unlock(&clocks_mutex); - return 0; -} - -void clk_disable(struct clk *clk) -{ - if (IS_ERR(clk) || clk == NULL) - return; - - mutex_lock(&clocks_mutex); - - if ((--clk->usage) == 0) - (clk->enable)(clk, 0); - - mutex_unlock(&clocks_mutex); - clk_disable(clk->parent); -} - - -unsigned long clk_get_rate(struct clk *clk) -{ - if (IS_ERR(clk)) - return 0; - - if (clk->rate != 0) - return clk->rate; - - if (clk->get_rate != NULL) - return (clk->get_rate)(clk); - - if (clk->parent != NULL) - return clk_get_rate(clk->parent); - - return clk->rate; -} - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (!IS_ERR(clk) && clk->round_rate) - return (clk->round_rate)(clk, rate); - - return rate; -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - - if (IS_ERR(clk)) - return -EINVAL; - - /* We do not default just do a clk->rate = rate as - * the clock may have been made this way by choice. - */ - - WARN_ON(clk->set_rate == NULL); - - if (clk->set_rate == NULL) - return -EINVAL; - - mutex_lock(&clocks_mutex); - ret = (clk->set_rate)(clk, rate); - mutex_unlock(&clocks_mutex); - - return ret; -} - -struct clk *clk_get_parent(struct clk *clk) -{ - return clk->parent; -} - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - int ret = 0; - - if (IS_ERR(clk)) - return -EINVAL; - - mutex_lock(&clocks_mutex); - - if (clk->set_parent) - ret = (clk->set_parent)(clk, parent); - - mutex_unlock(&clocks_mutex); - - return ret; -} - -EXPORT_SYMBOL(clk_get); -EXPORT_SYMBOL(clk_put); -EXPORT_SYMBOL(clk_enable); -EXPORT_SYMBOL(clk_disable); -EXPORT_SYMBOL(clk_get_rate); -EXPORT_SYMBOL(clk_round_rate); -EXPORT_SYMBOL(clk_set_rate); -EXPORT_SYMBOL(clk_get_parent); -EXPORT_SYMBOL(clk_set_parent); - -/* base clocks */ - -static int clk_default_setrate(struct clk *clk, unsigned long rate) -{ - clk->rate = rate; - return 0; -} - -struct clk clk_xtal = { - .name = "xtal", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_mpll = { - .name = "mpll", - .id = -1, - .set_rate = clk_default_setrate, -}; - -struct clk clk_upll = { - .name = "upll", - .id = -1, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_f = { - .name = "fclk", - .id = -1, - .rate = 0, - .parent = &clk_mpll, - .ctrlbit = 0, - .set_rate = clk_default_setrate, -}; - -struct clk clk_h = { - .name = "hclk", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, - .set_rate = clk_default_setrate, -}; - -struct clk clk_p = { - .name = "pclk", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, - .set_rate = clk_default_setrate, -}; - -struct clk clk_usb_bus = { - .name = "usb-bus", - .id = -1, - .rate = 0, - .parent = &clk_upll, -}; - -/* clocks that could be registered by external code */ - -static int s3c24xx_dclk_enable(struct clk *clk, int enable) -{ - unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (enable) - dclkcon |= clk->ctrlbit; - else - dclkcon &= ~clk->ctrlbit; - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - -static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long dclkcon; - unsigned int uclk; - - if (parent == &clk_upll) - uclk = 1; - else if (parent == &clk_p) - uclk = 0; - else - return -EINVAL; - - clk->parent = parent; - - dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; - } else { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; - } - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - -static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate) -{ - unsigned long div; - - if ((rate == 0) || !clk->parent) - return 0; - - div = clk_get_rate(clk->parent) / rate; - if (div < 2) - div = 2; - else if (div > 16) - div = 16; - - return div; -} - -static unsigned long s3c24xx_round_dclk_rate(struct clk *clk, - unsigned long rate) -{ - unsigned long div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return 0; - - return clk_get_rate(clk->parent) / div; -} - -static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate) -{ - unsigned long mask, data, div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return -EINVAL; - - if (clk == &s3c24xx_dclk0) { - mask = S3C2410_DCLKCON_DCLK0_DIV_MASK | - S3C2410_DCLKCON_DCLK0_CMP_MASK; - data = S3C2410_DCLKCON_DCLK0_DIV(div) | - S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2); - } else if (clk == &s3c24xx_dclk1) { - mask = S3C2410_DCLKCON_DCLK1_DIV_MASK | - S3C2410_DCLKCON_DCLK1_CMP_MASK; - data = S3C2410_DCLKCON_DCLK1_DIV(div) | - S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2); - } else - return -EINVAL; - - clk->rate = clk_get_rate(clk->parent) / div; - __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data), - S3C24XX_DCLKCON); - return clk->rate; -} - -static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long mask; - unsigned long source; - - /* calculate the MISCCR setting for the clock */ - - if (parent == &clk_xtal) - source = S3C2410_MISCCR_CLK0_MPLL; - else if (parent == &clk_upll) - source = S3C2410_MISCCR_CLK0_UPLL; - else if (parent == &clk_f) - source = S3C2410_MISCCR_CLK0_FCLK; - else if (parent == &clk_h) - source = S3C2410_MISCCR_CLK0_HCLK; - else if (parent == &clk_p) - source = S3C2410_MISCCR_CLK0_PCLK; - else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) - source = S3C2410_MISCCR_CLK0_DCLK0; - else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) - source = S3C2410_MISCCR_CLK0_DCLK0; - else - return -EINVAL; - - clk->parent = parent; - - if (clk == &s3c24xx_clkout0) - mask = S3C2410_MISCCR_CLK0_MASK; - else { - source <<= 4; - mask = S3C2410_MISCCR_CLK1_MASK; - } - - s3c2410_modify_misccr(mask, source); - return 0; -} - -/* external clock definitions */ - -struct clk s3c24xx_dclk0 = { - .name = "dclk0", - .id = -1, - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, - .enable = s3c24xx_dclk_enable, - .set_parent = s3c24xx_dclk_setparent, - .set_rate = s3c24xx_set_dclk_rate, - .round_rate = s3c24xx_round_dclk_rate, -}; - -struct clk s3c24xx_dclk1 = { - .name = "dclk1", - .id = -1, - .ctrlbit = S3C2410_DCLKCON_DCLK1EN, - .enable = s3c24xx_dclk_enable, - .set_parent = s3c24xx_dclk_setparent, - .set_rate = s3c24xx_set_dclk_rate, - .round_rate = s3c24xx_round_dclk_rate, -}; - -struct clk s3c24xx_clkout0 = { - .name = "clkout0", - .id = -1, - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_clkout1 = { - .name = "clkout1", - .id = -1, - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_uclk = { - .name = "uclk", - .id = -1, -}; - -/* initialise the clock system */ - -int s3c24xx_register_clock(struct clk *clk) -{ - clk->owner = THIS_MODULE; - - if (clk->enable == NULL) - clk->enable = clk_null_enable; - - /* add to the list of available clocks */ - - mutex_lock(&clocks_mutex); - list_add(&clk->list, &clocks); - mutex_unlock(&clocks_mutex); - - return 0; -} - -int s3c24xx_register_clocks(struct clk **clks, int nr_clks) -{ - int fails = 0; - - for (; nr_clks > 0; nr_clks--, clks++) { - if (s3c24xx_register_clock(*clks) < 0) - fails++; - } - - return fails; -} +#include <plat/pll.h> /* initalise all the clocks */ -int __init s3c24xx_setup_clocks(unsigned long xtal, - unsigned long fclk, - unsigned long hclk, - unsigned long pclk) +void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, + unsigned long hclk, + unsigned long pclk) { - printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); - - /* initialise the main system clocks */ - - clk_xtal.rate = xtal; - clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); + clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON), + clk_xtal.rate); clk_mpll.rate = fclk; clk_h.rate = hclk; clk_p.rate = pclk; clk_f.rate = fclk; - - /* assume uart clocks are correctly setup */ - - /* register our clocks */ - - if (s3c24xx_register_clock(&clk_xtal) < 0) - printk(KERN_ERR "failed to register master xtal\n"); - - if (s3c24xx_register_clock(&clk_mpll) < 0) - printk(KERN_ERR "failed to register mpll clock\n"); - - if (s3c24xx_register_clock(&clk_upll) < 0) - printk(KERN_ERR "failed to register upll clock\n"); - - if (s3c24xx_register_clock(&clk_f) < 0) - printk(KERN_ERR "failed to register cpu fclk\n"); - - if (s3c24xx_register_clock(&clk_h) < 0) - printk(KERN_ERR "failed to register cpu hclk\n"); - - if (s3c24xx_register_clock(&clk_p) < 0) - printk(KERN_ERR "failed to register cpu pclk\n"); - - return 0; } diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c index 3098736c65d9..3d4837021ac7 100644 --- a/arch/arm/plat-s3c24xx/common-smdk.c +++ b/arch/arm/plat-s3c24xx/common-smdk.c @@ -38,7 +38,7 @@ #include <mach/regs-gpio.h> #include <mach/leds-gpio.h> -#include <asm/plat-s3c/nand.h> +#include <plat/nand.h> #include <plat/common-smdk.h> #include <plat/devs.h> diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 22a329513c0f..542062f8cbc1 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -30,7 +30,6 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/delay.h> #include <mach/hardware.h> #include <asm/irq.h> @@ -55,16 +54,6 @@ #include <plat/s3c2442.h> #include <plat/s3c2443.h> -struct cpu_table { - unsigned long idcode; - unsigned long idmask; - void (*map_io)(struct map_desc *mach_desc, int size); - void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no); - void (*init_clocks)(int xtal); - int (*init)(void); - const char *name; -}; - /* table of supported CPUs */ static const char name_s3c2400[] = "S3C2400"; @@ -169,23 +158,7 @@ static struct map_desc s3c_iodesc[] __initdata = { IODESC_ENT(UART) }; -static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode) -{ - struct cpu_table *tab; - int count; - - tab = cpu_ids; - for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) { - if ((idcode & tab->idmask) == tab->idcode) - return tab; - } - - return NULL; -} - -/* cpu information */ - -static struct cpu_table *cpu; +/* read cpu identificaiton code */ static unsigned long s3c24xx_read_idcode_v5(void) { @@ -231,6 +204,7 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) unsigned long idcode = 0x0; /* initialise the io descriptors we need for initialisation */ + iotable_init(mach_desc, size); iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); if (cpu_architecture() >= CPU_ARCH_ARMv5) { @@ -239,117 +213,7 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) idcode = s3c24xx_read_idcode_v4(); } - cpu = s3c_lookup_cpu(idcode); - - if (cpu == NULL) { - printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode); - panic("Unknown S3C24XX CPU"); - } - - printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); - - if (cpu->map_io == NULL || cpu->init == NULL) { - printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); - panic("Unsupported S3C24XX CPU"); - } - arm_pm_restart = s3c24xx_pm_restart; - (cpu->map_io)(mach_desc, size); -} - -/* s3c24xx_init_clocks - * - * Initialise the clock subsystem and associated information from the - * given master crystal value. - * - * xtal = 0 -> use default PLL crystal value (normally 12MHz) - * != 0 -> PLL crystal value in Hz -*/ - -void __init s3c24xx_init_clocks(int xtal) -{ - if (xtal == 0) - xtal = 12*1000*1000; - - if (cpu == NULL) - panic("s3c24xx_init_clocks: no cpu setup?\n"); - - if (cpu->init_clocks == NULL) - panic("s3c24xx_init_clocks: cpu has no clock init\n"); - else - (cpu->init_clocks)(xtal); + s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); } - -/* uart management */ - -static int nr_uarts __initdata = 0; - -static struct s3c2410_uartcfg uart_cfgs[3]; - -/* s3c24xx_init_uartdevs - * - * copy the specified platform data and configuration into our central - * set of devices, before the data is thrown away after the init process. - * - * This also fills in the array passed to the serial driver for the - * early initialisation of the console. -*/ - -void __init s3c24xx_init_uartdevs(char *name, - struct s3c24xx_uart_resources *res, - struct s3c2410_uartcfg *cfg, int no) -{ - struct platform_device *platdev; - struct s3c2410_uartcfg *cfgptr = uart_cfgs; - struct s3c24xx_uart_resources *resp; - int uart; - - memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); - - for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { - platdev = s3c24xx_uart_src[cfgptr->hwport]; - - resp = res + cfgptr->hwport; - - s3c24xx_uart_devs[uart] = platdev; - - platdev->name = name; - platdev->resource = resp->resources; - platdev->num_resources = resp->nr_resources; - - platdev->dev.platform_data = cfgptr; - } - - nr_uarts = no; -} - -void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - if (cpu == NULL) - return; - - if (cpu->init_uarts == NULL) { - printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); - } else - (cpu->init_uarts)(cfg, no); -} - -static int __init s3c_arch_init(void) -{ - int ret; - - // do the correct init for cpu - - if (cpu == NULL) - panic("s3c_arch_init: NULL cpu\n"); - - ret = (cpu->init)(); - if (ret != 0) - return ret; - - ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); - return ret; -} - -arch_initcall(s3c_arch_init); diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index e93f8bf6d338..16ac01d9b8ab 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -29,11 +29,11 @@ #include <asm/irq.h> #include <plat/regs-serial.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/udc.h> #include <plat/devs.h> #include <plat/cpu.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> /* Serial port registrations */ @@ -76,6 +76,19 @@ static struct resource s3c2410_uart2_resource[] = { } }; +static struct resource s3c2410_uart3_resource[] = { + [0] = { + .start = S3C2443_PA_UART3, + .end = S3C2443_PA_UART3 + 0x3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX3, + .end = IRQ_S3CUART_ERR3, + .flags = IORESOURCE_IRQ, + }, +}; + struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { [0] = { .resources = s3c2410_uart0_resource, @@ -89,6 +102,10 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { .resources = s3c2410_uart2_resource, .nr_resources = ARRAY_SIZE(s3c2410_uart2_resource), }, + [3] = { + .resources = s3c2410_uart3_resource, + .nr_resources = ARRAY_SIZE(s3c2410_uart3_resource), + }, }; /* yart devices */ @@ -105,13 +122,18 @@ static struct platform_device s3c24xx_uart_device2 = { .id = 2, }; -struct platform_device *s3c24xx_uart_src[3] = { +static struct platform_device s3c24xx_uart_device3 = { + .id = 3, +}; + +struct platform_device *s3c24xx_uart_src[4] = { &s3c24xx_uart_device0, &s3c24xx_uart_device1, &s3c24xx_uart_device2, + &s3c24xx_uart_device3, }; -struct platform_device *s3c24xx_uart_devs[3] = { +struct platform_device *s3c24xx_uart_devs[4] = { }; /* USB Host Controller */ @@ -192,8 +214,8 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) static struct resource s3c_nand_resource[] = { [0] = { - .start = S3C2410_PA_NAND, - .end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1, + .start = S3C24XX_PA_NAND, + .end = S3C24XX_PA_NAND + S3C24XX_SZ_NAND - 1, .flags = IORESOURCE_MEM, } }; @@ -271,31 +293,6 @@ struct platform_device s3c_device_wdt = { EXPORT_SYMBOL(s3c_device_wdt); -/* I2C */ - -static struct resource s3c_i2c_resource[] = { - [0] = { - .start = S3C24XX_PA_IIC, - .end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_IIC, - .end = IRQ_IIC, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_i2c = { - .name = "s3c2410-i2c", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_i2c_resource), - .resource = s3c_i2c_resource, -}; - -EXPORT_SYMBOL(s3c_device_i2c); - /* IIS */ static struct resource s3c_iis_resource[] = { @@ -372,18 +369,26 @@ static struct resource s3c_adc_resource[] = { }; struct platform_device s3c_device_adc = { - .name = "s3c2410-adc", + .name = "s3c24xx-adc", .id = -1, .num_resources = ARRAY_SIZE(s3c_adc_resource), .resource = s3c_adc_resource, }; +/* HWMON */ + +struct platform_device s3c_device_hwmon = { + .name = "s3c24xx-hwmon", + .id = -1, + .dev.parent = &s3c_device_adc.dev, +}; + /* SDI */ static struct resource s3c_sdi_resource[] = { [0] = { - .start = S3C2410_PA_SDI, - .end = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1, + .start = S3C24XX_PA_SDI, + .end = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -403,36 +408,6 @@ struct platform_device s3c_device_sdi = { EXPORT_SYMBOL(s3c_device_sdi); -/* High-speed MMC/SD */ - -static struct resource s3c_hsmmc_resource[] = { - [0] = { - .start = S3C2443_PA_HSMMC, - .end = S3C2443_PA_HSMMC + S3C2443_SZ_HSMMC - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3C2443_HSMMC, - .end = IRQ_S3C2443_HSMMC, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_hsmmc = { - .name = "s3c-sdhci", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_hsmmc_resource), - .resource = s3c_hsmmc_resource, - .dev = { - .dma_mask = &s3c_device_hsmmc_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - - - /* SPI (0) */ static struct resource s3c_spi0_resource[] = { diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 1baf941d1930..aee2aeb46c60 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -25,15 +25,13 @@ #include <linux/sysdev.h> #include <linux/slab.h> #include <linux/errno.h> -#include <linux/delay.h> #include <linux/io.h> #include <asm/system.h> #include <asm/irq.h> #include <mach/hardware.h> -#include <asm/dma.h> +#include <mach/dma.h> -#include <asm/mach/dma.h> #include <mach/map.h> #include <plat/dma.h> @@ -804,7 +802,7 @@ EXPORT_SYMBOL(s3c2410_dma_request); * allowed to go through. */ -int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) +int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); unsigned long flags; @@ -995,7 +993,7 @@ static int s3c2410_dma_started(struct s3c2410_dma_chan *chan) } int -s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) +s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); @@ -1043,7 +1041,7 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl); * dcon: base value of the DCONx register */ -int s3c2410_dma_config(dmach_t channel, +int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon) { @@ -1092,7 +1090,7 @@ int s3c2410_dma_config(dmach_t channel, EXPORT_SYMBOL(s3c2410_dma_config); -int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) +int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); @@ -1113,7 +1111,7 @@ EXPORT_SYMBOL(s3c2410_dma_setflags); * irq? */ -int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) +int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); @@ -1129,7 +1127,7 @@ int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) EXPORT_SYMBOL(s3c2410_dma_set_opfn); -int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) +int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); @@ -1219,7 +1217,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig); * returns the current transfer points for the dma source and destination */ -int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst) +int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst) { struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index 3caec6bad3eb..f95c6c9d9f1a 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c @@ -19,104 +19,12 @@ #include <linux/io.h> #include <linux/gpio.h> +#include <plat/gpio-core.h> #include <mach/hardware.h> #include <asm/irq.h> #include <mach/regs-gpio.h> -struct s3c24xx_gpio_chip { - struct gpio_chip chip; - void __iomem *base; -}; - -static inline struct s3c24xx_gpio_chip *to_s3c_chip(struct gpio_chip *gpc) -{ - return container_of(gpc, struct s3c24xx_gpio_chip, chip); -} - -/* these routines are exported for use by other parts of the platform - * and system support, but are not intended to be used directly by the - * drivers themsevles. - */ - -static int s3c24xx_gpiolib_input(struct gpio_chip *chip, unsigned offset) -{ - struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long con; - - local_irq_save(flags); - - con = __raw_readl(base + 0x00); - con &= ~(3 << (offset * 2)); - con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2); - - __raw_writel(con, base + 0x00); - - local_irq_restore(flags); - return 0; -} - -static int s3c24xx_gpiolib_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long dat; - unsigned long con; - - local_irq_save(flags); - - dat = __raw_readl(base + 0x04); - dat &= ~(1 << offset); - if (value) - dat |= 1 << offset; - __raw_writel(dat, base + 0x04); - - con = __raw_readl(base + 0x00); - con &= ~(3 << (offset * 2)); - con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2); - - __raw_writel(con, base + 0x00); - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); - return 0; -} - -static void s3c24xx_gpiolib_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); - void __iomem *base = ourchip->base; - unsigned long flags; - unsigned long dat; - - local_irq_save(flags); - - dat = __raw_readl(base + 0x04); - dat &= ~(1 << offset); - if (value) - dat |= 1 << offset; - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); -} - -static int s3c24xx_gpiolib_get(struct gpio_chip *chip, unsigned offset) -{ - struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); - unsigned long val; - - val = __raw_readl(ourchip->base + 0x04); - val >>= offset; - val &= 1; - - return val; -} - static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset) { return -EINVAL; @@ -125,7 +33,7 @@ static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset) static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip, unsigned offset, int value) { - struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); void __iomem *base = ourchip->base; unsigned long flags; unsigned long dat; @@ -151,7 +59,7 @@ static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip, return 0; } -static struct s3c24xx_gpio_chip gpios[] = { +struct s3c_gpio_chip s3c24xx_gpios[] = { [0] = { .base = S3C24XX_GPIO_BASE(S3C2410_GPA0), .chip = { @@ -161,8 +69,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .ngpio = 24, .direction_input = s3c24xx_gpiolib_banka_input, .direction_output = s3c24xx_gpiolib_banka_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [1] = { @@ -172,10 +78,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .owner = THIS_MODULE, .label = "GPIOB", .ngpio = 16, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [2] = { @@ -185,10 +87,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .owner = THIS_MODULE, .label = "GPIOC", .ngpio = 16, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [3] = { @@ -198,10 +96,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .owner = THIS_MODULE, .label = "GPIOD", .ngpio = 16, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [4] = { @@ -211,10 +105,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .label = "GPIOE", .owner = THIS_MODULE, .ngpio = 16, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [5] = { @@ -224,10 +114,6 @@ static struct s3c24xx_gpio_chip gpios[] = { .owner = THIS_MODULE, .label = "GPIOF", .ngpio = 8, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, [6] = { @@ -237,21 +123,17 @@ static struct s3c24xx_gpio_chip gpios[] = { .owner = THIS_MODULE, .label = "GPIOG", .ngpio = 10, - .direction_input = s3c24xx_gpiolib_input, - .direction_output = s3c24xx_gpiolib_output, - .set = s3c24xx_gpiolib_set, - .get = s3c24xx_gpiolib_get, }, }, }; static __init int s3c24xx_gpiolib_init(void) { - struct s3c24xx_gpio_chip *chip = gpios; + struct s3c_gpio_chip *chip = s3c24xx_gpios; int gpn; - for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++) - gpiochip_add(&chip->chip); + for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) + s3c_gpiolib_add(chip); return 0; } diff --git a/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h new file mode 100644 index 000000000000..a087de21bc20 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h @@ -0,0 +1,55 @@ +/* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C24xx - pwm clock and timer support + */ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @cfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg == S3C2410_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << (1 + tcfg1); +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 0; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div) - 1; +} + +#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h new file mode 100644 index 000000000000..fef8ea8b8e1e --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/map.h @@ -0,0 +1,99 @@ +/* linux/include/asm-arm/plat-s3c24xx/map.h + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX - Memory map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_PLAT_S3C24XX_MAP_H +#define __ASM_PLAT_S3C24XX_MAP_H + +/* interrupt controller is the first thing we put in, to make + * the assembly code for the irq detection easier + */ +#define S3C24XX_VA_IRQ S3C_VA_IRQ +#define S3C2410_PA_IRQ (0x4A000000) +#define S3C24XX_SZ_IRQ SZ_1M + +/* memory controller registers */ +#define S3C24XX_VA_MEMCTRL S3C_VA_MEM +#define S3C2410_PA_MEMCTRL (0x48000000) +#define S3C24XX_SZ_MEMCTRL SZ_1M + +/* UARTs */ +#define S3C24XX_VA_UART S3C_VA_UART +#define S3C2410_PA_UART (0x50000000) +#define S3C24XX_SZ_UART SZ_1M +#define S3C_UART_OFFSET (0x4000) + +/* Timers */ +#define S3C24XX_VA_TIMER S3C_VA_TIMER +#define S3C2410_PA_TIMER (0x51000000) +#define S3C24XX_SZ_TIMER SZ_1M + +/* Clock and Power management */ +#define S3C24XX_VA_CLKPWR S3C_VA_SYS +#define S3C24XX_SZ_CLKPWR SZ_1M + +/* USB Device port */ +#define S3C2410_PA_USBDEV (0x52000000) +#define S3C24XX_SZ_USBDEV SZ_1M + +/* Watchdog */ +#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG +#define S3C2410_PA_WATCHDOG (0x53000000) +#define S3C24XX_SZ_WATCHDOG SZ_1M + +/* Standard size definitions for peripheral blocks. */ + +#define S3C24XX_SZ_IIS SZ_1M +#define S3C24XX_SZ_ADC SZ_1M +#define S3C24XX_SZ_SPI SZ_1M +#define S3C24XX_SZ_SDI SZ_1M +#define S3C24XX_SZ_NAND SZ_1M +#define S3C24XX_SZ_USBHOST SZ_1M + +/* GPIO ports */ + +/* the calculation for the VA of this must ensure that + * it is the same distance apart from the UART in the + * phsyical address space, as the initial mapping for the IO + * is done as a 1:1 maping. This puts it (currently) at + * 0xFA800000, which is not in the way of any current mapping + * by the base system. +*/ + +#define S3C2410_PA_GPIO (0x56000000) +#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART) +#define S3C24XX_SZ_GPIO SZ_1M + + +/* ISA style IO, for each machine to sort out mappings for, if it + * implements it. We reserve two 16M regions for ISA. + */ + +#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000) +#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000) + +/* deal with the registers that move under the 2412/2413 */ + +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) +#ifndef __ASSEMBLY__ +extern void __iomem *s3c24xx_va_gpio2; +#endif +#ifdef CONFIG_CPU_S3C2412_ONLY +#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10) +#else +#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2 +#endif +#else +#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO +#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO +#endif + +#endif /* __ASM_PLAT_S3C24XX_MAP_H */ diff --git a/include/asm-arm/plat-s3c24xx/mci.h b/arch/arm/plat-s3c24xx/include/plat/mci.h index 2d0852ac3b27..2d0852ac3b27 100644 --- a/include/asm-arm/plat-s3c24xx/mci.h +++ b/arch/arm/plat-s3c24xx/include/plat/mci.h diff --git a/arch/arm/plat-s3c24xx/include/plat/pll.h b/arch/arm/plat-s3c24xx/include/plat/pll.h new file mode 100644 index 000000000000..7ea8bffa7a9c --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/pll.h @@ -0,0 +1,37 @@ +/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C24xx - common pll registers and code + */ + +#define S3C24XX_PLLCON_MDIVSHIFT 12 +#define S3C24XX_PLLCON_PDIVSHIFT 4 +#define S3C24XX_PLLCON_SDIVSHIFT 0 +#define S3C24XX_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1) +#define S3C24XX_PLLCON_PDIVMASK ((1<<5)-1) +#define S3C24XX_PLLCON_SDIVMASK 3 + +#include <asm/div64.h> + +static inline unsigned int +s3c24xx_get_pll(unsigned int pllval, unsigned int baseclk) +{ + unsigned int mdiv, pdiv, sdiv; + uint64_t fvco; + + mdiv = pllval >> S3C24XX_PLLCON_MDIVSHIFT; + pdiv = pllval >> S3C24XX_PLLCON_PDIVSHIFT; + sdiv = pllval >> S3C24XX_PLLCON_SDIVSHIFT; + + mdiv &= S3C24XX_PLLCON_MDIVMASK; + pdiv &= S3C24XX_PLLCON_PDIVMASK; + sdiv &= S3C24XX_PLLCON_SDIVMASK; + + fvco = (uint64_t)baseclk * (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} diff --git a/include/asm-arm/plat-s3c24xx/regs-spi.h b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h index 2b35479ee35c..2b35479ee35c 100644 --- a/include/asm-arm/plat-s3c24xx/regs-spi.h +++ b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h diff --git a/include/asm-arm/plat-s3c24xx/regs-udc.h b/arch/arm/plat-s3c24xx/include/plat/regs-udc.h index f0dd4a41b37b..f0dd4a41b37b 100644 --- a/include/asm-arm/plat-s3c24xx/regs-udc.h +++ b/arch/arm/plat-s3c24xx/include/plat/regs-udc.h diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h b/arch/arm/plat-s3c24xx/include/plat/s3c2400.h index 3a5a16821af8..b3feaea5c70b 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2400.h @@ -17,7 +17,7 @@ extern int s3c2400_init(void); -extern void s3c2400_map_io(struct map_desc *mach_desc, int size); +extern void s3c2400_map_io(void); extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2410.h b/arch/arm/plat-s3c24xx/include/plat/s3c2410.h index 3cd1ec677b3f..a9ac9e29759e 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2410.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2410.h @@ -15,7 +15,7 @@ extern int s3c2410_init(void); -extern void s3c2410_map_io(struct map_desc *mach_desc, int size); +extern void s3c2410_map_io(void); extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2412.h b/arch/arm/plat-s3c24xx/include/plat/s3c2412.h index 3ec97685e781..bb15d3b68be5 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2412.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2412.h @@ -14,7 +14,7 @@ extern int s3c2412_init(void); -extern void s3c2412_map_io(struct map_desc *mach_desc, int size); +extern void s3c2412_map_io(void); extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2443.h b/arch/arm/plat-s3c24xx/include/plat/s3c2443.h index 11d83b5c84e6..815b107ed890 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2443.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2443.h @@ -16,7 +16,7 @@ struct s3c2410_uartcfg; extern int s3c2443_init(void); -extern void s3c2443_map_io(struct map_desc *mach_desc, int size); +extern void s3c2443_map_io(void); extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/include/asm-arm/plat-s3c24xx/udc.h b/arch/arm/plat-s3c24xx/include/plat/udc.h index 546bb4008f49..546bb4008f49 100644 --- a/include/asm-arm/plat-s3c24xx/udc.h +++ b/arch/arm/plat-s3c24xx/include/plat/udc.h diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 963f7a4f26f2..0192ecdc1442 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -62,6 +62,7 @@ #include <asm/mach/irq.h> +#include <plat/regs-irqtype.h> #include <mach/regs-irq.h> #include <mach/regs-gpio.h> diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index 8efb57ad5019..34ef18e5b2a1 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -33,7 +33,6 @@ #include <linux/interrupt.h> #include <linux/crc32.h> #include <linux/ioport.h> -#include <linux/delay.h> #include <linux/serial_core.h> #include <linux/io.h> @@ -76,11 +75,13 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_BANKCON4), SAVE_ITEM(S3C2410_BANKCON5), +#ifndef CONFIG_CPU_FREQ SAVE_ITEM(S3C2410_CLKDIVN), SAVE_ITEM(S3C2410_MPLLCON), + SAVE_ITEM(S3C2410_REFRESH), +#endif SAVE_ITEM(S3C2410_UPLLCON), SAVE_ITEM(S3C2410_CLKSLOW), - SAVE_ITEM(S3C2410_REFRESH), }; static struct gpio_sleep { diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c index 4e07943c1e29..b61bdb793734 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c @@ -272,5 +272,6 @@ int __init s3c2410_baseclk_add(void) (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + s3c_pwmclk_init(); return 0; } diff --git a/arch/arm/plat-s3c24xx/s3c244x-clock.c b/arch/arm/plat-s3c24xx/s3c244x-clock.c index 7c09773ff9fc..dde41f171aff 100644 --- a/arch/arm/plat-s3c24xx/s3c244x-clock.c +++ b/arch/arm/plat-s3c24xx/s3c244x-clock.c @@ -31,7 +31,6 @@ #include <linux/sysdev.h> #include <linux/interrupt.h> #include <linux/ioport.h> -#include <linux/mutex.h> #include <linux/clk.h> #include <linux/io.h> @@ -102,13 +101,13 @@ static int s3c244x_clk_add(struct sys_device *sysdev) if (clk_get_rate(clock_upll) > (94 * MHZ)) { clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; - mutex_lock(&clocks_mutex); + spin_lock(&clocks_lock); clkdivn = __raw_readl(S3C2410_CLKDIVN); clkdivn |= S3C2440_CLKDIVN_UCLK; __raw_writel(clkdivn, S3C2410_CLKDIVN); - mutex_unlock(&clocks_mutex); + spin_unlock(&clocks_lock); } return 0; diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c index c0344fac4a94..c1de6bb0101b 100644 --- a/arch/arm/plat-s3c24xx/s3c244x.c +++ b/arch/arm/plat-s3c24xx/s3c244x.c @@ -29,6 +29,8 @@ #include <mach/hardware.h> #include <asm/irq.h> +#include <plat/cpu-freq.h> + #include <mach/regs-clock.h> #include <plat/regs-serial.h> #include <mach/regs-gpio.h> @@ -42,6 +44,7 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <plat/pm.h> +#include <plat/pll.h> static struct map_desc s3c244x_iodesc[] __initdata = { IODESC_ENT(CLKPWR), @@ -56,32 +59,34 @@ void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no) s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); } -void __init s3c244x_map_io(struct map_desc *mach_desc, int size) +void __init s3c244x_map_io(void) { /* register our io-tables */ iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc)); - iotable_init(mach_desc, size); /* rename any peripherals used differing from the s3c2410 */ s3c_device_sdi.name = "s3c2440-sdi"; - s3c_device_i2c.name = "s3c2440-i2c"; + s3c_device_i2c0.name = "s3c2440-i2c"; s3c_device_nand.name = "s3c2440-nand"; s3c_device_usbgadget.name = "s3c2440-usbgadget"; } -void __init s3c244x_init_clocks(int xtal) +void __init_or_cpufreq s3c244x_setup_clocks(void) { + struct clk *xtal_clk; unsigned long clkdiv; unsigned long camdiv; + unsigned long xtal; unsigned long hclk, fclk, pclk; int hdiv = 1; - /* now we've got our machine bits initialised, work out what - * clocks we've got */ + xtal_clk = clk_get(NULL, "xtal"); + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); - fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; + fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; clkdiv = __raw_readl(S3C2410_CLKDIVN); camdiv = __raw_readl(S3C2440_CAMDIVN); @@ -107,18 +112,24 @@ void __init s3c244x_init_clocks(int xtal) } hclk = fclk / hdiv; - pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); + pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1); /* print brief summary of clocks, etc */ printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + s3c24xx_setup_clocks(fclk, hclk, pclk); +} + +void __init s3c244x_init_clocks(int xtal) +{ /* initialise the clocks here, to allow other things like the * console to use them, and to add new ones after the initialisation */ - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c24xx_register_baseclocks(xtal); + s3c244x_setup_clocks(); s3c2410_baseclk_add(); } diff --git a/arch/arm/plat-s3c24xx/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h index f8ed17676a35..6aab5eaae2b4 100644 --- a/arch/arm/plat-s3c24xx/s3c244x.h +++ b/arch/arm/plat-s3c24xx/s3c244x.h @@ -12,7 +12,7 @@ #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) -extern void s3c244x_map_io(struct map_desc *mach_desc, int size); +extern void s3c244x_map_io(void); extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c24xx/setup-i2c.c b/arch/arm/plat-s3c24xx/setup-i2c.c new file mode 100644 index 000000000000..d62b7e7fb355 --- /dev/null +++ b/arch/arm/plat-s3c24xx/setup-i2c.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/plat-s3c24xx/setup-i2c.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX Base setup for i2c device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> + +struct platform_device; + +#include <plat/iic.h> +#include <mach/hardware.h> +#include <mach/regs-gpio.h> + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA); + s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL); +} diff --git a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c new file mode 100644 index 000000000000..8b403cbb53d2 --- /dev/null +++ b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c @@ -0,0 +1,37 @@ +/* linux/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX SPI - gpio configuration for bus 0 on gpe11,12,13 + * + * 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. +*/ + +#include <linux/kernel.h> + +#include <mach/hardware.h> + +#include <mach/spi.h> +#include <mach/regs-gpio.h> + +void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, + int enable) +{ + if (enable) { + s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_SPICLK0); + s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_SPIMOSI0); + s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_SPIMISO0); + s3c2410_gpio_pullup(S3C2410_GPE11, 0); + s3c2410_gpio_pullup(S3C2410_GPE13, 0); + } else { + s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPIO_INPUT); + s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPIO_INPUT); + s3c2410_gpio_pullup(S3C2410_GPE11, 1); + s3c2410_gpio_pullup(S3C2410_GPE12, 1); + s3c2410_gpio_pullup(S3C2410_GPE13, 1); + } +} diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c new file mode 100644 index 000000000000..8fccd4e549f0 --- /dev/null +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c @@ -0,0 +1,37 @@ +/* linux/arch/arm/plat-s3c24xx/spi-bus0-gpg5_6_7.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX SPI - gpio configuration for bus 1 on gpg5,6,7 + * + * 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. +*/ + +#include <linux/kernel.h> + +#include <mach/hardware.h> + +#include <mach/spi.h> +#include <mach/regs-gpio.h> + +void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi, + int enable) +{ + if (enable) { + s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_SPICLK1); + s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_SPIMOSI1); + s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_SPIMISO1); + s3c2410_gpio_pullup(S3C2410_GPG5, 0); + s3c2410_gpio_pullup(S3C2410_GPG6, 0); + } else { + s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPIO_INPUT); + s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPIO_INPUT); + s3c2410_gpio_pullup(S3C2410_GPG5, 1); + s3c2410_gpio_pullup(S3C2410_GPG6, 1); + s3c2410_gpio_pullup(S3C2410_GPG7, 1); + } +} diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig new file mode 100644 index 000000000000..54375a00a7d2 --- /dev/null +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -0,0 +1,62 @@ +# arch/arm/plat-s3c64xx/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# Ben Dooks <ben@simtec.co.uk> +# +# Licensed under GPLv2 + +config PLAT_S3C64XX + bool + depends on ARCH_S3C64XX + default y + select CPU_V6 + select PLAT_S3C + select ARM_VIC + select NO_IOPORT + select ARCH_REQUIRE_GPIOLIB + select S3C_GPIO_TRACK + select S3C_GPIO_PULL_UPDOWN + select S3C_GPIO_CFG_S3C24XX + select S3C_GPIO_CFG_S3C64XX + help + Base platform code for any Samsung S3C64XX device + +if PLAT_S3C64XX + +# Configuration options shared by all S3C64XX implementations + +config CPU_S3C6400_INIT + bool + help + Common initialisation code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + +config CPU_S3C6400_CLOCK + bool + help + Common clock support code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + +# platform specific device setup + +config S3C64XX_SETUP_I2C0 + bool + default y + help + Common setup code for i2c bus 0. + + Note, currently since i2c0 is always compiled, this setup helper + is always compiled with it. + +config S3C64XX_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + +config S3C64XX_SETUP_FB_24BPP + bool + help + Common setup code for S3C64XX with an 24bpp RGB display helper. + +endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile new file mode 100644 index 000000000000..2e6d79bf8f33 --- /dev/null +++ b/arch/arm/plat-s3c64xx/Makefile @@ -0,0 +1,31 @@ +# arch/arm/plat-s3c64xx/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := dummy.o +obj- := + +# Core files + +obj-y += dev-uart.o +obj-y += cpu.o +obj-y += irq.o +obj-y += irq-eint.o +obj-y += clock.o +obj-y += gpiolib.o + +# CPU support + +obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o +obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o + +# Device setup + +obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o +obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o +obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c new file mode 100644 index 000000000000..136c982c68e1 --- /dev/null +++ b/arch/arm/plat-s3c64xx/clock.c @@ -0,0 +1,281 @@ +/* linux/arch/arm/plat-s3c64xx/clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX Base clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/regs-sys.h> +#include <plat/regs-clock.h> +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +struct clk clk_27m = { + .name = "clk_27m", + .id = -1, + .rate = 27000000, +}; + +static int clk_48m_ctrl(struct clk *clk, int enable) +{ + unsigned long flags; + u32 val; + + /* can't rely on clock lock, this register has other usages */ + local_irq_save(flags); + + val = __raw_readl(S3C64XX_OTHERS); + if (enable) + val |= S3C64XX_OTHERS_USBMASK; + else + val &= ~S3C64XX_OTHERS_USBMASK; + + __raw_writel(val, S3C64XX_OTHERS); + local_irq_restore(flags); + + return 0; +} + +struct clk clk_48m = { + .name = "clk_48m", + .id = -1, + .rate = 48000000, + .enable = clk_48m_ctrl, +}; + +static int inline s3c64xx_gate(void __iomem *reg, + struct clk *clk, + int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + u32 con; + + con = __raw_readl(reg); + + if (enable) + con |= ctrlbit; + else + con &= ~ctrlbit; + + __raw_writel(con, reg); + return 0; +} + +static int s3c64xx_pclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_PCLK_GATE, clk, enable); +} + +static int s3c64xx_hclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_HCLK_GATE, clk, enable); +} + +int s3c64xx_sclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_SCLK_GATE, clk, enable); +} + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_TSADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIC, + }, { + .name = "iis", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS0, + }, { + .name = "iis", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS1, + }, { + .name = "spi", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI0, + }, { + .name = "spi", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI1, + }, { + .name = "48m", + .id = 0, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC0_48, + }, { + .name = "48m", + .id = 1, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC1_48, + }, { + .name = "48m", + .id = 2, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC2_48, + }, +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_LCD, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC0, + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC1, + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC2, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_PWM, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART2, + }, { + .name = "uart", + .id = 3, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART3, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_WDT, + }, { + .name = "ac97", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_AC97, + } +}; + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_epll, + &clk_27m, + &clk_48m, +}; + +void s3c64xx_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c new file mode 100644 index 000000000000..fbde183a4560 --- /dev/null +++ b/arch/arm/plat-s3c64xx/cpu.c @@ -0,0 +1,114 @@ +/* linux/arch/arm/plat-s3c64xx/cpu.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX CPU Support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* table of supported CPUs */ + +static const char name_s3c6400[] = "S3C6400"; +static const char name_s3c6410[] = "S3C6410"; + +static struct cpu_table cpu_ids[] __initdata = { + { + .idcode = 0x36400000, + .idmask = 0xfffff000, + .map_io = s3c6400_map_io, + .init_clocks = s3c6400_init_clocks, + .init_uarts = s3c6400_init_uarts, + .init = s3c6400_init, + .name = name_s3c6400, + }, { + .idcode = 0x36410100, + .idmask = 0xffffff00, + .map_io = s3c6410_map_io, + .init_clocks = s3c6410_init_clocks, + .init_uarts = s3c6410_init_uarts, + .init = s3c6410_init, + .name = name_s3c6410, + }, +}; + +/* minimal IO mapping */ + +/* see notes on uart map in arch/arm/mach-s3c6400/include/mach/debug-macro.S */ +#define UART_OFFS (S3C_PA_UART & 0xfffff) + +static struct map_desc s3c_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_SYS, + .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)(S3C_VA_UART + UART_OFFS), + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_VIC0, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_VIC1, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_TIMER, + .pfn = __phys_to_pfn(S3C_PA_TIMER), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C64XX_VA_GPIO, + .pfn = __phys_to_pfn(S3C64XX_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +/* read cpu identification code */ + +void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) +{ + unsigned long idcode; + + /* initialise the io descriptors we need for initialisation */ + iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); + iotable_init(mach_desc, size); + + idcode = __raw_readl(S3C_VA_SYS + 0x118); + s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); +} diff --git a/arch/arm/plat-s3c64xx/dev-uart.c b/arch/arm/plat-s3c64xx/dev-uart.c new file mode 100644 index 000000000000..62c11a6fc7ba --- /dev/null +++ b/arch/arm/plat-s3c64xx/dev-uart.c @@ -0,0 +1,176 @@ +/* linux/arch/arm/plat-s3c64xx/dev-uart.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX UART resource and device definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/devs.h> + +/* Serial port registrations */ + +/* 64xx uarts are closer together */ + +static struct resource s3c64xx_uart0_resource[] = { + [0] = { + .start = S3C_PA_UART0, + .end = S3C_PA_UART0 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX0, + .end = IRQ_S3CUART_RX0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX0, + .end = IRQ_S3CUART_TX0, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR0, + .end = IRQ_S3CUART_ERR0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s3c64xx_uart1_resource[] = { + [0] = { + .start = S3C_PA_UART1, + .end = S3C_PA_UART1 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX1, + .end = IRQ_S3CUART_RX1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX1, + .end = IRQ_S3CUART_TX1, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR1, + .end = IRQ_S3CUART_ERR1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c6xx_uart2_resource[] = { + [0] = { + .start = S3C_PA_UART2, + .end = S3C_PA_UART2 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX2, + .end = IRQ_S3CUART_RX2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX2, + .end = IRQ_S3CUART_TX2, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR2, + .end = IRQ_S3CUART_ERR2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c64xx_uart3_resource[] = { + [0] = { + .start = S3C_PA_UART3, + .end = S3C_PA_UART3 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX3, + .end = IRQ_S3CUART_RX3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX3, + .end = IRQ_S3CUART_TX3, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR3, + .end = IRQ_S3CUART_ERR3, + .flags = IORESOURCE_IRQ, + }, +}; + + +struct s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata = { + [0] = { + .resources = s3c64xx_uart0_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart0_resource), + }, + [1] = { + .resources = s3c64xx_uart1_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart1_resource), + }, + [2] = { + .resources = s3c6xx_uart2_resource, + .nr_resources = ARRAY_SIZE(s3c6xx_uart2_resource), + }, + [3] = { + .resources = s3c64xx_uart3_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart3_resource), + }, +}; + +/* uart devices */ + +static struct platform_device s3c24xx_uart_device0 = { + .id = 0, +}; + +static struct platform_device s3c24xx_uart_device1 = { + .id = 1, +}; + +static struct platform_device s3c24xx_uart_device2 = { + .id = 2, +}; + +static struct platform_device s3c24xx_uart_device3 = { + .id = 3, +}; + +struct platform_device *s3c24xx_uart_src[4] = { + &s3c24xx_uart_device0, + &s3c24xx_uart_device1, + &s3c24xx_uart_device2, + &s3c24xx_uart_device3, +}; + +struct platform_device *s3c24xx_uart_devs[4] = { +}; + diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c new file mode 100644 index 000000000000..cc62941d7b5c --- /dev/null +++ b/arch/arm/plat-s3c64xx/gpiolib.c @@ -0,0 +1,420 @@ +/* arch/arm/plat-s3c64xx/gpiolib.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIOlib support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <mach/map.h> +#include <mach/gpio.h> +#include <mach/gpio-core.h> + +#include <plat/gpio-cfg.h> +#include <plat/gpio-cfg-helpers.h> +#include <plat/regs-gpio.h> + +/* GPIO bank summary: + * + * Bank GPIOs Style SlpCon ExtInt Group + * A 8 4Bit Yes 1 + * B 7 4Bit Yes 1 + * C 8 4Bit Yes 2 + * D 5 4Bit Yes 3 + * E 5 4Bit Yes None + * F 16 2Bit Yes 4 [1] + * G 7 4Bit Yes 5 + * H 10 4Bit[2] Yes 6 + * I 16 2Bit Yes None + * J 12 2Bit Yes None + * K 16 4Bit[2] No None + * L 15 4Bit[2] No None + * M 6 4Bit No IRQ_EINT + * N 16 2Bit No IRQ_EINT + * O 16 2Bit Yes 7 + * P 15 2Bit Yes 8 + * Q 9 2Bit Yes 9 + * + * [1] BANKF pins 14,15 do not form part of the external interrupt sources + * [2] BANK has two control registers, GPxCON0 and GPxCON1 + */ + +#define OFF_GPCON (0x00) +#define OFF_GPDAT (0x04) + +#define con_4bit_shift(__off) ((__off) * 4) + +#if 1 +#define gpio_dbg(x...) do { } while(0) +#else +#define gpio_dbg(x...) printk(KERN_DEBUG ## x) +#endif + +/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where + * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the + * following example: + * + * base + 0x00: Control register, 4 bits per gpio + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x04: Data register, 1 bit per gpio + * bit n: data bit n + * + * Note, since the data register is one bit per gpio and is at base + 0x4 + * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of + * the output. +*/ + +static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long con; + + con = __raw_readl(base + OFF_GPCON); + con &= ~(0xf << con_4bit_shift(offset)); + __raw_writel(con, base + OFF_GPCON); + + gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); + + return 0; +} + +static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long con; + unsigned long dat; + + con = __raw_readl(base + OFF_GPCON); + con &= ~(0xf << con_4bit_shift(offset)); + con |= 0x1 << con_4bit_shift(offset); + + dat = __raw_readl(base + OFF_GPDAT); + if (value) + dat |= 1 << offset; + else + dat &= ~(1 << offset); + + __raw_writel(dat, base + OFF_GPDAT); + __raw_writel(con, base + OFF_GPCON); + __raw_writel(dat, base + OFF_GPDAT); + + gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); + + return 0; +} + +/* The next set of routines are for the case where the GPIO configuration + * registers are 4 bits per GPIO but there is more than one register (the + * bank has more than 8 GPIOs. + * + * This case is the similar to the 4 bit case, but the registers are as + * follows: + * + * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs) + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs) + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x08: Data register, 1 bit per gpio + * bit n: data bit n + * + * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we + * store the 'base + 0x4' address so that these routines see the data + * register at ourchip->base + 0x04. +*/ + +static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + void __iomem *regcon = base; + unsigned long con; + + if (offset > 7) + offset -= 8; + else + regcon -= 4; + + con = __raw_readl(regcon); + con &= ~(0xf << con_4bit_shift(offset)); + __raw_writel(con, regcon); + + gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con); + + return 0; + +} + +static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + void __iomem *regcon = base; + unsigned long con; + unsigned long dat; + + if (offset > 7) + offset -= 8; + else + regcon -= 4; + + con = __raw_readl(regcon); + con &= ~(0xf << con_4bit_shift(offset)); + con |= 0x1 << con_4bit_shift(offset); + + dat = __raw_readl(base + OFF_GPDAT); + if (value) + dat |= 1 << offset; + else + dat &= ~(1 << offset); + + __raw_writel(dat, base + OFF_GPDAT); + __raw_writel(con, regcon); + __raw_writel(dat, base + OFF_GPDAT); + + gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); + + return 0; +} + +static struct s3c_gpio_cfg gpio_4bit_cfg_noint = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = { + .cfg_eint = 7, + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = { + .cfg_eint = 3, + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_chip gpio_4bit[] = { + { + .base = S3C64XX_GPA_BASE, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPA(0), + .ngpio = S3C64XX_GPIO_A_NR, + .label = "GPA", + }, + }, { + .base = S3C64XX_GPB_BASE, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPB(0), + .ngpio = S3C64XX_GPIO_B_NR, + .label = "GPB", + }, + }, { + .base = S3C64XX_GPC_BASE, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPC(0), + .ngpio = S3C64XX_GPIO_C_NR, + .label = "GPC", + }, + }, { + .base = S3C64XX_GPD_BASE, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPD(0), + .ngpio = S3C64XX_GPIO_D_NR, + .label = "GPD", + }, + }, { + .base = S3C64XX_GPE_BASE, + .config = &gpio_4bit_cfg_noint, + .chip = { + .base = S3C64XX_GPE(0), + .ngpio = S3C64XX_GPIO_E_NR, + .label = "GPE", + }, + }, { + .base = S3C64XX_GPG_BASE, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPG(0), + .ngpio = S3C64XX_GPIO_G_NR, + .label = "GPG", + }, + }, { + .base = S3C64XX_GPM_BASE, + .config = &gpio_4bit_cfg_eint0011, + .chip = { + .base = S3C64XX_GPM(0), + .ngpio = S3C64XX_GPIO_M_NR, + .label = "GPM", + }, + }, +}; + +static struct s3c_gpio_chip gpio_4bit2[] = { + { + .base = S3C64XX_GPH_BASE + 0x4, + .config = &gpio_4bit_cfg_eint0111, + .chip = { + .base = S3C64XX_GPH(0), + .ngpio = S3C64XX_GPIO_H_NR, + .label = "GPH", + }, + }, { + .base = S3C64XX_GPK_BASE + 0x4, + .config = &gpio_4bit_cfg_noint, + .chip = { + .base = S3C64XX_GPK(0), + .ngpio = S3C64XX_GPIO_K_NR, + .label = "GPK", + }, + }, { + .base = S3C64XX_GPL_BASE + 0x4, + .config = &gpio_4bit_cfg_eint0011, + .chip = { + .base = S3C64XX_GPL(0), + .ngpio = S3C64XX_GPIO_L_NR, + .label = "GPL", + }, + }, +}; + +static struct s3c_gpio_cfg gpio_2bit_cfg_noint = { + .set_config = s3c_gpio_setcfg_s3c24xx, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = { + .cfg_eint = 2, + .set_config = s3c_gpio_setcfg_s3c24xx, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = { + .cfg_eint = 3, + .set_config = s3c_gpio_setcfg_s3c24xx, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_chip gpio_2bit[] = { + { + .base = S3C64XX_GPF_BASE, + .config = &gpio_2bit_cfg_eint11, + .chip = { + .base = S3C64XX_GPF(0), + .ngpio = S3C64XX_GPIO_F_NR, + .label = "GPF", + }, + }, { + .base = S3C64XX_GPI_BASE, + .config = &gpio_2bit_cfg_noint, + .chip = { + .base = S3C64XX_GPI(0), + .ngpio = S3C64XX_GPIO_I_NR, + .label = "GPI", + }, + }, { + .base = S3C64XX_GPJ_BASE, + .config = &gpio_2bit_cfg_noint, + .chip = { + .base = S3C64XX_GPJ(0), + .ngpio = S3C64XX_GPIO_J_NR, + .label = "GPJ", + }, + }, { + .base = S3C64XX_GPN_BASE, + .config = &gpio_2bit_cfg_eint10, + .chip = { + .base = S3C64XX_GPN(0), + .ngpio = S3C64XX_GPIO_N_NR, + .label = "GPN", + }, + }, { + .base = S3C64XX_GPO_BASE, + .config = &gpio_2bit_cfg_eint11, + .chip = { + .base = S3C64XX_GPO(0), + .ngpio = S3C64XX_GPIO_O_NR, + .label = "GPO", + }, + }, { + .base = S3C64XX_GPP_BASE, + .config = &gpio_2bit_cfg_eint11, + .chip = { + .base = S3C64XX_GPP(0), + .ngpio = S3C64XX_GPIO_P_NR, + .label = "GPP", + }, + }, { + .base = S3C64XX_GPQ_BASE, + .config = &gpio_2bit_cfg_eint11, + .chip = { + .base = S3C64XX_GPQ(0), + .ngpio = S3C64XX_GPIO_Q_NR, + .label = "GPQ", + }, + }, +}; + +static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip) +{ + chip->chip.direction_input = s3c64xx_gpiolib_4bit_input; + chip->chip.direction_output = s3c64xx_gpiolib_4bit_output; +} + +static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip) +{ + chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input; + chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output; +} + +static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips, + int nr_chips, + void (*fn)(struct s3c_gpio_chip *)) +{ + for (; nr_chips > 0; nr_chips--, chips++) { + if (fn) + (fn)(chips); + s3c_gpiolib_add(chips); + } +} + +static __init int s3c64xx_gpiolib_init(void) +{ + s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit), + s3c64xx_gpiolib_add_4bit); + + s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2), + s3c64xx_gpiolib_add_4bit2); + + s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL); + + return 0; +} + +arch_initcall(s3c64xx_gpiolib_init); diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h new file mode 100644 index 000000000000..9aa0e427d113 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h @@ -0,0 +1,48 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank A register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPACON (S3C64XX_GPA_BASE + 0x00) +#define S3C64XX_GPADAT (S3C64XX_GPA_BASE + 0x04) +#define S3C64XX_GPAPUD (S3C64XX_GPA_BASE + 0x08) +#define S3C64XX_GPACONSLP (S3C64XX_GPA_BASE + 0x0c) +#define S3C64XX_GPAPUDSLP (S3C64XX_GPA_BASE + 0x10) + +#define S3C64XX_GPA_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPA_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPA_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPA0_UART_RXD0 (0x02 << 0) +#define S3C64XX_GPA0_EINT_G1_0 (0x07 << 0) + +#define S3C64XX_GPA1_UART_TXD0 (0x02 << 4) +#define S3C64XX_GPA1_EINT_G1_1 (0x07 << 4) + +#define S3C64XX_GPA2_UART_nCTS0 (0x02 << 8) +#define S3C64XX_GPA2_EINT_G1_2 (0x07 << 8) + +#define S3C64XX_GPA3_UART_nRTS0 (0x02 << 12) +#define S3C64XX_GPA3_EINT_G1_3 (0x07 << 12) + +#define S3C64XX_GPA4_UART_RXD1 (0x02 << 16) +#define S3C64XX_GPA4_EINT_G1_4 (0x07 << 16) + +#define S3C64XX_GPA5_UART_TXD1 (0x02 << 20) +#define S3C64XX_GPA5_EINT_G1_5 (0x07 << 20) + +#define S3C64XX_GPA6_UART_nCTS1 (0x02 << 24) +#define S3C64XX_GPA6_EINT_G1_6 (0x07 << 24) + +#define S3C64XX_GPA7_UART_nRTS1 (0x02 << 28) +#define S3C64XX_GPA7_EINT_G1_7 (0x07 << 28) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h new file mode 100644 index 000000000000..3933adb4d50a --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h @@ -0,0 +1,60 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank B register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPBCON (S3C64XX_GPB_BASE + 0x00) +#define S3C64XX_GPBDAT (S3C64XX_GPB_BASE + 0x04) +#define S3C64XX_GPBPUD (S3C64XX_GPB_BASE + 0x08) +#define S3C64XX_GPBCONSLP (S3C64XX_GPB_BASE + 0x0c) +#define S3C64XX_GPBPUDSLP (S3C64XX_GPB_BASE + 0x10) + +#define S3C64XX_GPB_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPB_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPB_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPB0_UART_RXD2 (0x02 << 0) +#define S3C64XX_GPB0_EXTDMA_REQ (0x03 << 0) +#define S3C64XX_GPB0_IrDA_RXD (0x04 << 0) +#define S3C64XX_GPB0_ADDR_CF0 (0x05 << 0) +#define S3C64XX_GPB0_EINT_G1_8 (0x07 << 0) + +#define S3C64XX_GPB1_UART_TXD2 (0x02 << 4) +#define S3C64XX_GPB1_EXTDMA_ACK (0x03 << 4) +#define S3C64XX_GPB1_IrDA_TXD (0x04 << 4) +#define S3C64XX_GPB1_ADDR_CF1 (0x05 << 4) +#define S3C64XX_GPB1_EINT_G1_9 (0x07 << 4) + +#define S3C64XX_GPB2_UART_RXD3 (0x02 << 8) +#define S3C64XX_GPB2_IrDA_RXD (0x03 << 8) +#define S3C64XX_GPB2_EXTDMA_REQ (0x04 << 8) +#define S3C64XX_GPB2_ADDR_CF2 (0x05 << 8) +#define S3C64XX_GPB2_I2C_SCL1 (0x06 << 8) +#define S3C64XX_GPB2_EINT_G1_10 (0x07 << 8) + +#define S3C64XX_GPB3_UART_TXD3 (0x02 << 12) +#define S3C64XX_GPB3_IrDA_TXD (0x03 << 12) +#define S3C64XX_GPB3_EXTDMA_ACK (0x04 << 12) +#define S3C64XX_GPB3_I2C_SDA1 (0x06 << 12) +#define S3C64XX_GPB3_EINT_G1_11 (0x07 << 12) + +#define S3C64XX_GPB4_IrDA_SDBW (0x02 << 16) +#define S3C64XX_GPB4_CAM_FIELD (0x03 << 16) +#define S3C64XX_GPB4_CF_DATA_DIR (0x04 << 16) +#define S3C64XX_GPB4_EINT_G1_12 (0x07 << 16) + +#define S3C64XX_GPB5_I2C_SCL0 (0x02 << 20) +#define S3C64XX_GPB5_EINT_G1_13 (0x07 << 20) + +#define S3C64XX_GPB6_I2C_SDA0 (0x02 << 24) +#define S3C64XX_GPB6_EINT_G1_14 (0x07 << 24) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h new file mode 100644 index 000000000000..c47daf7e2723 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h @@ -0,0 +1,53 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank C register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPCCON (S3C64XX_GPC_BASE + 0x00) +#define S3C64XX_GPCDAT (S3C64XX_GPC_BASE + 0x04) +#define S3C64XX_GPCPUD (S3C64XX_GPC_BASE + 0x08) +#define S3C64XX_GPCCONSLP (S3C64XX_GPC_BASE + 0x0c) +#define S3C64XX_GPCPUDSLP (S3C64XX_GPC_BASE + 0x10) + +#define S3C64XX_GPC_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPC_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPC_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPC0_SPI_MISO0 (0x02 << 0) +#define S3C64XX_GPC0_EINT_G2_0 (0x07 << 0) + +#define S3C64XX_GPC1_SPI_CLKO (0x02 << 4) +#define S3C64XX_GPC1_EINT_G2_1 (0x07 << 4) + +#define S3C64XX_GPC2_SPI_MOSIO (0x02 << 8) +#define S3C64XX_GPC2_EINT_G2_2 (0x07 << 8) + +#define S3C64XX_GPC3_SPI_nCSO (0x02 << 12) +#define S3C64XX_GPC3_EINT_G2_3 (0x07 << 12) + +#define S3C64XX_GPC4_SPI_MISO1 (0x02 << 16) +#define S3C64XX_GPC4_MMC2_CMD (0x03 << 16) +#define S3C64XX_GPC4_I2S0_V40_DO (0x05 << 16) +#define S3C64XX_GPC4_EINT_G2_4 (0x07 << 16) + +#define S3C64XX_GPC5_SPI_CLK1 (0x02 << 20) +#define S3C64XX_GPC5_MMC2_CLK (0x03 << 20) +#define S3C64XX_GPC5_I2S1_V40_DO (0x05 << 20) +#define S3C64XX_GPC5_EINT_G2_5 (0x07 << 20) + +#define S3C64XX_GPC6_SPI_MOSI1 (0x02 << 24) +#define S3C64XX_GPC6_EINT_G2_6 (0x07 << 24) + +#define S3C64XX_GPC7_SPI_nCS1 (0x02 << 28) +#define S3C64XX_GPC7_I2S2_V40_DO (0x05 << 28) +#define S3C64XX_GPC7_EINT_G2_7 (0x07 << 28) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h new file mode 100644 index 000000000000..6fe4a49c26f0 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h @@ -0,0 +1,49 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank D register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPDCON (S3C64XX_GPD_BASE + 0x00) +#define S3C64XX_GPDDAT (S3C64XX_GPD_BASE + 0x04) +#define S3C64XX_GPDPUD (S3C64XX_GPD_BASE + 0x08) +#define S3C64XX_GPDCONSLP (S3C64XX_GPD_BASE + 0x0c) +#define S3C64XX_GPDPUDSLP (S3C64XX_GPD_BASE + 0x10) + +#define S3C64XX_GPD_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPD_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPD_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPD0_PCM0_SCLK (0x02 << 0) +#define S3C64XX_GPD0_I2S0_CLK (0x03 << 0) +#define S3C64XX_GPD0_AC97_BITCLK (0x04 << 0) +#define S3C64XX_GPD0_EINT_G3_0 (0x07 << 0) + +#define S3C64XX_GPD1_PCM0_EXTCLK (0x02 << 4) +#define S3C64XX_GPD1_I2S0_CDCLK (0x03 << 4) +#define S3C64XX_GPD1_AC97_nRESET (0x04 << 4) +#define S3C64XX_GPD1_EINT_G3_1 (0x07 << 4) + +#define S3C64XX_GPD2_PCM0_FSYNC (0x02 << 8) +#define S3C64XX_GPD2_I2S0_LRCLK (0x03 << 8) +#define S3C64XX_GPD2_AC97_SYNC (0x04 << 8) +#define S3C64XX_GPD2_EINT_G3_2 (0x07 << 8) + +#define S3C64XX_GPD3_PCM0_SIN (0x02 << 12) +#define S3C64XX_GPD3_I2S0_DI (0x03 << 12) +#define S3C64XX_GPD3_AC97_SDI (0x04 << 12) +#define S3C64XX_GPD3_EINT_G3_3 (0x07 << 12) + +#define S3C64XX_GPD4_PCM0_SOUT (0x02 << 16) +#define S3C64XX_GPD4_I2S0_D0 (0x03 << 16) +#define S3C64XX_GPD4_AC97_SDO (0x04 << 16) +#define S3C64XX_GPD4_EINT_G3_4 (0x07 << 16) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h new file mode 100644 index 000000000000..7fcf3d8e0a48 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h @@ -0,0 +1,44 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank E register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPECON (S3C64XX_GPE_BASE + 0x00) +#define S3C64XX_GPEDAT (S3C64XX_GPE_BASE + 0x04) +#define S3C64XX_GPEPUD (S3C64XX_GPE_BASE + 0x08) +#define S3C64XX_GPECONSLP (S3C64XX_GPE_BASE + 0x0c) +#define S3C64XX_GPEPUDSLP (S3C64XX_GPE_BASE + 0x10) + +#define S3C64XX_GPE_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPE_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPE_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPE0_PCM1_SCLK (0x02 << 0) +#define S3C64XX_GPE0_I2S1_CLK (0x03 << 0) +#define S3C64XX_GPE0_AC97_BITCLK (0x04 << 0) + +#define S3C64XX_GPE1_PCM1_EXTCLK (0x02 << 4) +#define S3C64XX_GPE1_I2S1_CDCLK (0x03 << 4) +#define S3C64XX_GPE1_AC97_nRESET (0x04 << 4) + +#define S3C64XX_GPE2_PCM1_FSYNC (0x02 << 8) +#define S3C64XX_GPE2_I2S1_LRCLK (0x03 << 8) +#define S3C64XX_GPE2_AC97_SYNC (0x04 << 8) + +#define S3C64XX_GPE3_PCM1_SIN (0x02 << 12) +#define S3C64XX_GPE3_I2S1_DI (0x03 << 12) +#define S3C64XX_GPE3_AC97_SDI (0x04 << 12) + +#define S3C64XX_GPE4_PCM1_SOUT (0x02 << 16) +#define S3C64XX_GPE4_I2S1_D0 (0x03 << 16) +#define S3C64XX_GPE4_AC97_SDO (0x04 << 16) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h new file mode 100644 index 000000000000..f3faff974a18 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h @@ -0,0 +1,71 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank F register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPFCON (S3C64XX_GPF_BASE + 0x00) +#define S3C64XX_GPFDAT (S3C64XX_GPF_BASE + 0x04) +#define S3C64XX_GPFPUD (S3C64XX_GPF_BASE + 0x08) +#define S3C64XX_GPFCONSLP (S3C64XX_GPF_BASE + 0x0c) +#define S3C64XX_GPFPUDSLP (S3C64XX_GPF_BASE + 0x10) + +#define S3C64XX_GPF_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPF_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPF_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPF0_CAMIF_CLK (0x02 << 0) +#define S3C64XX_GPF0_EINT_G4_0 (0x03 << 0) + +#define S3C64XX_GPF1_CAMIF_HREF (0x02 << 2) +#define S3C64XX_GPF1_EINT_G4_1 (0x03 << 2) + +#define S3C64XX_GPF2_CAMIF_PCLK (0x02 << 4) +#define S3C64XX_GPF2_EINT_G4_2 (0x03 << 4) + +#define S3C64XX_GPF3_CAMIF_nRST (0x02 << 6) +#define S3C64XX_GPF3_EINT_G4_3 (0x03 << 6) + +#define S3C64XX_GPF4_CAMIF_VSYNC (0x02 << 8) +#define S3C64XX_GPF4_EINT_G4_4 (0x03 << 8) + +#define S3C64XX_GPF5_CAMIF_YDATA0 (0x02 << 10) +#define S3C64XX_GPF5_EINT_G4_5 (0x03 << 10) + +#define S3C64XX_GPF6_CAMIF_YDATA1 (0x02 << 12) +#define S3C64XX_GPF6_EINT_G4_6 (0x03 << 12) + +#define S3C64XX_GPF7_CAMIF_YDATA2 (0x02 << 14) +#define S3C64XX_GPF7_EINT_G4_7 (0x03 << 14) + +#define S3C64XX_GPF8_CAMIF_YDATA3 (0x02 << 16) +#define S3C64XX_GPF8_EINT_G4_8 (0x03 << 16) + +#define S3C64XX_GPF9_CAMIF_YDATA4 (0x02 << 18) +#define S3C64XX_GPF9_EINT_G4_9 (0x03 << 18) + +#define S3C64XX_GPF10_CAMIF_YDATA5 (0x02 << 20) +#define S3C64XX_GPF10_EINT_G4_10 (0x03 << 20) + +#define S3C64XX_GPF11_CAMIF_YDATA6 (0x02 << 22) +#define S3C64XX_GPF11_EINT_G4_11 (0x03 << 22) + +#define S3C64XX_GPF12_CAMIF_YDATA7 (0x02 << 24) +#define S3C64XX_GPF12_EINT_G4_12 (0x03 << 24) + +#define S3C64XX_GPF13_PWM_ECLK (0x02 << 26) +#define S3C64XX_GPF13_EINT_G4_13 (0x03 << 26) + +#define S3C64XX_GPF14_PWM_TOUT0 (0x02 << 28) +#define S3C64XX_GPF14_CLKOUT0 (0x03 << 28) + +#define S3C64XX_GPF15_PWM_TOUT1 (0x02 << 30) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h new file mode 100644 index 000000000000..35bbd2378e55 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h @@ -0,0 +1,42 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank G register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPGCON (S3C64XX_GPG_BASE + 0x00) +#define S3C64XX_GPGDAT (S3C64XX_GPG_BASE + 0x04) +#define S3C64XX_GPGPUD (S3C64XX_GPG_BASE + 0x08) +#define S3C64XX_GPGCONSLP (S3C64XX_GPG_BASE + 0x0c) +#define S3C64XX_GPGPUDSLP (S3C64XX_GPG_BASE + 0x10) + +#define S3C64XX_GPG_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPG_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPG_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPG0_MMC0_CLK (0x02 << 0) +#define S3C64XX_GPG0_EINT_G5_0 (0x07 << 0) + +#define S3C64XX_GPG1_MMC0_CMD (0x02 << 4) +#define S3C64XX_GPG1_EINT_G5_1 (0x07 << 4) + +#define S3C64XX_GPG2_MMC0_DATA0 (0x02 << 8) +#define S3C64XX_GPG2_EINT_G5_2 (0x07 << 8) + +#define S3C64XX_GPG3_MMC0_DATA1 (0x02 << 12) +#define S3C64XX_GPG3_EINT_G5_3 (0x07 << 12) + +#define S3C64XX_GPG4_MMC0_DATA2 (0x02 << 16) +#define S3C64XX_GPG4_EINT_G5_4 (0x07 << 16) + +#define S3C64XX_GPG5_MMC0_DATA3 (0x02 << 20) +#define S3C64XX_GPG5_EINT_G5_5 (0x07 << 20) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h new file mode 100644 index 000000000000..81549516572f --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h @@ -0,0 +1,74 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank H register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPHCON0 (S3C64XX_GPH_BASE + 0x00) +#define S3C64XX_GPHCON1 (S3C64XX_GPH_BASE + 0x04) +#define S3C64XX_GPHDAT (S3C64XX_GPH_BASE + 0x08) +#define S3C64XX_GPHPUD (S3C64XX_GPH_BASE + 0x0c) +#define S3C64XX_GPHCONSLP (S3C64XX_GPH_BASE + 0x10) +#define S3C64XX_GPHPUDSLP (S3C64XX_GPH_BASE + 0x14) + +#define S3C64XX_GPH_CONMASK(__gpio) (0xf << ((__gpio) * 4)) +#define S3C64XX_GPH_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S3C64XX_GPH_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) + +#define S3C64XX_GPH0_MMC1_CLK (0x02 << 0) +#define S3C64XX_GPH0_KP_COL0 (0x04 << 0) +#define S3C64XX_GPH0_EINT_G6_0 (0x07 << 0) + +#define S3C64XX_GPH1_MMC1_CMD (0x02 << 4) +#define S3C64XX_GPH1_KP_COL1 (0x04 << 4) +#define S3C64XX_GPH1_EINT_G6_1 (0x07 << 4) + +#define S3C64XX_GPH2_MMC1_DATA0 (0x02 << 8) +#define S3C64XX_GPH2_KP_COL2 (0x04 << 8) +#define S3C64XX_GPH2_EINT_G6_2 (0x07 << 8) + +#define S3C64XX_GPH3_MMC1_DATA1 (0x02 << 12) +#define S3C64XX_GPH3_KP_COL3 (0x04 << 12) +#define S3C64XX_GPH3_EINT_G6_3 (0x07 << 12) + +#define S3C64XX_GPH4_MMC1_DATA2 (0x02 << 16) +#define S3C64XX_GPH4_KP_COL4 (0x04 << 16) +#define S3C64XX_GPH4_EINT_G6_4 (0x07 << 16) + +#define S3C64XX_GPH5_MMC1_DATA3 (0x02 << 20) +#define S3C64XX_GPH5_KP_COL5 (0x04 << 20) +#define S3C64XX_GPH5_EINT_G6_5 (0x07 << 20) + +#define S3C64XX_GPH6_MMC1_DATA4 (0x02 << 24) +#define S3C64XX_GPH6_MMC2_DATA0 (0x03 << 24) +#define S3C64XX_GPH6_KP_COL6 (0x04 << 24) +#define S3C64XX_GPH6_I2S_V40_BCLK (0x05 << 24) +#define S3C64XX_GPH6_ADDR_CF0 (0x06 << 24) +#define S3C64XX_GPH6_EINT_G6_6 (0x07 << 24) + +#define S3C64XX_GPH7_MMC1_DATA5 (0x02 << 28) +#define S3C64XX_GPH7_MMC2_DATA1 (0x03 << 28) +#define S3C64XX_GPH7_KP_COL7 (0x04 << 28) +#define S3C64XX_GPH7_I2S_V40_CDCLK (0x05 << 28) +#define S3C64XX_GPH7_ADDR_CF1 (0x06 << 28) +#define S3C64XX_GPH7_EINT_G6_7 (0x07 << 28) + +#define S3C64XX_GPH8_MMC1_DATA6 (0x02 << 32) +#define S3C64XX_GPH8_MMC2_DATA2 (0x03 << 32) +#define S3C64XX_GPH8_I2S_V40_LRCLK (0x05 << 32) +#define S3C64XX_GPH8_ADDR_CF2 (0x06 << 32) +#define S3C64XX_GPH8_EINT_G6_8 (0x07 << 32) + +#define S3C64XX_GPH9_MMC1_DATA7 (0x02 << 36) +#define S3C64XX_GPH9_MMC2_DATA3 (0x03 << 36) +#define S3C64XX_GPH9_I2S_V40_DI (0x05 << 36) +#define S3C64XX_GPH9_EINT_G6_9 (0x07 << 36) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h new file mode 100644 index 000000000000..ce9ebe335566 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h @@ -0,0 +1,40 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank I register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPICON (S3C64XX_GPI_BASE + 0x00) +#define S3C64XX_GPIDAT (S3C64XX_GPI_BASE + 0x04) +#define S3C64XX_GPIPUD (S3C64XX_GPI_BASE + 0x08) +#define S3C64XX_GPICONSLP (S3C64XX_GPI_BASE + 0x0c) +#define S3C64XX_GPIPUDSLP (S3C64XX_GPI_BASE + 0x10) + +#define S3C64XX_GPI_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPI_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPI_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPI0_VD0 (0x02 << 0) +#define S3C64XX_GPI1_VD1 (0x02 << 2) +#define S3C64XX_GPI2_VD2 (0x02 << 4) +#define S3C64XX_GPI3_VD3 (0x02 << 6) +#define S3C64XX_GPI4_VD4 (0x02 << 8) +#define S3C64XX_GPI5_VD5 (0x02 << 10) +#define S3C64XX_GPI6_VD6 (0x02 << 12) +#define S3C64XX_GPI7_VD7 (0x02 << 14) +#define S3C64XX_GPI8_VD8 (0x02 << 16) +#define S3C64XX_GPI9_VD9 (0x02 << 18) +#define S3C64XX_GPI10_VD10 (0x02 << 20) +#define S3C64XX_GPI11_VD11 (0x02 << 22) +#define S3C64XX_GPI12_VD12 (0x02 << 24) +#define S3C64XX_GPI13_VD13 (0x02 << 26) +#define S3C64XX_GPI14_VD14 (0x02 << 28) +#define S3C64XX_GPI15_VD15 (0x02 << 30) diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h new file mode 100644 index 000000000000..21a906299d30 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h @@ -0,0 +1,36 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank J register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPJCON (S3C64XX_GPJ_BASE + 0x00) +#define S3C64XX_GPJDAT (S3C64XX_GPJ_BASE + 0x04) +#define S3C64XX_GPJPUD (S3C64XX_GPJ_BASE + 0x08) +#define S3C64XX_GPJCONSLP (S3C64XX_GPJ_BASE + 0x0c) +#define S3C64XX_GPJPUDSLP (S3C64XX_GPJ_BASE + 0x10) + +#define S3C64XX_GPJ_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPJ_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPJ_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPJ0_VD16 (0x02 << 0) +#define S3C64XX_GPJ1_VD17 (0x02 << 2) +#define S3C64XX_GPJ2_VD18 (0x02 << 4) +#define S3C64XX_GPJ3_VD19 (0x02 << 6) +#define S3C64XX_GPJ4_VD20 (0x02 << 8) +#define S3C64XX_GPJ5_VD21 (0x02 << 10) +#define S3C64XX_GPJ6_VD22 (0x02 << 12) +#define S3C64XX_GPJ7_VD23 (0x02 << 14) +#define S3C64XX_GPJ8_LCD_HSYNC (0x02 << 16) +#define S3C64XX_GPJ9_LCD_VSYNC (0x02 << 18) +#define S3C64XX_GPJ10_LCD_VDEN (0x02 << 20) +#define S3C64XX_GPJ11_LCD_VCLK (0x02 << 22) diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h new file mode 100644 index 000000000000..569e76120881 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h @@ -0,0 +1,54 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank N register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPNCON (S3C64XX_GPN_BASE + 0x00) +#define S3C64XX_GPNDAT (S3C64XX_GPN_BASE + 0x04) +#define S3C64XX_GPNPUD (S3C64XX_GPN_BASE + 0x08) + +#define S3C64XX_GPN_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPN_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPN_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPN0_EINT0 (0x02 << 0) +#define S3C64XX_GPN0_KP_ROW0 (0x03 << 0) + +#define S3C64XX_GPN1_EINT1 (0x02 << 2) +#define S3C64XX_GPN1_KP_ROW1 (0x03 << 2) + +#define S3C64XX_GPN2_EINT2 (0x02 << 4) +#define S3C64XX_GPN2_KP_ROW2 (0x03 << 4) + +#define S3C64XX_GPN3_EINT3 (0x02 << 6) +#define S3C64XX_GPN3_KP_ROW3 (0x03 << 6) + +#define S3C64XX_GPN4_EINT4 (0x02 << 8) +#define S3C64XX_GPN4_KP_ROW4 (0x03 << 8) + +#define S3C64XX_GPN5_EINT5 (0x02 << 10) +#define S3C64XX_GPN5_KP_ROW5 (0x03 << 10) + +#define S3C64XX_GPN6_EINT6 (0x02 << 12) +#define S3C64XX_GPN6_KP_ROW6 (0x03 << 12) + +#define S3C64XX_GPN7_EINT7 (0x02 << 14) +#define S3C64XX_GPN7_KP_ROW7 (0x03 << 14) + +#define S3C64XX_GPN8_EINT8 (0x02 << 16) +#define S3C64XX_GPN9_EINT9 (0x02 << 18) +#define S3C64XX_GPN10_EINT10 (0x02 << 20) +#define S3C64XX_GPN11_EINT11 (0x02 << 22) +#define S3C64XX_GPN12_EINT12 (0x02 << 24) +#define S3C64XX_GPN13_EINT13 (0x02 << 26) +#define S3C64XX_GPN14_EINT14 (0x02 << 28) +#define S3C64XX_GPN15_EINT15 (0x02 << 30) diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h new file mode 100644 index 000000000000..b09e12954b57 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h @@ -0,0 +1,70 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank O register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPOCON (S3C64XX_GPO_BASE + 0x00) +#define S3C64XX_GPODAT (S3C64XX_GPO_BASE + 0x04) +#define S3C64XX_GPOPUD (S3C64XX_GPO_BASE + 0x08) +#define S3C64XX_GPOCONSLP (S3C64XX_GPO_BASE + 0x0c) +#define S3C64XX_GPOPUDSLP (S3C64XX_GPO_BASE + 0x10) + +#define S3C64XX_GPO_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPO_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPO_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPO0_MEM0_nCS2 (0x02 << 0) +#define S3C64XX_GPO0_EINT_G7_0 (0x03 << 0) + +#define S3C64XX_GPO1_MEM0_nCS3 (0x02 << 2) +#define S3C64XX_GPO1_EINT_G7_1 (0x03 << 2) + +#define S3C64XX_GPO2_MEM0_nCS4 (0x02 << 4) +#define S3C64XX_GPO2_EINT_G7_2 (0x03 << 4) + +#define S3C64XX_GPO3_MEM0_nCS5 (0x02 << 6) +#define S3C64XX_GPO3_EINT_G7_3 (0x03 << 6) + +#define S3C64XX_GPO4_EINT_G7_4 (0x03 << 8) + +#define S3C64XX_GPO5_EINT_G7_5 (0x03 << 10) + +#define S3C64XX_GPO6_MEM0_ADDR6 (0x02 << 12) +#define S3C64XX_GPO6_EINT_G7_6 (0x03 << 12) + +#define S3C64XX_GPO7_MEM0_ADDR7 (0x02 << 14) +#define S3C64XX_GPO7_EINT_G7_7 (0x03 << 14) + +#define S3C64XX_GPO8_MEM0_ADDR8 (0x02 << 16) +#define S3C64XX_GPO8_EINT_G7_8 (0x03 << 16) + +#define S3C64XX_GPO9_MEM0_ADDR9 (0x02 << 18) +#define S3C64XX_GPO9_EINT_G7_9 (0x03 << 18) + +#define S3C64XX_GPO10_MEM0_ADDR10 (0x02 << 20) +#define S3C64XX_GPO10_EINT_G7_10 (0x03 << 20) + +#define S3C64XX_GPO11_MEM0_ADDR11 (0x02 << 22) +#define S3C64XX_GPO11_EINT_G7_11 (0x03 << 22) + +#define S3C64XX_GPO12_MEM0_ADDR12 (0x02 << 24) +#define S3C64XX_GPO12_EINT_G7_12 (0x03 << 24) + +#define S3C64XX_GPO13_MEM0_ADDR13 (0x02 << 26) +#define S3C64XX_GPO13_EINT_G7_13 (0x03 << 26) + +#define S3C64XX_GPO14_MEM0_ADDR14 (0x02 << 28) +#define S3C64XX_GPO14_EINT_G7_14 (0x03 << 28) + +#define S3C64XX_GPO15_MEM0_ADDR15 (0x02 << 30) +#define S3C64XX_GPO15_EINT_G7_15 (0x03 << 30) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h new file mode 100644 index 000000000000..92f00517926b --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h @@ -0,0 +1,69 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank P register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPPCON (S3C64XX_GPP_BASE + 0x00) +#define S3C64XX_GPPDAT (S3C64XX_GPP_BASE + 0x04) +#define S3C64XX_GPPPUD (S3C64XX_GPP_BASE + 0x08) +#define S3C64XX_GPPCONSLP (S3C64XX_GPP_BASE + 0x0c) +#define S3C64XX_GPPPUDSLP (S3C64XX_GPP_BASE + 0x10) + +#define S3C64XX_GPP_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPP_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPP_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPP0_MEM0_ADDRV (0x02 << 0) +#define S3C64XX_GPP0_EINT_G8_0 (0x03 << 0) + +#define S3C64XX_GPP1_MEM0_SMCLK (0x02 << 2) +#define S3C64XX_GPP1_EINT_G8_1 (0x03 << 2) + +#define S3C64XX_GPP2_MEM0_nWAIT (0x02 << 4) +#define S3C64XX_GPP2_EINT_G8_2 (0x03 << 4) + +#define S3C64XX_GPP3_MEM0_RDY0_ALE (0x02 << 6) +#define S3C64XX_GPP3_EINT_G8_3 (0x03 << 6) + +#define S3C64XX_GPP4_MEM0_RDY1_CLE (0x02 << 8) +#define S3C64XX_GPP4_EINT_G8_4 (0x03 << 8) + +#define S3C64XX_GPP5_MEM0_INTsm0_FWE (0x02 << 10) +#define S3C64XX_GPP5_EINT_G8_5 (0x03 << 10) + +#define S3C64XX_GPP6_MEM0_(null) (0x02 << 12) +#define S3C64XX_GPP6_EINT_G8_6 (0x03 << 12) + +#define S3C64XX_GPP7_MEM0_INTsm1_FRE (0x02 << 14) +#define S3C64XX_GPP7_EINT_G8_7 (0x03 << 14) + +#define S3C64XX_GPP8_MEM0_RPn_RnB (0x02 << 16) +#define S3C64XX_GPP8_EINT_G8_8 (0x03 << 16) + +#define S3C64XX_GPP9_MEM0_ATA_RESET (0x02 << 18) +#define S3C64XX_GPP9_EINT_G8_9 (0x03 << 18) + +#define S3C64XX_GPP10_MEM0_ATA_INPACK (0x02 << 20) +#define S3C64XX_GPP10_EINT_G8_10 (0x03 << 20) + +#define S3C64XX_GPP11_MEM0_ATA_REG (0x02 << 22) +#define S3C64XX_GPP11_EINT_G8_11 (0x03 << 22) + +#define S3C64XX_GPP12_MEM0_ATA_WE (0x02 << 24) +#define S3C64XX_GPP12_EINT_G8_12 (0x03 << 24) + +#define S3C64XX_GPP13_MEM0_ATA_OE (0x02 << 26) +#define S3C64XX_GPP13_EINT_G8_13 (0x03 << 26) + +#define S3C64XX_GPP14_MEM0_ATA_CD (0x02 << 28) +#define S3C64XX_GPP14_EINT_G8_14 (0x03 << 28) + diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h new file mode 100644 index 000000000000..565e60aaee47 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h @@ -0,0 +1,46 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * GPIO Bank Q register and configuration definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C64XX_GPQCON (S3C64XX_GPQ_BASE + 0x00) +#define S3C64XX_GPQDAT (S3C64XX_GPQ_BASE + 0x04) +#define S3C64XX_GPQPUD (S3C64XX_GPQ_BASE + 0x08) +#define S3C64XX_GPQCONSLP (S3C64XX_GPQ_BASE + 0x0c) +#define S3C64XX_GPQPUDSLP (S3C64XX_GPQ_BASE + 0x10) + +#define S3C64XX_GPQ_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) +#define S3C64XX_GPQ_INPUT(__gpio) (0x0 << ((__gpio) * 2)) +#define S3C64XX_GPQ_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) + +#define S3C64XX_GPQ0_MEM0_ADDR18_RAS (0x02 << 0) +#define S3C64XX_GPQ0_EINT_G9_0 (0x03 << 0) + +#define S3C64XX_GPQ1_MEM0_ADDR19_CAS (0x02 << 2) +#define S3C64XX_GPQ1_EINT_G9_1 (0x03 << 2) + +#define S3C64XX_GPQ2_EINT_G9_2 (0x03 << 4) + +#define S3C64XX_GPQ3_EINT_G9_3 (0x03 << 6) + +#define S3C64XX_GPQ4_EINT_G9_4 (0x03 << 8) + +#define S3C64XX_GPQ5_EINT_G9_5 (0x03 << 10) + +#define S3C64XX_GPQ6_EINT_G9_6 (0x03 << 12) + +#define S3C64XX_GPQ7_MEM0_ADDR17_WENDMC (0x02 << 14) +#define S3C64XX_GPQ7_EINT_G9_7 (0x03 << 14) + +#define S3C64XX_GPQ8_MEM0_ADDR16_APDMC (0x02 << 16) +#define S3C64XX_GPQ8_EINT_G9_8 (0x03 << 16) + diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h new file mode 100644 index 000000000000..02e8dd4c97d5 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -0,0 +1,201 @@ +/* linux/arch/arm/plat-s3c64xx/include/mach/irqs.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Common IRQ support + */ + +#ifndef __ASM_PLAT_S3C64XX_IRQS_H +#define __ASM_PLAT_S3C64XX_IRQS_H __FILE__ + +/* we keep the first set of CPU IRQs out of the range of + * the ISA space, so that the PC104 has them to itself + * and we don't end up having to do horrible things to the + * standard ISA drivers.... + * + * note, since we're using the VICs, our start must be a + * mulitple of 32 to allow the common code to work + */ + +#define S3C_IRQ_OFFSET (32) + +#define S3C_IRQ(x) ((x) + S3C_IRQ_OFFSET) + +#define S3C_VIC0_BASE S3C_IRQ(0) +#define S3C_VIC1_BASE S3C_IRQ(32) + +/* UART interrupts, each UART has 4 intterupts per channel so + * use the space between the ISA and S3C main interrupts. Note, these + * are not in the same order as the S3C24XX series! */ + +#define IRQ_S3CUART_BASE0 (16) +#define IRQ_S3CUART_BASE1 (20) +#define IRQ_S3CUART_BASE2 (24) +#define IRQ_S3CUART_BASE3 (28) + +#define UART_IRQ_RXD (0) +#define UART_IRQ_ERR (1) +#define UART_IRQ_TXD (2) +#define UART_IRQ_MODEM (3) + +#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) + +/* VIC based IRQs */ + +#define S3C64XX_IRQ_VIC0(x) (S3C_VIC0_BASE + (x)) +#define S3C64XX_IRQ_VIC1(x) (S3C_VIC1_BASE + (x)) + +/* VIC0 */ + +#define IRQ_EINT0_3 S3C64XX_IRQ_VIC0(0) +#define IRQ_EINT4_11 S3C64XX_IRQ_VIC0(1) +#define IRQ_RTC_TIC S3C64XX_IRQ_VIC0(2) +#define IRQ_CAMIF_C S3C64XX_IRQ_VIC0(3) +#define IRQ_CAMIF_P S3C64XX_IRQ_VIC0(4) +#define IRQ_CAMIF_MC S3C64XX_IRQ_VIC0(5) +#define IRQ_S3C6410_IIC1 S3C64XX_IRQ_VIC0(5) +#define IRQ_S3C6410_IIS S3C64XX_IRQ_VIC0(6) +#define IRQ_S3C6400_CAMIF_MP S3C64XX_IRQ_VIC0(6) +#define IRQ_CAMIF_WE_C S3C64XX_IRQ_VIC0(7) +#define IRQ_S3C6410_G3D S3C64XX_IRQ_VIC0(8) +#define IRQ_S3C6400_CAMIF_WE_P S3C64XX_IRQ_VIC0(8) +#define IRQ_POST0 S3C64XX_IRQ_VIC0(9) +#define IRQ_ROTATOR S3C64XX_IRQ_VIC0(10) +#define IRQ_2D S3C64XX_IRQ_VIC0(11) +#define IRQ_TVENC S3C64XX_IRQ_VIC0(12) +#define IRQ_SCALER S3C64XX_IRQ_VIC0(13) +#define IRQ_BATF S3C64XX_IRQ_VIC0(14) +#define IRQ_JPEG S3C64XX_IRQ_VIC0(15) +#define IRQ_MFC S3C64XX_IRQ_VIC0(16) +#define IRQ_SDMA0 S3C64XX_IRQ_VIC0(17) +#define IRQ_SDMA1 S3C64XX_IRQ_VIC0(18) +#define IRQ_ARM_DMAERR S3C64XX_IRQ_VIC0(19) +#define IRQ_ARM_DMA S3C64XX_IRQ_VIC0(20) +#define IRQ_ARM_DMAS S3C64XX_IRQ_VIC0(21) +#define IRQ_KEYPAD S3C64XX_IRQ_VIC0(22) +#define IRQ_TIMER0_VIC S3C64XX_IRQ_VIC0(23) +#define IRQ_TIMER1_VIC S3C64XX_IRQ_VIC0(24) +#define IRQ_TIMER2_VIC S3C64XX_IRQ_VIC0(25) +#define IRQ_WDT S3C64XX_IRQ_VIC0(26) +#define IRQ_TIMER3_VIC S3C64XX_IRQ_VIC0(27) +#define IRQ_TIMER4_VIC S3C64XX_IRQ_VIC0(28) +#define IRQ_LCD_FIFO S3C64XX_IRQ_VIC0(29) +#define IRQ_LCD_VSYNC S3C64XX_IRQ_VIC0(30) +#define IRQ_LCD_SYSTEM S3C64XX_IRQ_VIC0(31) + +/* VIC1 */ + +#define IRQ_EINT12_19 S3C64XX_IRQ_VIC1(0) +#define IRQ_EINT20_27 S3C64XX_IRQ_VIC1(1) +#define IRQ_PCM0 S3C64XX_IRQ_VIC1(2) +#define IRQ_PCM1 S3C64XX_IRQ_VIC1(3) +#define IRQ_AC97 S3C64XX_IRQ_VIC1(4) +#define IRQ_UART0 S3C64XX_IRQ_VIC1(5) +#define IRQ_UART1 S3C64XX_IRQ_VIC1(6) +#define IRQ_UART2 S3C64XX_IRQ_VIC1(7) +#define IRQ_UART3 S3C64XX_IRQ_VIC1(8) +#define IRQ_DMA0 S3C64XX_IRQ_VIC1(9) +#define IRQ_DMA1 S3C64XX_IRQ_VIC1(10) +#define IRQ_ONENAND0 S3C64XX_IRQ_VIC1(11) +#define IRQ_ONENAND1 S3C64XX_IRQ_VIC1(12) +#define IRQ_NFC S3C64XX_IRQ_VIC1(13) +#define IRQ_CFCON S3C64XX_IRQ_VIC1(14) +#define IRQ_UHOST S3C64XX_IRQ_VIC1(15) +#define IRQ_SPI0 S3C64XX_IRQ_VIC1(16) +#define IRQ_SPI1 S3C64XX_IRQ_VIC1(17) +#define IRQ_IIC S3C64XX_IRQ_VIC1(18) +#define IRQ_HSItx S3C64XX_IRQ_VIC1(19) +#define IRQ_HSIrx S3C64XX_IRQ_VIC1(20) +#define IRQ_RESERVED S3C64XX_IRQ_VIC1(21) +#define IRQ_MSM S3C64XX_IRQ_VIC1(22) +#define IRQ_HOSTIF S3C64XX_IRQ_VIC1(23) +#define IRQ_HSMMC0 S3C64XX_IRQ_VIC1(24) +#define IRQ_HSMMC1 S3C64XX_IRQ_VIC1(25) +#define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */ +#define IRQ_OTG S3C64XX_IRQ_VIC1(26) +#define IRQ_IRDA S3C64XX_IRQ_VIC1(27) +#define IRQ_RTC_ALARM S3C64XX_IRQ_VIC1(28) +#define IRQ_SEC S3C64XX_IRQ_VIC1(29) +#define IRQ_PENDN S3C64XX_IRQ_VIC1(30) +#define IRQ_TC IRQ_PENDN +#define IRQ_ADC S3C64XX_IRQ_VIC1(31) + +#define S3C64XX_TIMER_IRQ(x) S3C_IRQ(64 + (x)) + +#define IRQ_TIMER0 S3C64XX_TIMER_IRQ(0) +#define IRQ_TIMER1 S3C64XX_TIMER_IRQ(1) +#define IRQ_TIMER2 S3C64XX_TIMER_IRQ(2) +#define IRQ_TIMER3 S3C64XX_TIMER_IRQ(3) +#define IRQ_TIMER4 S3C64XX_TIMER_IRQ(4) + +/* compatibility for device defines */ + +#define IRQ_IIC1 IRQ_S3C6410_IIC1 + +/* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series + * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE + * which we place after the pair of VICs. */ + +#define S3C_IRQ_EINT_BASE S3C_IRQ(64+5) + +#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) +#define IRQ_EINT(x) S3C_EINT(x) + +/* Next the external interrupt groups. These are similar to the IRQ_EINT(x) + * that they are sourced from the GPIO pins but with a different scheme for + * priority and source indication. + * + * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO + * interrupts, but for historical reasons they are kept apart from these + * next interrupts. + * + * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the + * machine specific support files. + */ + +#define IRQ_EINT_GROUP1_NR (15) +#define IRQ_EINT_GROUP2_NR (8) +#define IRQ_EINT_GROUP3_NR (5) +#define IRQ_EINT_GROUP4_NR (14) +#define IRQ_EINT_GROUP5_NR (7) +#define IRQ_EINT_GROUP6_NR (10) +#define IRQ_EINT_GROUP7_NR (16) +#define IRQ_EINT_GROUP8_NR (15) +#define IRQ_EINT_GROUP9_NR (9) + +#define IRQ_EINT_GROUP_BASE S3C_EINT(28) +#define IRQ_EINT_GROUP1_BASE (IRQ_EINT_GROUP_BASE + 0x00) +#define IRQ_EINT_GROUP2_BASE (IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR) +#define IRQ_EINT_GROUP3_BASE (IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR) +#define IRQ_EINT_GROUP4_BASE (IRQ_EINT_GROUP3_BASE + IRQ_EINT_GROUP3_NR) +#define IRQ_EINT_GROUP5_BASE (IRQ_EINT_GROUP4_BASE + IRQ_EINT_GROUP4_NR) +#define IRQ_EINT_GROUP6_BASE (IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR) +#define IRQ_EINT_GROUP7_BASE (IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR) +#define IRQ_EINT_GROUP8_BASE (IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR) +#define IRQ_EINT_GROUP9_BASE (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR) + +#define IRQ_EINT_GROUP(group, no) (IRQ_EINT_GROUP##group##__BASE + (x)) + +/* Set the default NR_IRQS */ + +#define NR_IRQS (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1) + +#endif /* __ASM_PLAT_S3C64XX_IRQS_H */ + diff --git a/arch/arm/plat-s3c64xx/include/plat/pll.h b/arch/arm/plat-s3c64xx/include/plat/pll.h new file mode 100644 index 000000000000..90bbd72fdc4e --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/pll.h @@ -0,0 +1,74 @@ +/* arch/arm/plat-s3c64xx/include/plat/pll.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX PLL code + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S3C6400_PLL_MDIV_MASK ((1 << (25-16+1)) - 1) +#define S3C6400_PLL_PDIV_MASK ((1 << (13-8+1)) - 1) +#define S3C6400_PLL_SDIV_MASK ((1 << (2-0+1)) - 1) +#define S3C6400_PLL_MDIV_SHIFT (16) +#define S3C6400_PLL_PDIV_SHIFT (8) +#define S3C6400_PLL_SDIV_SHIFT (0) + +#include <asm/div64.h> + +static inline unsigned long s3c6400_get_pll(unsigned long baseclk, + u32 pllcon) +{ + u32 mdiv, pdiv, sdiv; + u64 fvco = baseclk; + + mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK; + pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK; + sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +#define S3C6400_EPLL_MDIV_MASK ((1 << (23-16)) - 1) +#define S3C6400_EPLL_PDIV_MASK ((1 << (13-8)) - 1) +#define S3C6400_EPLL_SDIV_MASK ((1 << (2-0)) - 1) +#define S3C6400_EPLL_MDIV_SHIFT (16) +#define S3C6400_EPLL_PDIV_SHIFT (8) +#define S3C6400_EPLL_SDIV_SHIFT (0) +#define S3C6400_EPLL_KDIV_MASK (0xffff) + +static inline unsigned long s3c6400_get_epll(unsigned long baseclk) +{ + unsigned long result; + u32 epll0 = __raw_readl(S3C_EPLL_CON0); + u32 epll1 = __raw_readl(S3C_EPLL_CON1); + u32 mdiv, pdiv, sdiv, kdiv; + u64 tmp; + + mdiv = (epll0 >> S3C6400_EPLL_MDIV_SHIFT) & S3C6400_EPLL_MDIV_MASK; + pdiv = (epll0 >> S3C6400_EPLL_PDIV_SHIFT) & S3C6400_EPLL_PDIV_MASK; + sdiv = (epll0 >> S3C6400_EPLL_SDIV_SHIFT) & S3C6400_EPLL_SDIV_MASK; + kdiv = epll1 & S3C6400_EPLL_KDIV_MASK; + + /* We need to multiple baseclk by mdiv (the integer part) and kdiv + * which is in 2^16ths, so shift mdiv up (does not overflow) and + * add kdiv before multiplying. The use of tmp is to avoid any + * overflows before shifting bac down into result when multipling + * by the mdiv and kdiv pair. + */ + + tmp = baseclk; + tmp *= (mdiv << 16) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 16; + + return result; +} diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h new file mode 100644 index 000000000000..b1082c163247 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h @@ -0,0 +1,224 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-clock.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX clock register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_REGS_CLOCK_H +#define __PLAT_REGS_CLOCK_H __FILE__ + +#define S3C_CLKREG(x) (S3C_VA_SYS + (x)) + +#define S3C_APLL_LOCK S3C_CLKREG(0x00) +#define S3C_MPLL_LOCK S3C_CLKREG(0x04) +#define S3C_EPLL_LOCK S3C_CLKREG(0x08) +#define S3C_APLL_CON S3C_CLKREG(0x0C) +#define S3C_MPLL_CON S3C_CLKREG(0x10) +#define S3C_EPLL_CON0 S3C_CLKREG(0x14) +#define S3C_EPLL_CON1 S3C_CLKREG(0x18) +#define S3C_CLK_SRC S3C_CLKREG(0x1C) +#define S3C_CLK_DIV0 S3C_CLKREG(0x20) +#define S3C_CLK_DIV1 S3C_CLKREG(0x24) +#define S3C_CLK_DIV2 S3C_CLKREG(0x28) +#define S3C_CLK_OUT S3C_CLKREG(0x2C) +#define S3C_HCLK_GATE S3C_CLKREG(0x30) +#define S3C_PCLK_GATE S3C_CLKREG(0x34) +#define S3C_SCLK_GATE S3C_CLKREG(0x38) + +/* CLKDIV0 */ +#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28) +#define S3C6400_CLKDIV0_MFC_SHIFT (28) +#define S3C6400_CLKDIV0_JPEG_MASK (0xf << 24) +#define S3C6400_CLKDIV0_JPEG_SHIFT (24) +#define S3C6400_CLKDIV0_CAM_MASK (0xf << 20) +#define S3C6400_CLKDIV0_CAM_SHIFT (20) +#define S3C6400_CLKDIV0_SECURITY_MASK (0x3 << 18) +#define S3C6400_CLKDIV0_SECURITY_SHIFT (18) +#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12) +#define S3C6400_CLKDIV0_PCLK_SHIFT (12) +#define S3C6400_CLKDIV0_HCLK2_MASK (0x7 << 9) +#define S3C6400_CLKDIV0_HCLK2_SHIFT (9) +#define S3C6400_CLKDIV0_HCLK_MASK (0x1 << 8) +#define S3C6400_CLKDIV0_HCLK_SHIFT (8) +#define S3C6400_CLKDIV0_MPLL_MASK (0x1 << 4) +#define S3C6400_CLKDIV0_MPLL_SHIFT (4) +#define S3C6400_CLKDIV0_ARM_MASK (0x3 << 0) +#define S3C6410_CLKDIV0_ARM_MASK (0x7 << 0) +#define S3C6400_CLKDIV0_ARM_SHIFT (0) + +/* CLKDIV1 */ +#define S3C6410_CLKDIV1_FIMC_MASK (0xf << 24) +#define S3C6410_CLKDIV1_FIMC_SHIFT (24) +#define S3C6400_CLKDIV1_UHOST_MASK (0xf << 20) +#define S3C6400_CLKDIV1_UHOST_SHIFT (20) +#define S3C6400_CLKDIV1_SCALER_MASK (0xf << 16) +#define S3C6400_CLKDIV1_SCALER_SHIFT (16) +#define S3C6400_CLKDIV1_LCD_MASK (0xf << 12) +#define S3C6400_CLKDIV1_LCD_SHIFT (12) +#define S3C6400_CLKDIV1_MMC2_MASK (0xf << 8) +#define S3C6400_CLKDIV1_MMC2_SHIFT (8) +#define S3C6400_CLKDIV1_MMC1_MASK (0xf << 4) +#define S3C6400_CLKDIV1_MMC1_SHIFT (4) +#define S3C6400_CLKDIV1_MMC0_MASK (0xf << 0) +#define S3C6400_CLKDIV1_MMC0_SHIFT (0) + +/* CLKDIV2 */ +#define S3C6410_CLKDIV2_AUDIO2_MASK (0xf << 24) +#define S3C6410_CLKDIV2_AUDIO2_SHIFT (24) +#define S3C6400_CLKDIV2_IRDA_MASK (0xf << 20) +#define S3C6400_CLKDIV2_IRDA_SHIFT (20) +#define S3C6400_CLKDIV2_UART_MASK (0xf << 16) +#define S3C6400_CLKDIV2_UART_SHIFT (16) +#define S3C6400_CLKDIV2_AUDIO1_MASK (0xf << 12) +#define S3C6400_CLKDIV2_AUDIO1_SHIFT (12) +#define S3C6400_CLKDIV2_AUDIO0_MASK (0xf << 8) +#define S3C6400_CLKDIV2_AUDIO0_SHIFT (8) +#define S3C6400_CLKDIV2_SPI1_MASK (0xf << 4) +#define S3C6400_CLKDIV2_SPI1_SHIFT (4) +#define S3C6400_CLKDIV2_SPI0_MASK (0xf << 0) +#define S3C6400_CLKDIV2_SPI0_SHIFT (0) + +/* HCLK GATE Registers */ +#define S3C_CLKCON_HCLK_BUS (1<<30) +#define S3C_CLKCON_HCLK_SECUR (1<<29) +#define S3C_CLKCON_HCLK_SDMA1 (1<<28) +#define S3C_CLKCON_HCLK_SDMA2 (1<<27) +#define S3C_CLKCON_HCLK_UHOST (1<<26) +#define S3C_CLKCON_HCLK_IROM (1<<25) +#define S3C_CLKCON_HCLK_DDR1 (1<<24) +#define S3C_CLKCON_HCLK_DDR0 (1<<23) +#define S3C_CLKCON_HCLK_MEM1 (1<<22) +#define S3C_CLKCON_HCLK_MEM0 (1<<21) +#define S3C_CLKCON_HCLK_USB (1<<20) +#define S3C_CLKCON_HCLK_HSMMC2 (1<<19) +#define S3C_CLKCON_HCLK_HSMMC1 (1<<18) +#define S3C_CLKCON_HCLK_HSMMC0 (1<<17) +#define S3C_CLKCON_HCLK_MDP (1<<16) +#define S3C_CLKCON_HCLK_DHOST (1<<15) +#define S3C_CLKCON_HCLK_IHOST (1<<14) +#define S3C_CLKCON_HCLK_DMA1 (1<<13) +#define S3C_CLKCON_HCLK_DMA0 (1<<12) +#define S3C_CLKCON_HCLK_JPEG (1<<11) +#define S3C_CLKCON_HCLK_CAMIF (1<<10) +#define S3C_CLKCON_HCLK_SCALER (1<<9) +#define S3C_CLKCON_HCLK_2D (1<<8) +#define S3C_CLKCON_HCLK_TV (1<<7) +#define S3C_CLKCON_HCLK_POST0 (1<<5) +#define S3C_CLKCON_HCLK_ROT (1<<4) +#define S3C_CLKCON_HCLK_LCD (1<<3) +#define S3C_CLKCON_HCLK_TZIC (1<<2) +#define S3C_CLKCON_HCLK_INTC (1<<1) +#define S3C_CLKCON_HCLK_MFC (1<<0) + +/* PCLK GATE Registers */ +#define S3C6410_CLKCON_PCLK_I2C1 (1<<27) +#define S3C6410_CLKCON_PCLK_IIS2 (1<<26) +#define S3C_CLKCON_PCLK_SKEY (1<<24) +#define S3C_CLKCON_PCLK_CHIPID (1<<23) +#define S3C_CLKCON_PCLK_SPI1 (1<<22) +#define S3C_CLKCON_PCLK_SPI0 (1<<21) +#define S3C_CLKCON_PCLK_HSIRX (1<<20) +#define S3C_CLKCON_PCLK_HSITX (1<<19) +#define S3C_CLKCON_PCLK_GPIO (1<<18) +#define S3C_CLKCON_PCLK_IIC (1<<17) +#define S3C_CLKCON_PCLK_IIS1 (1<<16) +#define S3C_CLKCON_PCLK_IIS0 (1<<15) +#define S3C_CLKCON_PCLK_AC97 (1<<14) +#define S3C_CLKCON_PCLK_TZPC (1<<13) +#define S3C_CLKCON_PCLK_TSADC (1<<12) +#define S3C_CLKCON_PCLK_KEYPAD (1<<11) +#define S3C_CLKCON_PCLK_IRDA (1<<10) +#define S3C_CLKCON_PCLK_PCM1 (1<<9) +#define S3C_CLKCON_PCLK_PCM0 (1<<8) +#define S3C_CLKCON_PCLK_PWM (1<<7) +#define S3C_CLKCON_PCLK_RTC (1<<6) +#define S3C_CLKCON_PCLK_WDT (1<<5) +#define S3C_CLKCON_PCLK_UART3 (1<<4) +#define S3C_CLKCON_PCLK_UART2 (1<<3) +#define S3C_CLKCON_PCLK_UART1 (1<<2) +#define S3C_CLKCON_PCLK_UART0 (1<<1) +#define S3C_CLKCON_PCLK_MFC (1<<0) + +/* SCLK GATE Registers */ +#define S3C_CLKCON_SCLK_UHOST (1<<30) +#define S3C_CLKCON_SCLK_MMC2_48 (1<<29) +#define S3C_CLKCON_SCLK_MMC1_48 (1<<28) +#define S3C_CLKCON_SCLK_MMC0_48 (1<<27) +#define S3C_CLKCON_SCLK_MMC2 (1<<26) +#define S3C_CLKCON_SCLK_MMC1 (1<<25) +#define S3C_CLKCON_SCLK_MMC0 (1<<24) +#define S3C_CLKCON_SCLK_SPI1_48 (1<<23) +#define S3C_CLKCON_SCLK_SPI0_48 (1<<22) +#define S3C_CLKCON_SCLK_SPI1 (1<<21) +#define S3C_CLKCON_SCLK_SPI0 (1<<20) +#define S3C_CLKCON_SCLK_DAC27 (1<<19) +#define S3C_CLKCON_SCLK_TV27 (1<<18) +#define S3C_CLKCON_SCLK_SCALER27 (1<<17) +#define S3C_CLKCON_SCLK_SCALER (1<<16) +#define S3C_CLKCON_SCLK_LCD27 (1<<15) +#define S3C_CLKCON_SCLK_LCD (1<<14) +#define S3C6400_CLKCON_SCLK_POST1_27 (1<<13) +#define S3C6410_CLKCON_FIMC (1<<13) +#define S3C_CLKCON_SCLK_POST0_27 (1<<12) +#define S3C6400_CLKCON_SCLK_POST1 (1<<11) +#define S3C6410_CLKCON_SCLK_AUDIO2 (1<<11) +#define S3C_CLKCON_SCLK_POST0 (1<<10) +#define S3C_CLKCON_SCLK_AUDIO1 (1<<9) +#define S3C_CLKCON_SCLK_AUDIO0 (1<<8) +#define S3C_CLKCON_SCLK_SECUR (1<<7) +#define S3C_CLKCON_SCLK_IRDA (1<<6) +#define S3C_CLKCON_SCLK_UART (1<<5) +#define S3C_CLKCON_SCLK_ONENAND (1<<4) +#define S3C_CLKCON_SCLK_MFC (1<<3) +#define S3C_CLKCON_SCLK_CAM (1<<2) +#define S3C_CLKCON_SCLK_JPEG (1<<1) + +/* CLKSRC */ + +#define S3C6400_CLKSRC_APLL_MOUT (1 << 0) +#define S3C6400_CLKSRC_MPLL_MOUT (1 << 1) +#define S3C6400_CLKSRC_EPLL_MOUT (1 << 2) +#define S3C6400_CLKSRC_APLL_MOUT_SHIFT (0) +#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT (1) +#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2) +#define S3C6400_CLKSRC_MFC (1 << 4) + +#define S3C6410_CLKSRC_TV27_MASK (0x1 << 31) +#define S3C6410_CLKSRC_TV27_SHIFT (31) +#define S3C6410_CLKSRC_DAC27_MASK (0x1 << 30) +#define S3C6410_CLKSRC_DAC27_SHIFT (30) +#define S3C6400_CLKSRC_SCALER_MASK (0x3 << 28) +#define S3C6400_CLKSRC_SCALER_SHIFT (28) +#define S3C6400_CLKSRC_LCD_MASK (0x3 << 26) +#define S3C6400_CLKSRC_LCD_SHIFT (26) +#define S3C6400_CLKSRC_IRDA_MASK (0x3 << 24) +#define S3C6400_CLKSRC_IRDA_SHIFT (24) +#define S3C6400_CLKSRC_MMC2_MASK (0x3 << 22) +#define S3C6400_CLKSRC_MMC2_SHIFT (22) +#define S3C6400_CLKSRC_MMC1_MASK (0x3 << 20) +#define S3C6400_CLKSRC_MMC1_SHIFT (20) +#define S3C6400_CLKSRC_MMC0_MASK (0x3 << 18) +#define S3C6400_CLKSRC_MMC0_SHIFT (18) +#define S3C6400_CLKSRC_SPI1_MASK (0x3 << 16) +#define S3C6400_CLKSRC_SPI1_SHIFT (16) +#define S3C6400_CLKSRC_SPI0_MASK (0x3 << 14) +#define S3C6400_CLKSRC_SPI0_SHIFT (14) +#define S3C6400_CLKSRC_UART_MASK (0x1 << 13) +#define S3C6400_CLKSRC_UART_SHIFT (13) +#define S3C6400_CLKSRC_AUDIO1_MASK (0x7 << 10) +#define S3C6400_CLKSRC_AUDIO1_SHIFT (10) +#define S3C6400_CLKSRC_AUDIO0_MASK (0x7 << 7) +#define S3C6400_CLKSRC_AUDIO0_SHIFT (7) +#define S3C6400_CLKSRC_UHOST_MASK (0x3 << 5) +#define S3C6400_CLKSRC_UHOST_SHIFT (5) + + +#endif /* _PLAT_REGS_CLOCK_H */ diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h new file mode 100644 index 000000000000..75b873d82808 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h @@ -0,0 +1,35 @@ +/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIO register definitions + */ + +#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_H +#define __ASM_PLAT_S3C64XX_REGS_GPIO_H __FILE__ + +/* Base addresses for each of the banks */ + +#define S3C64XX_GPA_BASE (S3C64XX_VA_GPIO + 0x0000) +#define S3C64XX_GPB_BASE (S3C64XX_VA_GPIO + 0x0020) +#define S3C64XX_GPC_BASE (S3C64XX_VA_GPIO + 0x0040) +#define S3C64XX_GPD_BASE (S3C64XX_VA_GPIO + 0x0060) +#define S3C64XX_GPE_BASE (S3C64XX_VA_GPIO + 0x0080) +#define S3C64XX_GPF_BASE (S3C64XX_VA_GPIO + 0x00A0) +#define S3C64XX_GPG_BASE (S3C64XX_VA_GPIO + 0x00C0) +#define S3C64XX_GPH_BASE (S3C64XX_VA_GPIO + 0x00E0) +#define S3C64XX_GPI_BASE (S3C64XX_VA_GPIO + 0x0100) +#define S3C64XX_GPJ_BASE (S3C64XX_VA_GPIO + 0x0120) +#define S3C64XX_GPK_BASE (S3C64XX_VA_GPIO + 0x0800) +#define S3C64XX_GPL_BASE (S3C64XX_VA_GPIO + 0x0810) +#define S3C64XX_GPM_BASE (S3C64XX_VA_GPIO + 0x0820) +#define S3C64XX_GPN_BASE (S3C64XX_VA_GPIO + 0x0830) +#define S3C64XX_GPO_BASE (S3C64XX_VA_GPIO + 0x0140) +#define S3C64XX_GPP_BASE (S3C64XX_VA_GPIO + 0x0160) +#define S3C64XX_GPQ_BASE (S3C64XX_VA_GPIO + 0x0180) + +#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */ + diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h new file mode 100644 index 000000000000..d8ed82917096 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h @@ -0,0 +1,24 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-sys.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX system register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_REGS_SYS_H +#define __PLAT_REGS_SYS_H __FILE__ + +#define S3C_SYSREG(x) (S3C_VA_SYS + (x)) + +#define S3C64XX_OTHERS S3C_SYSREG(0x900) + +#define S3C64XX_OTHERS_USBMASK (1 << 16) + +#endif /* _PLAT_REGS_SYS_H */ diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h new file mode 100644 index 000000000000..571eaa2e54f1 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h @@ -0,0 +1,35 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6400.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6400 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Common init code for S3C6400 related SoCs */ + +extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); +extern void s3c6400_register_clocks(void); +extern void s3c6400_setup_clocks(void); + +#ifdef CONFIG_CPU_S3C6400 + +extern int s3c6400_init(void); +extern void s3c6400_map_io(void); +extern void s3c6400_init_clocks(int xtal); + +#define s3c6400_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6400_init_clocks NULL +#define s3c6400_init_uarts NULL +#define s3c6400_map_io NULL +#define s3c6400_init NULL +#endif + diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h new file mode 100644 index 000000000000..50dcdd6f6800 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h @@ -0,0 +1,29 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6410.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6410 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C6410 + +extern int s3c6410_init(void); +extern void s3c6410_init_irq(void); +extern void s3c6410_map_io(void); +extern void s3c6410_init_clocks(int xtal); + +#define s3c6410_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6410_init_clocks NULL +#define s3c6410_init_uarts NULL +#define s3c6410_map_io NULL +#define s3c6410_init NULL +#endif diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c new file mode 100644 index 000000000000..1f7cc0067f5c --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -0,0 +1,202 @@ +/* arch/arm/plat-s3c64xx/irq-eint.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling for IRQ_EINT(x) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/hardware/vic.h> + +#include <plat/regs-irqtype.h> + +#include <mach/map.h> +#include <plat/cpu.h> + +/* GPIO is 0x7F008xxx, */ +#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x)) + +#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900) +#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904) +#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910) +#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914) +#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918) +#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C) + +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) + + +#define eint_offset(irq) ((irq) - IRQ_EINT(0)) +#define eint_irq_to_bit(irq) (1 << eint_offset(irq)) + +static inline void s3c_irq_eint_mask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static void s3c_irq_eint_unmask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static inline void s3c_irq_eint_ack(unsigned int irq) +{ + __raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND); +} + +static void s3c_irq_eint_maskack(unsigned int irq) +{ + /* compiler should in-line these */ + s3c_irq_eint_mask(irq); + s3c_irq_eint_ack(irq); +} + +static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) +{ + int offs = eint_offset(irq); + int shift; + u32 ctrl, mask; + u32 newvalue = 0; + void __iomem *reg; + + if (offs > 27) + return -EINVAL; + + if (offs <= 15) + reg = S3C64XX_EINT0CON0; + else + reg = S3C64XX_EINT0CON1; + + switch (type) { + case IRQ_TYPE_NONE: + printk(KERN_WARNING "No edge setting!\n"); + break; + + case IRQ_TYPE_EDGE_RISING: + newvalue = S3C2410_EXTINT_RISEEDGE; + break; + + case IRQ_TYPE_EDGE_FALLING: + newvalue = S3C2410_EXTINT_FALLEDGE; + break; + + case IRQ_TYPE_EDGE_BOTH: + newvalue = S3C2410_EXTINT_BOTHEDGE; + break; + + case IRQ_TYPE_LEVEL_LOW: + newvalue = S3C2410_EXTINT_LOWLEV; + break; + + case IRQ_TYPE_LEVEL_HIGH: + newvalue = S3C2410_EXTINT_HILEV; + break; + + default: + printk(KERN_ERR "No such irq type %d", type); + return -1; + } + + shift = (offs / 2) * 4; + mask = 0x7 << shift; + + ctrl = __raw_readl(reg); + ctrl &= ~mask; + ctrl |= newvalue << shift; + __raw_writel(ctrl, reg); + + return 0; +} + +static struct irq_chip s3c_irq_eint = { + .name = "s3c-eint", + .mask = s3c_irq_eint_mask, + .unmask = s3c_irq_eint_unmask, + .mask_ack = s3c_irq_eint_maskack, + .ack = s3c_irq_eint_ack, + .set_type = s3c_irq_eint_set_type, +}; + +/* s3c_irq_demux_eint + * + * This function demuxes the IRQ from the group0 external interrupts, + * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into + * the specific handlers s3c_irq_demux_eintX_Y. + */ +static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end) +{ + u32 status = __raw_readl(S3C64XX_EINT0PEND); + u32 mask = __raw_readl(S3C64XX_EINT0MASK); + unsigned int irq; + + status &= ~mask; + status >>= start; + status &= (1 << (end - start + 1)) - 1; + + for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) { + if (status & 1) + generic_handle_irq(irq); + + status >>= 1; + } +} + +static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(0, 3); +} + +static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(4, 11); +} + +static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(12, 19); +} + +static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(20, 27); +} + +int __init s3c64xx_init_irq_eint(void) +{ + int irq; + + for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) { + set_irq_chip(irq, &s3c_irq_eint); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3); + set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11); + set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19); + set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27); + + return 0; +} + +arch_initcall(s3c64xx_init_irq_eint); diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c new file mode 100644 index 000000000000..a94f1d5e819d --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq.c @@ -0,0 +1,257 @@ +/* arch/arm/plat-s3c64xx/irq.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/hardware/vic.h> + +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/cpu.h> + +/* Timer interrupt handling */ + +static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq) +{ + generic_handle_irq(sub_irq); +} + +static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER0); +} + +static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER1); +} + +static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER2); +} + +static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER3); +} + +static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER4); +} + +/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ + +static void s3c_irq_timer_mask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg &= ~(1 << (irq - IRQ_TIMER0)); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_unmask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg |= 1 << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_ack(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; + reg |= (1 << 5) << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static struct irq_chip s3c_irq_timer = { + .name = "s3c-timer", + .mask = s3c_irq_timer_mask, + .unmask = s3c_irq_timer_unmask, + .ack = s3c_irq_timer_ack, +}; + +struct uart_irq { + void __iomem *regs; + unsigned int base_irq; + unsigned int parent_irq; +}; + +/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] + * are consecutive when looking up the interrupt in the demux routines. + */ +static struct uart_irq uart_irqs[] = { + [0] = { + .regs = S3C_VA_UART0, + .base_irq = IRQ_S3CUART_BASE0, + .parent_irq = IRQ_UART0, + }, + [1] = { + .regs = S3C_VA_UART1, + .base_irq = IRQ_S3CUART_BASE1, + .parent_irq = IRQ_UART1, + }, + [2] = { + .regs = S3C_VA_UART2, + .base_irq = IRQ_S3CUART_BASE2, + .parent_irq = IRQ_UART2, + }, + [3] = { + .regs = S3C_VA_UART3, + .base_irq = IRQ_S3CUART_BASE3, + .parent_irq = IRQ_UART3, + }, +}; + +static inline void __iomem *s3c_irq_uart_base(unsigned int irq) +{ + struct uart_irq *uirq = get_irq_chip_data(irq); + return uirq->regs; +} + +static inline unsigned int s3c_irq_uart_bit(unsigned int irq) +{ + return irq & 3; +} + +/* UART interrupt registers, not worth adding to seperate include header */ +#define S3C64XX_UINTP 0x30 +#define S3C64XX_UINTSP 0x34 +#define S3C64XX_UINTM 0x38 + +static void s3c_irq_uart_mask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_maskack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_uart_unmask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg &= ~(1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_ack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) +{ + struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0]; + u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); + int base = uirq->base_irq; + + if (pend & (1 << 0)) + generic_handle_irq(base); + if (pend & (1 << 1)) + generic_handle_irq(base + 1); + if (pend & (1 << 2)) + generic_handle_irq(base + 2); + if (pend & (1 << 3)) + generic_handle_irq(base + 3); +} + +static struct irq_chip s3c_irq_uart = { + .name = "s3c-uart", + .mask = s3c_irq_uart_mask, + .unmask = s3c_irq_uart_unmask, + .mask_ack = s3c_irq_uart_maskack, + .ack = s3c_irq_uart_ack, +}; + +static void __init s3c64xx_uart_irq(struct uart_irq *uirq) +{ + void *reg_base = uirq->regs; + unsigned int irq; + int offs; + + /* mask all interrupts at the start. */ + __raw_writel(0xf, reg_base + S3C64XX_UINTM); + + for (offs = 0; offs < 3; offs++) { + irq = uirq->base_irq + offs; + + set_irq_chip(irq, &s3c_irq_uart); + set_irq_chip_data(irq, uirq); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); +} + +void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) +{ + int uart, irq; + + printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); + + /* initialise the pair of VICs */ + vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); + vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); + + /* add the timer sub-irqs */ + + set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0); + set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1); + set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2); + set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3); + set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4); + + for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) { + set_irq_chip(irq, &s3c_irq_timer); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++) + s3c64xx_uart_irq(&uart_irqs[uart]); +} + + diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c new file mode 100644 index 000000000000..8d9a0cada668 --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -0,0 +1,655 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 based common clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/cpu-freq.h> + +#include <plat/regs-clock.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> + +/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call + * ext_xtal_mux for want of an actual name from the manual. +*/ + +struct clk clk_ext_xtal_mux = { + .name = "ext_xtal", + .id = -1, +}; + +#define clk_fin_apll clk_ext_xtal_mux +#define clk_fin_mpll clk_ext_xtal_mux +#define clk_fin_epll clk_ext_xtal_mux + +#define clk_fout_mpll clk_mpll + +struct clk_sources { + unsigned int nr_sources; + struct clk **sources; +}; + +struct clksrc_clk { + struct clk clk; + unsigned int mask; + unsigned int shift; + + struct clk_sources *sources; + + unsigned int divider_shift; + void __iomem *reg_divider; +}; + +struct clk clk_fout_apll = { + .name = "fout_apll", + .id = -1, +}; + +static struct clk *clk_src_apll_list[] = { + [0] = &clk_fin_apll, + [1] = &clk_fout_apll, +}; + +static struct clk_sources clk_src_apll = { + .sources = clk_src_apll_list, + .nr_sources = ARRAY_SIZE(clk_src_apll_list), +}; + +struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_APLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_APLL_MOUT, + .sources = &clk_src_apll, +}; + +struct clk clk_fout_epll = { + .name = "fout_epll", + .id = -1, +}; + +static struct clk *clk_src_epll_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_fout_epll, +}; + +static struct clk_sources clk_src_epll = { + .sources = clk_src_epll_list, + .nr_sources = ARRAY_SIZE(clk_src_epll_list), +}; + +struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_EPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_EPLL_MOUT, + .sources = &clk_src_epll, +}; + +static struct clk *clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_fout_mpll, +}; + +static struct clk_sources clk_src_mpll = { + .sources = clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_list), +}; + +struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_MPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_MPLL_MOUT, + .sources = &clk_src_mpll, +}; + +static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + + printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate); + + if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK) + rate /= 2; + + return rate; +} + +struct clk clk_dout_mpll = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + .get_rate = s3c64xx_clk_doutmpll_get_rate, +}; + +static struct clk *clkset_spi_mmc_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_27m, +}; + +static struct clk_sources clkset_spi_mmc = { + .sources = clkset_spi_mmc_list, + .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list), +}; + +static struct clk *clkset_irda_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + &clk_27m, +}; + +static struct clk_sources clkset_irda = { + .sources = clkset_irda_list, + .nr_sources = ARRAY_SIZE(clkset_irda_list), +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + NULL +}; + +static struct clk_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_uhost_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_48m, +}; + +static struct clk_sources clkset_uhost = { + .sources = clkset_uhost_list, + .nr_sources = ARRAY_SIZE(clkset_uhost_list), +}; + + +/* The peripheral clocks are all controlled via clocksource followed + * by an optional divider and gate stage. We currently roll this into + * one clock which hides the intermediate clock from the mux. + * + * Note, the JPEG clock can only be an even divider... + * + * The scaler and LCD clocks depend on the S3C64XX version, and also + * have a common parent divisor so are not included here. + */ + +static inline struct clksrc_clk *to_clksrc(struct clk *clk) +{ + return container_of(clk, struct clksrc_clk, clk); +} + +static unsigned long s3c64xx_getrate_clksrc(struct clk *clk) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv = __raw_readl(sclk->reg_divider); + + clkdiv >>= sclk->divider_shift; + clkdiv &= 0xf; + clkdiv++; + + rate /= clkdiv; + return rate; +} + +static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + void __iomem *reg = sclk->reg_divider; + unsigned int div; + u32 val; + + rate = clk_round_rate(clk, rate); + div = clk_get_rate(clk->parent) / rate; + + val = __raw_readl(reg); + val &= ~sclk->mask; + val |= (rate - 1) << sclk->shift; + __raw_writel(val, reg); + + return 0; +} + +static int s3c64xx_setparent_clksrc(struct clk *clk, struct clk *parent) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + struct clk_sources *srcs = sclk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + int src_nr = -1; + int ptr; + + for (ptr = 0; ptr < srcs->nr_sources; ptr++) + if (srcs->sources[ptr] == parent) { + src_nr = ptr; + break; + } + + if (src_nr >= 0) { + clksrc &= ~sclk->mask; + clksrc |= src_nr << sclk->shift; + + __raw_writel(clksrc, S3C_CLK_SRC); + return 0; + } + + return -EINVAL; +} + +static unsigned long s3c64xx_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + rate = parent_rate; + else { + div = rate / parent_rate; + + if (div == 0) + div = 1; + if (div > 16) + div = 16; + + rate = parent_rate / div; + } + + return rate; +} + +static struct clksrc_clk clk_mmc0 = { + .clk = { + .name = "mmc_bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_MMC0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC0_SHIFT, + .mask = S3C6400_CLKSRC_MMC0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC0_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc1 = { + .clk = { + .name = "mmc_bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_MMC1, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC1_SHIFT, + .mask = S3C6400_CLKSRC_MMC1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC1_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc2 = { + .clk = { + .name = "mmc_bus", + .id = 2, + .ctrlbit = S3C_CLKCON_SCLK_MMC2, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC2_SHIFT, + .mask = S3C6400_CLKSRC_MMC2_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC2_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_usbhost = { + .clk = { + .name = "usb-host-bus", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UHOST_SHIFT, + .mask = S3C6400_CLKSRC_UHOST_MASK, + .sources = &clkset_uhost, + .divider_shift = S3C6400_CLKDIV1_UHOST_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_uart_uclk1 = { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UART, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UART_SHIFT, + .mask = S3C6400_CLKSRC_UART_MASK, + .sources = &clkset_uart, + .divider_shift = S3C6400_CLKDIV2_UART_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Where does UCLK0 come from? */ + +static struct clksrc_clk clk_spi0 = { + .clk = { + .name = "spi-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_SPI0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI0_SHIFT, + .mask = S3C6400_CLKSRC_SPI0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_spi1 = { + .clk = { + .name = "spi-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_SPI1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI1_SHIFT, + .mask = S3C6400_CLKSRC_SPI1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk clk_iis_cd0 = { + .name = "iis_cdclk0", + .id = -1, +}; + +static struct clk clk_iis_cd1 = { + .name = "iis_cdclk1", + .id = -1, +}; + +static struct clk clk_pcm_cd = { + .name = "pcm_cdclk", + .id = -1, +}; + +static struct clk *clkset_audio0_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd0, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio0 = { + .sources = clkset_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_audio0_list), +}; + +static struct clksrc_clk clk_audio0 = { + .clk = { + .name = "audio-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO0_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO0_MASK, + .sources = &clkset_audio0, + .divider_shift = S3C6400_CLKDIV2_AUDIO0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk *clkset_audio1_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd1, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio1 = { + .sources = clkset_audio1_list, + .nr_sources = ARRAY_SIZE(clkset_audio1_list), +}; + +static struct clksrc_clk clk_audio1 = { + .clk = { + .name = "audio-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO1_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO1_MASK, + .sources = &clkset_audio1, + .divider_shift = S3C6400_CLKDIV2_AUDIO1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_irda = { + .clk = { + .name = "irda-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_IRDA, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_IRDA_SHIFT, + .mask = S3C6400_CLKSRC_IRDA_MASK, + .sources = &clkset_irda, + .divider_shift = S3C6400_CLKDIV2_IRDA_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Clock initialisation code */ + +static struct clksrc_clk *init_parents[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_mmc0, + &clk_mmc1, + &clk_mmc2, + &clk_usbhost, + &clk_uart_uclk1, + &clk_spi0, + &clk_spi1, + &clk_audio0, + &clk_audio1, + &clk_irda, +}; + +static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk) +{ + struct clk_sources *srcs = clk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + + clksrc &= clk->mask; + clksrc >>= clk->shift; + + if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) { + printk(KERN_ERR "%s: bad source %d\n", + clk->clk.name, clksrc); + return; + } + + clk->clk.parent = srcs->sources[clksrc]; + + printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n", + clk->clk.name, clk->clk.parent->name, clksrc, + clk_get_rate(&clk->clk)); +} + +#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) + +void __init_or_cpufreq s3c6400_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk2; + unsigned long pclk; + unsigned long epll; + unsigned long apll; + unsigned long mpll; + unsigned int ptr; + u32 clkdiv0; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + clkdiv0 = __raw_readl(S3C_CLK_DIV0); + printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + epll = s3c6400_get_epll(xtal); + mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON)); + apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON)); + + fclk = mpll; + + printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n", + apll, mpll, epll); + + hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2); + hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK); + pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK); + + printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n", + hclk2, hclk, pclk); + + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_apll.rate = apll; + + clk_h.rate = hclk; + clk_p.rate = pclk; + clk_f.rate = fclk; + + for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) + s3c6400_set_clksrc(init_parents[ptr]); +} + +static struct clk *clks[] __initdata = { + &clk_ext_xtal_mux, + &clk_iis_cd0, + &clk_iis_cd1, + &clk_pcm_cd, + &clk_mout_epll.clk, + &clk_fout_epll, + &clk_mout_mpll.clk, + &clk_dout_mpll, + &clk_mmc0.clk, + &clk_mmc1.clk, + &clk_mmc2.clk, + &clk_usbhost.clk, + &clk_uart_uclk1.clk, + &clk_spi0.clk, + &clk_spi1.clk, + &clk_audio0.clk, + &clk_audio1.clk, + &clk_irda.clk, +}; + +void __init s3c6400_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clk_mpll.parent = &clk_mout_mpll.clk; + clk_epll.parent = &clk_mout_epll.clk; +} diff --git a/arch/arm/plat-s3c64xx/s3c6400-init.c b/arch/arm/plat-s3c64xx/s3c6400-init.c new file mode 100644 index 000000000000..6c28f39df097 --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-init.c @@ -0,0 +1,29 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-init.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - CPU initialisation (common with other S3C64XX chips) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* uart registration process */ + +void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no); +} diff --git a/arch/arm/plat-s3c64xx/setup-fb-24bpp.c b/arch/arm/plat-s3c64xx/setup-fb-24bpp.c new file mode 100644 index 000000000000..8e28e448dd20 --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-fb-24bpp.c @@ -0,0 +1,37 @@ +/* linux/arch/arm/plat-s3c64xx/setup-fb-24bpp.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX setup information for 24bpp LCD framebuffer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/fb.h> + +#include <mach/regs-fb.h> +#include <mach/gpio.h> +#include <plat/fb.h> +#include <plat/gpio-cfg.h> + +extern void s3c64xx_fb_gpio_setup_24bpp(void) +{ + unsigned int gpio; + + for (gpio = S3C64XX_GPI(0); gpio <= S3C64XX_GPI(15); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } +} diff --git a/arch/arm/plat-s3c64xx/setup-i2c0.c b/arch/arm/plat-s3c64xx/setup-i2c0.c new file mode 100644 index 000000000000..364480763728 --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-i2c0.c @@ -0,0 +1,31 @@ +/* linux/arch/arm/plat-s3c64xx/setup-i2c0.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX I2C bus 0 gpio configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> + +struct platform_device; /* don't need the contents */ + +#include <mach/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-bank-b.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S3C64XX_GPB(5), S3C64XX_GPB5_I2C_SCL0); + s3c_gpio_cfgpin(S3C64XX_GPB(6), S3C64XX_GPB6_I2C_SDA0); + s3c_gpio_setpull(S3C64XX_GPB(5), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPB(6), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/plat-s3c64xx/setup-i2c1.c b/arch/arm/plat-s3c64xx/setup-i2c1.c new file mode 100644 index 000000000000..bbe229bd90ca --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-i2c1.c @@ -0,0 +1,31 @@ +/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX I2C bus 1 gpio configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> + +struct platform_device; /* don't need the contents */ + +#include <mach/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-bank-b.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S3C64XX_GPB(2), S3C64XX_GPB2_I2C_SCL1); + s3c_gpio_cfgpin(S3C64XX_GPB(3), S3C64XX_GPB3_I2C_SDA1); + s3c_gpio_setpull(S3C64XX_GPB(2), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPB(3), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 43aa2020f85c..fd23c0e9e698 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Thu Sep 25 10:10:50 2008 +# Last update: Sun Nov 30 16:39:36 2008 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1380,7 +1380,7 @@ holon MACH_HOLON HOLON 1377 olip8 MACH_OLIP8 OLIP8 1378 ghi270hg MACH_GHI270HG GHI270HG 1379 davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380 -davinci_dm355_evm MACH_DAVINCI_DM350_EVM DAVINCI_DM350_EVM 1381 +davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381 blackriver MACH_BLACKRIVER BLACKRIVER 1383 sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384 cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385 @@ -1771,7 +1771,7 @@ axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 davinci_da8xx_evm MACH_DAVINCI_DA8XX_EVM DAVINCI_DA8XX_EVM 1781 ep9302 MACH_EP9302 EP9302 1782 -at572d940hfeb MACH_AT572D940HFEB AT572D940HFEB 1783 +at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 cybook3 MACH_CYBOOK3 CYBOOK3 1784 wdg002 MACH_WDG002 WDG002 1785 sg560adsl MACH_SG560ADSL SG560ADSL 1786 @@ -1899,3 +1899,98 @@ rut100 MACH_RUT100 RUT100 1908 asusp535 MACH_ASUSP535 ASUSP535 1909 htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910 sygdg1 MACH_SYGDG1 SYGDG1 1911 +sygdg2 MACH_SYGDG2 SYGDG2 1912 +seoul MACH_SEOUL SEOUL 1913 +salerno MACH_SALERNO SALERNO 1914 +ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915 +msm7201a MACH_MSM7201A MSM7201A 1916 +lpr1 MACH_LPR1 LPR1 1917 +armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918 +g3evm MACH_G3EVM G3EVM 1919 +z3_dm355 MACH_Z3_DM355 Z3_DM355 1920 +w90p910evb MACH_W90P910EVB W90P910EVB 1921 +w90p920evb MACH_W90P920EVB W90P920EVB 1922 +w90p950evb MACH_W90P950EVB W90P950EVB 1923 +w90n960evb MACH_W90N960EVB W90N960EVB 1924 +camhd MACH_CAMHD CAMHD 1925 +mvc100 MACH_MVC100 MVC100 1926 +electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927 +htcjade MACH_HTCJADE HTCJADE 1928 +memphis MACH_MEMPHIS MEMPHIS 1929 +imx27sbc MACH_IMX27SBC IMX27SBC 1930 +lextar MACH_LEXTAR LEXTAR 1931 +mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932 +ncp MACH_NCP NCP 1933 +z32an_series MACH_Z32AN Z32AN 1934 +tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935 +omap3_wl MACH_OMAP3_WL OMAP3_WL 1936 +chumby MACH_CHUMBY CHUMBY 1937 +atsarm9 MACH_ATSARM9 ATSARM9 1938 +davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939 +bahamas MACH_BAHAMAS BAHAMAS 1940 +das MACH_DAS DAS 1941 +minidas MACH_MINIDAS MINIDAS 1942 +vk1000 MACH_VK1000 VK1000 1943 +centro MACH_CENTRO CENTRO 1944 +ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945 +edgeconnect MACH_EDGECONNECT EDGECONNECT 1946 +nd27000 MACH_ND27000 ND27000 1947 +cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948 +ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949 +pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950 +blackstone MACH_BLACKSTONE BLACKSTONE 1951 +topaz MACH_TOPAZ TOPAZ 1952 +aixle MACH_AIXLE AIXLE 1953 +mw998 MACH_MW998 MW998 1954 +nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955 +vsc5605ev MACH_VSC5605EV VSC5605EV 1956 +nt98700dk MACH_NT98700DK NT98700DK 1957 +icontact MACH_ICONTACT ICONTACT 1958 +swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959 +swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960 +bbox_p16 MACH_BBOX_P16 BBOX_P16 1961 +bstd MACH_BSTD BSTD 1962 +sbc2440ii MACH_SBC2440II SBC2440II 1963 +pcm034 MACH_PCM034 PCM034 1964 +neso MACH_NESO NESO 1965 +wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966 +omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967 +totemnova MACH_TOTEMNOVA TOTEMNOVA 1968 +c5000 MACH_C5000 C5000 1969 +unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970 +ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 +arm11 MACH_ARM11 ARM11 1972 +cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 +cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 +cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 +cheflux MACH_CHEFLUX CHEFLUX 1976 +eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 +opcotec MACH_OPCOTEC OPCOTEC 1978 +yt MACH_YT YT 1979 +motoq MACH_MOTOQ MOTOQ 1980 +bsb1 MACH_BSB1 BSB1 1981 +acs5k MACH_ACS5K ACS5K 1982 +milan MACH_MILAN MILAN 1983 +quartzv2 MACH_QUARTZV2 QUARTZV2 1984 +rsvp MACH_RSVP RSVP 1985 +rmp200 MACH_RMP200 RMP200 1986 +snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987 +dsm320 MACH_DSM320 DSM320 1988 +adsgcm MACH_ADSGCM ADSGCM 1989 +ase2_400 MACH_ASE2_400 ASE2_400 1990 +pizza MACH_PIZZA PIZZA 1991 +spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992 +armata MACH_ARMATA ARMATA 1993 +exeda MACH_EXEDA EXEDA 1994 +mx31sf005 MACH_MX31SF005 MX31SF005 1995 +f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996 +q2440 MACH_Q2440 Q2440 1997 +qq2440 MACH_QQ2440 QQ2440 1998 +mini2440 MACH_MINI2440 MINI2440 1999 +colibri300 MACH_COLIBRI300 COLIBRI300 2000 +jades MACH_JADES JADES 2001 +spark MACH_SPARK SPARK 2002 +benzina MACH_BENZINA BENZINA 2003 +blaze MACH_BLAZE BLAZE 2004 +linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 +htcvenus MACH_HTCVENUS HTCVENUS 2006 diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index c85860bad585..8de86e4feada 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -377,6 +377,6 @@ struct op { u32 flags; }; -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PM) extern void vfp_save_state(void *location, u32 fpexc); #endif diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index a62dcf7098ba..c92a08bd6a86 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -101,9 +101,12 @@ ENTRY(vfp_support_entry) VFPFSTMIA r4, r5 @ save the working registers VFPFMRX r5, FPSCR @ current status tst r1, #FPEXC_EX @ is there additional state to save? - VFPFMRX r6, FPINST, NE @ FPINST (only if FPEXC.EX is set) - tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? - VFPFMRX r8, FPINST2, NE @ FPINST2 if needed (and present) + beq 1f + VFPFMRX r6, FPINST @ FPINST (only if FPEXC.EX is set) + tst r1, #FPEXC_FP2V @ is there an FPINST2 to read? + beq 1f + VFPFMRX r8, FPINST2 @ FPINST2 if needed (and present) +1: stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 @ and point r4 at the word at the @ start of the register dump @@ -117,9 +120,12 @@ no_old_VFP_process: @ FPEXC is in a safe state ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 tst r1, #FPEXC_EX @ is there additional state to restore? - VFPFMXR FPINST, r6, NE @ restore FPINST (only if FPEXC.EX is set) - tstne r1, #FPEXC_FP2V @ is there an FPINST2 to write? - VFPFMXR FPINST2, r8, NE @ FPINST2 if needed (and present) + beq 1f + VFPFMXR FPINST, r6 @ restore FPINST (only if FPEXC.EX is set) + tst r1, #FPEXC_FP2V @ is there an FPINST2 to write? + beq 1f + VFPFMXR FPINST2, r8 @ FPINST2 if needed (and present) +1: VFPFMXR FPSCR, r5 @ restore status check_for_exception: @@ -166,7 +172,7 @@ process_exception: @ retry the faulted instruction ENDPROC(vfp_support_entry) -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PM) ENTRY(vfp_save_state) @ Save the current VFP state @ r0 - save location @@ -175,9 +181,12 @@ ENTRY(vfp_save_state) VFPFSTMIA r0, r2 @ save the working registers VFPFMRX r2, FPSCR @ current status tst r1, #FPEXC_EX @ is there additional state to save? - VFPFMRX r3, FPINST, NE @ FPINST (only if FPEXC.EX is set) - tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? - VFPFMRX r12, FPINST2, NE @ FPINST2 if needed (and present) + beq 1f + VFPFMRX r3, FPINST @ FPINST (only if FPEXC.EX is set) + tst r1, #FPEXC_FP2V @ is there an FPINST2 to read? + beq 1f + VFPFMRX r12, FPINST2 @ FPINST2 if needed (and present) +1: stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 mov pc, lr ENDPROC(vfp_save_state) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index c0d2c9bb952b..9f476a1be2ca 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -322,6 +322,61 @@ static void vfp_enable(void *unused) set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); } +#ifdef CONFIG_PM +#include <linux/sysdev.h> + +static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state) +{ + struct thread_info *ti = current_thread_info(); + u32 fpexc = fmrx(FPEXC); + + /* if vfp is on, then save state for resumption */ + if (fpexc & FPEXC_EN) { + printk(KERN_DEBUG "%s: saving vfp state\n", __func__); + vfp_save_state(&ti->vfpstate, fpexc); + + /* disable, just in case */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } + + /* clear any information we had about last context state */ + memset(last_VFP_context, 0, sizeof(last_VFP_context)); + + return 0; +} + +static int vfp_pm_resume(struct sys_device *dev) +{ + /* ensure we have access to the vfp */ + vfp_enable(NULL); + + /* and disable it to ensure the next usage restores the state */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + + return 0; +} + +static struct sysdev_class vfp_pm_sysclass = { + .name = "vfp", + .suspend = vfp_pm_suspend, + .resume = vfp_pm_resume, +}; + +static struct sys_device vfp_pm_sysdev = { + .cls = &vfp_pm_sysclass, +}; + +static void vfp_pm_init(void) +{ + sysdev_class_register(&vfp_pm_sysclass); + sysdev_register(&vfp_pm_sysdev); +} + + +#else +static inline void vfp_pm_init(void) { } +#endif /* CONFIG_PM */ + #include <linux/smp.h> /* @@ -365,12 +420,22 @@ static int __init vfp_init(void) vfp_vector = vfp_support_entry; thread_register_notifier(&vfp_notifier_block); + vfp_pm_init(); /* * We detected VFP, and the support code is * in place; report VFP support to userspace. */ elf_hwcap |= HWCAP_VFP; +#ifdef CONFIG_NEON + /* + * Check for the presence of the Advanced SIMD + * load/store instructions, integer and single + * precision floating point operations. + */ + if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) + elf_hwcap |= HWCAP_NEON; +#endif } return 0; } diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index f4e55be2eea9..afad9f5ac0ac 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -208,6 +208,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) break; case ERR_TYPE_KERNEL_PANIC: default: + WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ spin_unlock_irqrestore(&rtasd_log_lock, s); return; } @@ -227,6 +228,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) /* Check to see if we need to or have stopped logging */ if (fatal || !logging_enabled) { logging_enabled = 0; + WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ spin_unlock_irqrestore(&rtasd_log_lock, s); return; } @@ -249,11 +251,13 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) else rtas_log_start += 1; + WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ spin_unlock_irqrestore(&rtasd_log_lock, s); wake_up_interruptible(&rtas_log_wait); break; case ERR_TYPE_KERNEL_PANIC: default: + WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ spin_unlock_irqrestore(&rtasd_log_lock, s); return; } diff --git a/arch/s390/include/asm/kvm_virtio.h b/arch/s390/include/asm/kvm_virtio.h index c13568b9351c..0503936f101f 100644 --- a/arch/s390/include/asm/kvm_virtio.h +++ b/arch/s390/include/asm/kvm_virtio.h @@ -50,6 +50,10 @@ struct kvm_vqconfig { #define KVM_S390_VIRTIO_RESET 1 #define KVM_S390_VIRTIO_SET_STATUS 2 +/* The alignment to use between consumer and producer parts of vring. + * This is pagesize for historical reasons. */ +#define KVM_S390_VIRTIO_RING_ALIGN 4096 + #ifdef __KERNEL__ /* early virtio console setup */ #ifdef CONFIG_S390_GUEST diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index ef3635b52fc0..0767827540b1 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -263,7 +263,7 @@ int s390_enable_sie(void) /* lets check if we are allowed to replace the mm */ task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || - tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) { + tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) { task_unlock(tsk); return -EINVAL; } @@ -279,7 +279,7 @@ int s390_enable_sie(void) /* Now lets check again if something happened */ task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || - tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) { + tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) { mmput(mm); task_unlock(tsk); return -EINVAL; diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index e594559c8dba..0a94d9c9cde1 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -4,21 +4,116 @@ mainmenu "Linux/SPARC Kernel Configuration" +config SPARC + bool + default y + select HAVE_IDE + select HAVE_OPROFILE + select HAVE_ARCH_KGDB if !SMP || SPARC64 + select HAVE_ARCH_TRACEHOOK + select ARCH_WANT_OPTIONAL_GPIOLIB + select RTC_CLASS + select RTC_DRV_M48T59 + +# Identify this as a Sparc32 build +config SPARC32 + bool + default y if ARCH = "sparc" + help + SPARC is a family of RISC microprocessors designed and marketed by + Sun Microsystems, incorporated. They are very widely found in Sun + workstations and clones. This port covers the original 32-bit SPARC; + it is old and stable and usually considered one of the "big three" + along with the Intel and Alpha ports. The UltraLinux project + maintains both the SPARC32 and SPARC64 ports; its web page is + available at <http://www.ultralinux.org/>. + +config SPARC64 + bool + default y if ARCH = "sparc64" + select ARCH_SUPPORTS_MSI + select HAVE_FUNCTION_TRACER + select HAVE_KRETPROBES + select HAVE_KPROBES + select HAVE_LMB + select USE_GENERIC_SMP_HELPERS if SMP + select RTC_DRV_CMOS + select RTC_DRV_BQ4802 + select RTC_DRV_SUN4V + select RTC_DRV_STARFIRE + +config ARCH_DEFCONFIG + string + default "arch/sparc/configs/sparc32_defconfig" if SPARC32 + default "arch/sparc/configs/sparc64_defconfig" if SPARC64 + +# CONFIG_BITS can be used at source level to get 32/64 bits +config BITS + int + default 32 if SPARC32 + default 64 if SPARC64 + +config 64BIT + def_bool y if SPARC64 + +config GENERIC_TIME + bool + default y if SPARC64 + +config GENERIC_CMOS_UPDATE + bool + default y if SPARC64 + +config GENERIC_CLOCKEVENTS + bool + default y if SPARC64 + +config IOMMU_HELPER + bool + default y if SPARC64 + +config QUICKLIST + bool + default y if SPARC64 + +config STACKTRACE_SUPPORT + bool + default y if SPARC64 + +config LOCKDEP_SUPPORT + bool + default y if SPARC64 + +config HAVE_LATENCYTOP_SUPPORT + bool + default y if SPARC64 + +config AUDIT_ARCH + bool + default y + +config HAVE_SETUP_PER_CPU_AREA + def_bool y if SPARC64 + +config GENERIC_HARDIRQS_NO__DO_IRQ + bool + def_bool y if SPARC64 + config MMU bool default y config HIGHMEM bool - default y + default y if SPARC32 config ZONE_DMA bool - default y + default y if SPARC32 config GENERIC_ISA_DMA bool - default y + default y if SPARC32 config GENERIC_GPIO bool @@ -31,15 +126,11 @@ config ARCH_NO_VIRT_TO_BUS config OF def_bool y -config HZ - int - default 100 - source "init/Kconfig" source "kernel/Kconfig.freezer" -menu "General machine setup" +menu "Processor type and features" config SMP bool "Symmetric multi-processing support (does not work on sun4/sun4c)" @@ -64,82 +155,269 @@ config SMP If you don't know what to do here, say N. config NR_CPUS - int "Maximum number of CPUs (2-32)" - range 2 32 + int "Maximum number of CPUs" depends on SMP - default "32" + range 2 32 if SPARC32 + range 2 1024 if SPARC64 + default 32 if SPARC32 + default 64 if SPARC64 -config SPARC +source kernel/Kconfig.hz + +config RWSEM_GENERIC_SPINLOCK + bool + default y if SPARC32 + +config RWSEM_XCHGADD_ALGORITHM + bool + default y if SPARC64 + +config GENERIC_FIND_NEXT_BIT bool default y - select HAVE_IDE - select HAVE_OPROFILE - select HAVE_ARCH_KGDB if !SMP - select HAVE_ARCH_TRACEHOOK - select ARCH_WANT_OPTIONAL_GPIOLIB - select RTC_CLASS - select RTC_DRV_M48T59 -# Identify this as a Sparc32 build -config SPARC32 +config GENERIC_HWEIGHT + bool + default y if !ULTRA_HAS_POPULATION_COUNT + +config GENERIC_CALIBRATE_DELAY bool default y - help - SPARC is a family of RISC microprocessors designed and marketed by - Sun Microsystems, incorporated. They are very widely found in Sun - workstations and clones. This port covers the original 32-bit SPARC; - it is old and stable and usually considered one of the "big three" - along with the Intel and Alpha ports. The UltraLinux project - maintains both the SPARC32 and SPARC64 ports; its web page is - available at <http://www.ultralinux.org/>. -# Global things across all Sun machines. -config ISA +config ARCH_MAY_HAVE_PC_FDC bool - help - ISA is found on Espresso only and is not supported currently. - Say N + default y -config EISA +config ARCH_HAS_ILOG2_U32 bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + +config EMULATED_CMPXCHG + bool + default y if SPARC32 help - EISA is not supported. - Say N + Sparc32 does not have a CAS instruction like sparc64. cmpxchg() + is emulated, and therefore it is not completely atomic. -config MCA +# Makefile helpers +config SPARC32_SMP + bool + default y + depends on SPARC32 && SMP + +config SPARC64_SMP bool + default y + depends on SPARC64 && SMP + +choice + prompt "Kernel page size" if SPARC64 + default SPARC64_PAGE_SIZE_8KB + +config SPARC64_PAGE_SIZE_8KB + bool "8KB" help - MCA is not supported. - Say N + This lets you select the page size of the kernel. -config PCMCIA - tristate - ---help--- - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. + 8KB and 64KB work quite well, since SPARC ELF sections + provide for up to 64KB alignment. - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> - for location). Please also read the PCMCIA-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. + If you don't know what to do, choose 8KB. - To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. +config SPARC64_PAGE_SIZE_64KB + bool "64KB" -config SBUS +endchoice + +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + depends on SPARC64 && PROC_FS + default y + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via /proc/<pid>/seccomp, it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + If unsure, say Y. Only embedded should say N here. + +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs" + depends on SPARC64 && SMP + select HOTPLUG + help + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu/cpu#. + Say N if you want to disable CPU hotplug. + +config GENERIC_HARDIRQS bool + default y if SPARC64 + +source "kernel/time/Kconfig" + +if SPARC64 +source "drivers/cpufreq/Kconfig" + +config US3_FREQ + tristate "UltraSPARC-III CPU Frequency driver" + depends on CPU_FREQ + select CPU_FREQ_TABLE + help + This adds the CPUFreq driver for UltraSPARC-III processors. + + For details, take a look at <file:Documentation/cpu-freq>. + + If in doubt, say N. + +config US2E_FREQ + tristate "UltraSPARC-IIe CPU Frequency driver" + depends on CPU_FREQ + select CPU_FREQ_TABLE + help + This adds the CPUFreq driver for UltraSPARC-IIe processors. + + For details, take a look at <file:Documentation/cpu-freq>. + + If in doubt, say N. + +endif + +config US3_MC + tristate "UltraSPARC-III Memory Controller driver" + depends on SPARC64 default y + help + This adds a driver for the UltraSPARC-III memory controller. + Loading this driver allows exact mnemonic strings to be + printed in the event of a memory error, so that the faulty DIMM + on the motherboard can be matched to the error. -config SBUSCHAR + If in doubt, say Y, as this information can be very useful. + +# Global things across all Sun machines. +config GENERIC_LOCKBREAK bool default y + depends on SPARC64 && SMP && PREEMPT + +choice + prompt "SPARC64 Huge TLB Page Size" + depends on SPARC64 && HUGETLB_PAGE + default HUGETLB_PAGE_SIZE_4MB + +config HUGETLB_PAGE_SIZE_4MB + bool "4MB" + +config HUGETLB_PAGE_SIZE_512K + bool "512K" + +config HUGETLB_PAGE_SIZE_64K + depends on !SPARC64_PAGE_SIZE_64KB + bool "64K" + +endchoice + +config NUMA + bool "NUMA support" + depends on SPARC64 && SMP + +config NODES_SHIFT + int + default "4" + depends on NEED_MULTIPLE_NODES + +# Some NUMA nodes have memory ranges that span +# other nodes. Even though a pfn is valid and +# between a node's start and end pfns, it may not +# reside on that node. See memmap_init_zone() +# for details. +config NODES_SPAN_OTHER_NODES + def_bool y + depends on NEED_MULTIPLE_NODES + +config ARCH_POPULATES_NODE_MAP + def_bool y if SPARC64 + +config ARCH_SELECT_MEMORY_MODEL + def_bool y if SPARC64 + +config ARCH_SPARSEMEM_ENABLE + def_bool y if SPARC64 + select SPARSEMEM_VMEMMAP_ENABLE + +config ARCH_SPARSEMEM_DEFAULT + def_bool y if SPARC64 + +source "mm/Kconfig" + +config SCHED_SMT + bool "SMT (Hyperthreading) scheduler support" + depends on SPARC64 && SMP + default y + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with SPARC cpus at a cost of slightly increased overhead + in some places. If unsure say N here. + +config SCHED_MC + bool "Multi-core scheduler support" + depends on SPARC64 && SMP + default y + help + Multi-core scheduler support improves the CPU scheduler's decision + making when dealing with multi-core CPU chips at a cost of slightly + increased overhead in some places. If unsure say N here. + +if SPARC64 +source "kernel/Kconfig.preempt" +endif + +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" + depends on SPARC64 + +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttyS0,9600 root=/dev/sda1" + help + Say Y here if you want to be able to pass default arguments to + the kernel. This will be overridden by the bootloader, if you + use one (such as SILO). This is most useful if you want to boot + a kernel from TFTP, and want default options to be available + with having them passed on the command line. + + NOTE: This option WILL override the PROM bootargs setting! + +config SUN_PM + bool + default y if SPARC32 + help + Enable power management and CPU standby features on supported + SPARC platforms. + +config SPARC_LED + tristate "Sun4m LED driver" + depends on SPARC32 + help + This driver toggles the front-panel LED on sun4m systems + in a user-specifiable manner. Its state can be probed + by reading /proc/led and its blinking mode can be changed + via writes to /proc/led config SERIAL_CONSOLE bool + depends on SPARC32 default y ---help--- If you say Y here, it will be possible to use a serial port as the @@ -161,71 +439,66 @@ config SERIAL_CONSOLE If unsure, say N. -config SUN_AUXIO - bool - default y - -config SUN_IO - bool - default y - -config RWSEM_GENERIC_SPINLOCK - bool - default y +endmenu -config RWSEM_XCHGADD_ALGORITHM +menu "Bus options (PCI etc.)" +config ISA bool + help + ISA is found on Espresso only and is not supported currently. -config GENERIC_FIND_NEXT_BIT +config ISAPNP bool - default y + help + ISAPNP is not supported -config GENERIC_HWEIGHT +config EISA bool - default y + help + EISA is not supported. -config GENERIC_CALIBRATE_DELAY +config MCA bool - default y + help + MCA is not supported. -config ARCH_MAY_HAVE_PC_FDC +config SBUS bool default y -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -config EMULATED_CMPXCHG +config SBUSCHAR bool default y - help - Sparc32 does not have a CAS instruction like sparc64. cmpxchg() - is emulated, and therefore it is not completely atomic. -config SUN_PM - bool - default y +config SUN_LDOMS + bool "Sun Logical Domains support" + depends on SPARC64 help - Enable power management and CPU standby features on supported - SPARC platforms. + Say Y here is you want to support virtual devices via + Logical Domains. config PCI bool "Support for PCI and PS/2 keyboard/mouse" help + Find out whether your system includes a PCI bus. PCI is the name of + a bus system, i.e. the way the CPU talks to the other stuff inside + your box. If you say Y here, the kernel will include drivers and + infrastructure code to support PCI bus devices. + CONFIG_PCI is needed for all JavaStation's (including MrCoffee), CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC. All of these platforms are extremely obscure, so say N if unsure. +config PCI_DOMAINS + def_bool PCI if SPARC64 + config PCI_SYSCALL def_bool PCI source "drivers/pci/Kconfig" +source "drivers/pcmcia/Kconfig" + config SUN_OPENPROMFS tristate "Openprom tree appears in /proc/openprom" help @@ -239,17 +512,33 @@ config SUN_OPENPROMFS Only choose N if you know in advance that you will not need to modify OpenPROM settings on the running system. -config SPARC_LED - tristate "Sun4m LED driver" - help - This driver toggles the front-panel LED on sun4m systems - in a user-specifiable manner. Its state can be probed - by reading /proc/led and its blinking mode can be changed - via writes to /proc/led +# Makefile helpers +config SPARC32_PCI + bool + default y + depends on SPARC32 && PCI + +config SPARC64_PCI + bool + default y + depends on SPARC64 && PCI + +endmenu + +menu "Executable file formats" source "fs/Kconfig.binfmt" -source "mm/Kconfig" +config COMPAT + bool + depends on SPARC64 + default y + select COMPAT_BINFMT_ELF + +config SYSVIPC_COMPAT + bool + depends on COMPAT && SYSVIPC + default y endmenu @@ -259,40 +548,6 @@ source "drivers/Kconfig" source "drivers/sbus/char/Kconfig" -# This one must be before the filesystem configs. -DaveM - -menu "Unix98 PTY support" - -config UNIX98_PTYS - bool "Unix98 PTY support" - ---help--- - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/<number>. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - The entries in /dev/pts/ are created on the fly by a virtual - file system; therefore, if you say Y here you should say Y to - "/dev/pts file system for Unix98 PTYs" as well. - - If you want to say Y here, you need to have the C library glibc 2.1 - or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). - Read the instructions in <file:Documentation/Changes> pertaining to - pseudo terminals. It's safe to say N. - -endmenu - source "fs/Kconfig" source "arch/sparc/Kconfig.debug" diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 87dd496f15eb..b8a15e271bfa 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug @@ -15,4 +15,30 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config DEBUG_DCFLUSH + bool "D-cache flush debugging" + depends on SPARC64 && DEBUG_KERNEL + +config STACK_DEBUG + bool "Stack Overflow Detection Support" + +config DEBUG_PAGEALLOC + bool "Debug page memory allocations" + depends on SPARC64 && DEBUG_KERNEL && !HIBERNATION + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + +config MCOUNT + bool + depends on SPARC64 + depends on STACK_DEBUG || FUNCTION_TRACER + default y + +config FRAME_POINTER + bool + depends on MCOUNT + default y + endmenu diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 9592889a6fd0..2003ded054c2 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -2,18 +2,31 @@ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the -# Sparc. +# Sparc and sparc64. # -# Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +# Copyright (C) 1994,1996,1998 David S. Miller (davem@caip.rutgers.edu) +# Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) + +# We are not yet configured - so test on arch +ifeq ($(ARCH),sparc) + KBUILD_DEFCONFIG := sparc32_defconfig +else + KBUILD_DEFCONFIG := sparc64_defconfig +endif + +ifeq ($(CONFIG_SPARC32),y) +##### +# sparc32 # # # Uncomment the first KBUILD_CFLAGS if you are doing kgdb source level # debugging of the kernel to get the proper debugging information. -AS := $(AS) -32 -LDFLAGS := -m elf32_sparc -CHECKFLAGS += -D__sparc__ +AS := $(AS) -32 +LDFLAGS := -m elf32_sparc +CHECKFLAGS += -D__sparc__ +export BITS := 32 #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 @@ -25,38 +38,60 @@ CPPFLAGS_vmlinux.lds += -m32 # Actual linking is done with "make image". LDFLAGS_vmlinux = -r -head-y := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o -HEAD_Y := $(head-y) +# Default target +all: zImage + + +else +##### +# sparc64 +# -core-y += arch/sparc/kernel/ arch/sparc/mm/ arch/sparc/math-emu/ -libs-y += arch/sparc/prom/ arch/sparc/lib/ +CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 + +# Undefine sparc when processing vmlinux.lds - it is used +# And teach CPP we are doing 64 bit builds (for this case) +CPPFLAGS_vmlinux.lds += -m64 -Usparc +LDFLAGS := -m elf64_sparc +export BITS := 64 + +KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ + -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ + -Wa,--undeclared-regs +KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3) +KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs + +ifeq ($(CONFIG_MCOUNT),y) + KBUILD_CFLAGS += -pg +endif + +endif + +head-y := arch/sparc/kernel/head_$(BITS).o +head-y += arch/sparc/kernel/init_task.o + +core-y += arch/sparc/kernel/ +core-y += arch/sparc/mm/ arch/sparc/math-emu/ + +libs-y += arch/sparc/prom/ +libs-y += arch/sparc/lib/ drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ # Export what is needed by arch/sparc/boot/Makefile -# Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-) -INIT_Y := $(patsubst %/, %/built-in.o, $(init-y)) -CORE_Y := $(core-y) -CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ -CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y)) -DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y)) -NET_Y := $(patsubst %/, %/built-in.o, $(net-y)) -LIBS_Y1 := $(patsubst %/, %/lib.a, $(libs-y)) -LIBS_Y2 := $(patsubst %/, %/built-in.o, $(libs-y)) -LIBS_Y := $(LIBS_Y1) $(LIBS_Y2) +export VMLINUX_INIT VMLINUX_MAIN +VMLINUX_INIT := $(head-y) $(init-y) +VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y) +VMLINUX_MAIN += $(drivers-y) $(net-y) ifdef CONFIG_KALLSYMS -kallsyms.o := .tmp_kallsyms2.o +export kallsyms.o := .tmp_kallsyms2.o endif -export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y kallsyms.o - -# Default target -all: zImage - boot := arch/sparc/boot -image zImage tftpboot.img: vmlinux +image zImage tftpboot.img vmlinux.aout: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ archclean: @@ -65,11 +100,17 @@ archclean: # This is the image used for packaging KBUILD_IMAGE := $(boot)/zImage -CLEAN_FILES += arch/$(ARCH)/boot/System.map - # Don't use tabs in echo arguments. +ifeq ($(ARCH),sparc) define archhelp echo '* image - kernel image ($(boot)/image)' echo '* zImage - stripped kernel image ($(boot)/zImage)' echo ' tftpboot.img - image prepared for tftp' endef +else +define archhelp + echo '* vmlinux - Standard sparc64 kernel' + echo ' vmlinux.aout - a.out kernel for sparc64' + echo ' tftpboot.img - image prepared for tftp' +endef +endif diff --git a/arch/sparc64/boot/.gitignore b/arch/sparc/boot/.gitignore index 36356f9d498e..fc6f3986c76c 100644 --- a/arch/sparc64/boot/.gitignore +++ b/arch/sparc/boot/.gitignore @@ -1,4 +1,8 @@ +btfix.S +btfixupprep image +zImage tftpboot.img vmlinux.aout piggyback + diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 3e77a9f52248..96041a8d39e8 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -6,13 +6,16 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -hostprogs-y := piggyback btfixupprep -targets := tftpboot.img btfix.o btfix.S image +hostprogs-y := piggyback_32 piggyback_64 btfixupprep +targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout +clean-files := System.map quiet_cmd_elftoaout = ELFTOAOUT $@ cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ + +ifeq ($(CONFIG_SPARC32),y) quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG) + cmd_piggy = $(obj)/piggyback_32 $@ $(obj)/System.map $(ROOT_IMG) quiet_cmd_btfix = BTFIX $@ cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map @@ -37,8 +40,8 @@ define rule_image echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd endef -BTOBJS := $(HEAD_Y) $(INIT_Y) -BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y) +BTOBJS := $(patsubst %/, %/built-in.o, $(VMLINUX_INIT)) +BTLIBS := $(patsubst %/, %/built-in.o, $(VMLINUX_MAIN)) LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \ --start-group $(BTLIBS) --end-group \ $(kallsyms.o) $(obj)/btfix.o @@ -61,3 +64,28 @@ $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE $(call if_changed,btfix) + +endif + +ifeq ($(CONFIG_SPARC64),y) +quiet_cmd_piggy = PIGGY $@ + cmd_piggy = $(obj)/piggyback_64 $@ System.map $(ROOT_IMG) +quiet_cmd_strip = STRIP $@ + cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ + + +# Actual linking +$(obj)/image: vmlinux FORCE + $(call if_changed,strip) + @echo ' kernel: $@ is ready' + +$(obj)/tftpboot.img: vmlinux $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE + $(call if_changed,elftoaout) + $(call if_changed,piggy) + @echo ' kernel: $@ is ready' + +$(obj)/vmlinux.aout: vmlinux FORCE + $(call if_changed,elftoaout) + @echo ' kernel: $@ is ready' +endif + diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback_32.c index c9f500c1a8b2..c9f500c1a8b2 100644 --- a/arch/sparc/boot/piggyback.c +++ b/arch/sparc/boot/piggyback_32.c diff --git a/arch/sparc64/boot/piggyback.c b/arch/sparc/boot/piggyback_64.c index de364bfed0bb..de364bfed0bb 100644 --- a/arch/sparc64/boot/piggyback.c +++ b/arch/sparc/boot/piggyback_64.c diff --git a/arch/sparc/defconfig b/arch/sparc/configs/sparc32_defconfig index 2e3a149ea0e7..2e3a149ea0e7 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/configs/sparc32_defconfig diff --git a/arch/sparc64/defconfig b/arch/sparc/configs/sparc64_defconfig index 05d19a3e590f..05d19a3e590f 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc/configs/sparc64_defconfig diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 2d2769d766ec..89c260aab45c 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -15,8 +15,6 @@ header-y += signal_32.h header-y += signal_64.h header-y += stat_32.h header-y += stat_64.h -header-y += unistd_32.h -header-y += unistd_64.h header-y += apc.h header-y += asi.h diff --git a/arch/sparc/include/asm/asm.h b/arch/sparc/include/asm/asm.h new file mode 100644 index 000000000000..e8e1d94b4cc9 --- /dev/null +++ b/arch/sparc/include/asm/asm.h @@ -0,0 +1,40 @@ +#ifndef _SPARC_ASM_H +#define _SPARC_ASM_H + +/* Macros to assist the sharing of assembler code between 32-bit and + * 64-bit sparc. + */ + +#ifdef CONFIG_SPARC64 +#define BRANCH32(TYPE, PREDICT, DEST) \ + TYPE,PREDICT %icc, DEST +#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \ + TYPE,a,PREDICT %icc, DEST +#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \ + brz,PREDICT REG, DEST +#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \ + brz,a,PREDICT REG, DEST +#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \ + brnz,PREDICT REG, DEST +#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \ + brnz,a,PREDICT REG, DEST +#else +#define BRANCH32(TYPE, PREDICT, DEST) \ + TYPE DEST +#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \ + TYPE,a DEST +#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \ + cmp REG, 0; \ + be DEST +#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \ + cmp REG, 0; \ + be,a DEST +#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \ + cmp REG, 0; \ + bne DEST +#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \ + cmp REG, 0; \ + bne,a DEST +#endif + +#endif /* _SPARC_ASM_H */ diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index 2c71ec4a3b18..5982c5ae7f07 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -112,17 +112,10 @@ static inline int atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) /* Atomic operations are already serializing */ -#ifdef CONFIG_SMP -#define smp_mb__before_atomic_dec() membar_storeload_loadload(); -#define smp_mb__after_atomic_dec() membar_storeload_storestore(); -#define smp_mb__before_atomic_inc() membar_storeload_loadload(); -#define smp_mb__after_atomic_inc() membar_storeload_storestore(); -#else #define smp_mb__before_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier() #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#endif #include <asm-generic/atomic.h> #endif /* !(__ARCH_SPARC64_ATOMIC__) */ diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h index bb87b8080220..e72ac9cdfb98 100644 --- a/arch/sparc/include/asm/bitops_64.h +++ b/arch/sparc/include/asm/bitops_64.h @@ -23,13 +23,8 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr); #include <asm-generic/bitops/non-atomic.h> -#ifdef CONFIG_SMP -#define smp_mb__before_clear_bit() membar_storeload_loadload() -#define smp_mb__after_clear_bit() membar_storeload_storestore() -#else #define smp_mb__before_clear_bit() barrier() #define smp_mb__after_clear_bit() barrier() -#endif #include <asm-generic/bitops/ffz.h> #include <asm-generic/bitops/__ffs.h> diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h index 109ae24ba242..bafe5a631b6d 100644 --- a/arch/sparc/include/asm/hypervisor.h +++ b/arch/sparc/include/asm/hypervisor.h @@ -2713,6 +2713,30 @@ extern unsigned long sun4v_ldc_revoke(unsigned long channel, */ #define HV_FAST_SET_PERFREG 0x101 +#define HV_N2_PERF_SPARC_CTL 0x0 +#define HV_N2_PERF_DRAM_CTL0 0x1 +#define HV_N2_PERF_DRAM_CNT0 0x2 +#define HV_N2_PERF_DRAM_CTL1 0x3 +#define HV_N2_PERF_DRAM_CNT1 0x4 +#define HV_N2_PERF_DRAM_CTL2 0x5 +#define HV_N2_PERF_DRAM_CNT2 0x6 +#define HV_N2_PERF_DRAM_CTL3 0x7 +#define HV_N2_PERF_DRAM_CNT3 0x8 + +#define HV_FAST_N2_GET_PERFREG 0x104 +#define HV_FAST_N2_SET_PERFREG 0x105 + +#ifndef __ASSEMBLY__ +extern unsigned long sun4v_niagara_getperf(unsigned long reg, + unsigned long *val); +extern unsigned long sun4v_niagara_setperf(unsigned long reg, + unsigned long val); +extern unsigned long sun4v_niagara2_getperf(unsigned long reg, + unsigned long *val); +extern unsigned long sun4v_niagara2_setperf(unsigned long reg, + unsigned long val); +#endif + /* MMU statistics services. * * The hypervisor maintains MMU statistics and privileged code provides diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index fe205cc444b8..ea43057d4763 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h @@ -12,4 +12,5 @@ #define irq_canonicalize(irq) (irq) +extern void __init init_IRQ(void); #endif diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 71673eca3660..d47d4a1955a9 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -66,6 +66,9 @@ extern void virt_irq_free(unsigned int virt_irq); extern void __init init_IRQ(void); extern void fixup_irqs(void); +extern int register_perfctr_intr(void (*handler)(struct pt_regs *)); +extern void release_perfctr_intr(void (*handler)(struct pt_regs *)); + static inline void set_softint(unsigned long bits) { __asm__ __volatile__("wr %0, 0x0, %%set_softint" diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h index bb42e59162aa..8b49bf920df3 100644 --- a/arch/sparc/include/asm/irqflags_64.h +++ b/arch/sparc/include/asm/irqflags_64.h @@ -10,6 +10,8 @@ #ifndef _ASM_IRQFLAGS_H #define _ASM_IRQFLAGS_H +#include <asm/pil.h> + #ifndef __ASSEMBLY__ static inline unsigned long __raw_local_save_flags(void) @@ -40,9 +42,9 @@ static inline void raw_local_irq_restore(unsigned long flags) static inline void raw_local_irq_disable(void) { __asm__ __volatile__( - "wrpr 15, %%pil" + "wrpr %0, %%pil" : /* no outputs */ - : /* no inputs */ + : "i" (PIL_NORMAL_MAX) : "memory" ); } diff --git a/arch/sparc/include/asm/module.h b/arch/sparc/include/asm/module.h index e82cf9a3e60e..ff8e02d80334 100644 --- a/arch/sparc/include/asm/module.h +++ b/arch/sparc/include/asm/module.h @@ -1,8 +1,24 @@ -#ifndef ___ASM_SPARC_MODULE_H -#define ___ASM_SPARC_MODULE_H -#if defined(__sparc__) && defined(__arch64__) -#include <asm/module_64.h> -#else -#include <asm/module_32.h> -#endif -#endif +#ifndef __SPARC_MODULE_H +#define __SPARC_MODULE_H +struct mod_arch_specific { }; + +/* + * Use some preprocessor magic to define the correct symbol + * for sparc32 and sparc64. + * Elf_Addr becomes Elf32_Addr for sparc32 and Elf64_Addr for sparc64 + */ +#define ___ELF(a, b, c) a##b##c +#define __ELF(a, b, c) ___ELF(a, b, c) +#define _Elf(t) __ELF(Elf, CONFIG_BITS, t) +#define _ELF(t) __ELF(ELF, CONFIG_BITS, t) + +#define Elf_Shdr _Elf(_Shdr) +#define Elf_Sym _Elf(_Sym) +#define Elf_Ehdr _Elf(_Ehdr) +#define Elf_Rela _Elf(_Rela) +#define Elf_Addr _Elf(_Addr) + +#define ELF_R_SYM _ELF(_R_SYM) +#define ELF_R_TYPE _ELF(_R_TYPE) + +#endif /* __SPARC_MODULE_H */ diff --git a/arch/sparc/include/asm/module_32.h b/arch/sparc/include/asm/module_32.h deleted file mode 100644 index cbd9e67b0c0b..000000000000 --- a/arch/sparc/include/asm/module_32.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_SPARC_MODULE_H -#define _ASM_SPARC_MODULE_H -struct mod_arch_specific { }; -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr -#endif /* _ASM_SPARC_MODULE_H */ diff --git a/arch/sparc/include/asm/module_64.h b/arch/sparc/include/asm/module_64.h deleted file mode 100644 index 3d77ba465783..000000000000 --- a/arch/sparc/include/asm/module_64.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_SPARC64_MODULE_H -#define _ASM_SPARC64_MODULE_H -struct mod_arch_specific { }; -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Ehdr Elf64_Ehdr -#endif /* _ASM_SPARC64_MODULE_H */ diff --git a/arch/sparc/include/asm/openprom_32.h b/arch/sparc/include/asm/openprom_32.h index 8b1649f29ed9..875da3552d80 100644 --- a/arch/sparc/include/asm/openprom_32.h +++ b/arch/sparc/include/asm/openprom_32.h @@ -170,9 +170,9 @@ struct linux_romvec { struct linux_nodeops { int (*no_nextnode)(int node); int (*no_child)(int node); - int (*no_proplen)(int node, char *name); - int (*no_getprop)(int node, char *name, char *val); - int (*no_setprop)(int node, char *name, char *val, int len); + int (*no_proplen)(int node, const char *name); + int (*no_getprop)(int node, const char *name, char *val); + int (*no_setprop)(int node, const char *name, char *val, int len); char * (*no_nextprop)(int node, char *name); }; diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 699da05235c8..73d45521db04 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -136,7 +136,7 @@ extern char prom_getchar(void); extern void prom_putchar(char character); /* Prom's internal routines, don't use in kernel/boot code. */ -extern void prom_printf(char *fmt, ...); +extern void prom_printf(const char *fmt, ...); extern void prom_write(const char *buf, unsigned int len); /* Multiprocessor operations... */ @@ -199,12 +199,12 @@ extern int prom_getsibling(int node); /* Get the length, at the passed node, of the given property type. * Returns -1 on error (ie. no such property at this node). */ -extern int prom_getproplen(int thisnode, char *property); +extern int prom_getproplen(int thisnode, const char *property); /* Fetch the requested property using the given buffer. Returns * the number of bytes the prom put into your buffer or -1 on error. */ -extern int __must_check prom_getproperty(int thisnode, char *property, +extern int __must_check prom_getproperty(int thisnode, const char *property, char *prop_buffer, int propbuf_size); /* Acquire an integer property. */ @@ -246,7 +246,7 @@ extern int prom_node_has_property(int node, char *property); /* Set the indicated property at the given node with the passed value. * Returns the number of bytes of your value that the prom took. */ -extern int prom_setprop(int node, char *prop_name, char *prop_value, +extern int prom_setprop(int node, const char *prop_name, char *prop_value, int value_size); extern int prom_pathtoinode(char *path); diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index 71819bb943fc..d573820c0ff4 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h @@ -10,7 +10,12 @@ * * In fact any XCALL which has to etrap/rtrap has a problem because * it is difficult to prevent rtrap from running BH's, and that would - * need to be done if the XCALL arrived while %pil==15. + * need to be done if the XCALL arrived while %pil==PIL_NORMAL_MAX. + * + * Finally, in order to handle profiling events even when a + * local_irq_disable() is in progress, we only disable up to level 14 + * interrupts. Profile counter overflow interrupts arrive at level + * 15. */ #define PIL_SMP_CALL_FUNC 1 #define PIL_SMP_RECEIVE_SIGNAL 2 @@ -18,5 +23,7 @@ #define PIL_SMP_CTX_NEW_VERSION 4 #define PIL_DEVICE_IRQ 5 #define PIL_SMP_CALL_FUNC_SNGL 6 +#define PIL_NORMAL_MAX 14 +#define PIL_NMI 15 #endif /* !(_SPARC64_PIL_H) */ diff --git a/arch/sparc/include/asm/scatterlist.h b/arch/sparc/include/asm/scatterlist.h index ec21a4517641..e580f5581c88 100644 --- a/arch/sparc/include/asm/scatterlist.h +++ b/arch/sparc/include/asm/scatterlist.h @@ -1,8 +1,27 @@ -#ifndef ___ASM_SPARC_SCATTERLIST_H -#define ___ASM_SPARC_SCATTERLIST_H -#if defined(__sparc__) && defined(__arch64__) -#include <asm/scatterlist_64.h> -#else -#include <asm/scatterlist_32.h> -#endif +#ifndef _SPARC_SCATTERLIST_H +#define _SPARC_SCATTERLIST_H + +#include <asm/page.h> +#include <asm/types.h> + +struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; #endif + unsigned long page_link; + unsigned int offset; + + unsigned int length; + + dma_addr_t dma_address; + __u32 dma_length; +}; + +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->dma_length) + +#define ISA_DMA_THRESHOLD (~0UL) + +#define ARCH_HAS_SG_CHAIN + +#endif /* !(_SPARC_SCATTERLIST_H) */ diff --git a/arch/sparc/include/asm/scatterlist_32.h b/arch/sparc/include/asm/scatterlist_32.h deleted file mode 100644 index c82609ca1d0f..000000000000 --- a/arch/sparc/include/asm/scatterlist_32.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SPARC_SCATTERLIST_H -#define _SPARC_SCATTERLIST_H - -#include <linux/types.h> - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - unsigned int offset; - - unsigned int length; - - __u32 dvma_address; /* A place to hang host-specific addresses at. */ - __u32 dvma_length; -}; - -#define sg_dma_address(sg) ((sg)->dvma_address) -#define sg_dma_len(sg) ((sg)->dvma_length) - -#define ISA_DMA_THRESHOLD (~0UL) - -#define ARCH_HAS_SG_CHAIN - -#endif /* !(_SPARC_SCATTERLIST_H) */ diff --git a/arch/sparc/include/asm/scatterlist_64.h b/arch/sparc/include/asm/scatterlist_64.h deleted file mode 100644 index 81bd058f9382..000000000000 --- a/arch/sparc/include/asm/scatterlist_64.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _SPARC64_SCATTERLIST_H -#define _SPARC64_SCATTERLIST_H - -#include <asm/page.h> -#include <asm/types.h> - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - unsigned int offset; - - unsigned int length; - - dma_addr_t dma_address; - __u32 dma_length; -}; - -#define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->dma_length) - -#define ISA_DMA_THRESHOLD (~0UL) - -#define ARCH_HAS_SG_CHAIN - -#endif /* !(_SPARC64_SCATTERLIST_H) */ diff --git a/arch/sparc/include/asm/sections.h b/arch/sparc/include/asm/sections.h index c7c69b00967f..0b0553bbd8a0 100644 --- a/arch/sparc/include/asm/sections.h +++ b/arch/sparc/include/asm/sections.h @@ -1,8 +1,10 @@ -#ifndef ___ASM_SPARC_SECTIONS_H -#define ___ASM_SPARC_SECTIONS_H -#if defined(__sparc__) && defined(__arch64__) -#include <asm/sections_64.h> -#else -#include <asm/sections_32.h> -#endif +#ifndef __SPARC_SECTIONS_H +#define __SPARC_SECTIONS_H + +/* nothing to see, move along */ +#include <asm-generic/sections.h> + +/* sparc entry point */ +extern char _start[]; + #endif diff --git a/arch/sparc/include/asm/sections_32.h b/arch/sparc/include/asm/sections_32.h deleted file mode 100644 index 6832841df051..000000000000 --- a/arch/sparc/include/asm/sections_32.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SPARC_SECTIONS_H -#define _SPARC_SECTIONS_H - -#include <asm-generic/sections.h> - -#endif diff --git a/arch/sparc/include/asm/sections_64.h b/arch/sparc/include/asm/sections_64.h deleted file mode 100644 index 3f4b9fdc28d0..000000000000 --- a/arch/sparc/include/asm/sections_64.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _SPARC64_SECTIONS_H -#define _SPARC64_SECTIONS_H - -/* nothing to see, move along */ -#include <asm-generic/sections.h> - -extern char _start[]; - -#endif diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h index 120cfe4577c7..c4d274d330e9 100644 --- a/arch/sparc/include/asm/spinlock_64.h +++ b/arch/sparc/include/asm/spinlock_64.h @@ -13,17 +13,12 @@ * and rebuild your kernel. */ -/* All of these locking primitives are expected to work properly - * even in an RMO memory model, which currently is what the kernel - * runs in. - * - * There is another issue. Because we play games to save cycles - * in the non-contention case, we need to be extra careful about - * branch targets into the "spinning" code. They live in their - * own section, but the newer V9 branches have a shorter range - * than the traditional 32-bit sparc branch variants. The rule - * is that the branches that go into and out of the spinner sections - * must be pre-V9 branches. +/* Because we play games to save cycles in the non-contention case, we + * need to be extra careful about branch targets into the "spinning" + * code. They live in their own section, but the newer V9 branches + * have a shorter range than the traditional 32-bit sparc branch + * variants. The rule is that the branches that go into and out of + * the spinner sections must be pre-V9 branches. */ #define __raw_spin_is_locked(lp) ((lp)->lock != 0) @@ -38,12 +33,10 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) __asm__ __volatile__( "1: ldstub [%1], %0\n" -" membar #StoreLoad | #StoreStore\n" " brnz,pn %0, 2f\n" " nop\n" " .subsection 2\n" "2: ldub [%1], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 2b\n" " nop\n" " ba,a,pt %%xcc, 1b\n" @@ -59,7 +52,6 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) __asm__ __volatile__( " ldstub [%1], %0\n" -" membar #StoreLoad | #StoreStore" : "=r" (result) : "r" (lock) : "memory"); @@ -70,7 +62,6 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) static inline void __raw_spin_unlock(raw_spinlock_t *lock) { __asm__ __volatile__( -" membar #StoreStore | #LoadStore\n" " stb %%g0, [%0]" : /* No outputs */ : "r" (lock) @@ -83,14 +74,12 @@ static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long fla __asm__ __volatile__( "1: ldstub [%2], %0\n" -" membar #StoreLoad | #StoreStore\n" " brnz,pn %0, 2f\n" " nop\n" " .subsection 2\n" "2: rdpr %%pil, %1\n" " wrpr %3, %%pil\n" "3: ldub [%2], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 3b\n" " nop\n" " ba,pt %%xcc, 1b\n" @@ -113,12 +102,10 @@ static void inline __read_lock(raw_rwlock_t *lock) "4: add %0, 1, %1\n" " cas [%2], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" " nop\n" " .subsection 2\n" "2: ldsw [%2], %0\n" -" membar #LoadLoad\n" " brlz,pt %0, 2b\n" " nop\n" " ba,a,pt %%xcc, 4b\n" @@ -139,7 +126,6 @@ static int inline __read_trylock(raw_rwlock_t *lock) " add %0, 1, %1\n" " cas [%2], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" " mov 1, %0\n" "2:" @@ -155,7 +141,6 @@ static void inline __read_unlock(raw_rwlock_t *lock) unsigned long tmp1, tmp2; __asm__ __volatile__( -" membar #StoreLoad | #LoadLoad\n" "1: lduw [%2], %0\n" " sub %0, 1, %1\n" " cas [%2], %0, %1\n" @@ -179,12 +164,10 @@ static void inline __write_lock(raw_rwlock_t *lock) "4: or %0, %3, %1\n" " cas [%2], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" " nop\n" " .subsection 2\n" "2: lduw [%2], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 2b\n" " nop\n" " ba,a,pt %%xcc, 4b\n" @@ -197,7 +180,6 @@ static void inline __write_lock(raw_rwlock_t *lock) static void inline __write_unlock(raw_rwlock_t *lock) { __asm__ __volatile__( -" membar #LoadStore | #StoreStore\n" " stw %%g0, [%0]" : /* no outputs */ : "r" (lock) @@ -217,7 +199,6 @@ static int inline __write_trylock(raw_rwlock_t *lock) " or %0, %4, %1\n" " cas [%3], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" " nop\n" " mov 1, %2\n" diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h index 985ea7e31992..f0d0c40c44da 100644 --- a/arch/sparc/include/asm/spitfire.h +++ b/arch/sparc/include/asm/spitfire.h @@ -6,6 +6,8 @@ #ifndef _SPARC64_SPITFIRE_H #define _SPARC64_SPITFIRE_H +#ifdef CONFIG_SPARC64 + #include <asm/asi.h> /* The following register addresses are accessible via ASI_DMMU @@ -338,5 +340,5 @@ static inline void cheetah_put_itlb_data(int entry, unsigned long data) } #endif /* !(__ASSEMBLY__) */ - +#endif /* CONFIG_SPARC64 */ #endif /* !(_SPARC64_SPITFIRE_H) */ diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index 8623fc48fe24..79c1ae2b42a3 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h @@ -15,6 +15,11 @@ #include <linux/irqflags.h> +static inline unsigned int probe_irq_mask(unsigned long val) +{ + return 0; +} + /* * Sparc (general) CPU types */ diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index 8759f2a1b837..6c077816ab28 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h @@ -59,20 +59,9 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ : : : "memory"); \ } while (0) -#define mb() \ - membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad") -#define rmb() \ - membar_safe("#LoadLoad") -#define wmb() \ - membar_safe("#StoreStore") -#define membar_storeload() \ - membar_safe("#StoreLoad") -#define membar_storeload_storestore() \ - membar_safe("#StoreLoad | #StoreStore") -#define membar_storeload_loadload() \ - membar_safe("#StoreLoad | #LoadLoad") -#define membar_storestore_loadstore() \ - membar_safe("#StoreStore | #LoadStore") +#define mb() membar_safe("#StoreLoad") +#define rmb() __asm__ __volatile__("":::"memory") +#define wmb() __asm__ __volatile__("":::"memory") #endif @@ -80,20 +69,20 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ #define read_barrier_depends() do { } while(0) #define set_mb(__var, __value) \ - do { __var = __value; membar_storeload_storestore(); } while(0) + do { __var = __value; membar_safe("#StoreLoad"); } while(0) #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() #define smp_wmb() wmb() -#define smp_read_barrier_depends() read_barrier_depends() #else #define smp_mb() __asm__ __volatile__("":::"memory") #define smp_rmb() __asm__ __volatile__("":::"memory") #define smp_wmb() __asm__ __volatile__("":::"memory") -#define smp_read_barrier_depends() do { } while(0) #endif +#define smp_read_barrier_depends() do { } while(0) + #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") #define flushw_all() __asm__ __volatile__("flushw") @@ -107,11 +96,12 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt() * for more information. */ -#define reset_pic() \ - __asm__ __volatile__("ba,pt %xcc, 99f\n\t" \ +#define write_pic(__p) \ + __asm__ __volatile__("ba,pt %%xcc, 99f\n\t" \ ".align 64\n" \ - "99:wr %g0, 0x0, %pic\n\t" \ - "rd %pic, %g0") + "99:wr %0, 0x0, %%pic\n\t" \ + "rd %%pic, %%g0" : : "r" (__p)) +#define reset_pic() write_pic(0) #ifndef __ASSEMBLY__ @@ -170,6 +160,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \ "stb %%o5, [%%g6 + %5]\n\t" \ "rdpr %%cwp, %%o5\n\t" \ "stb %%o5, [%%g6 + %8]\n\t" \ + "wrpr %%g0, 15, %%pil\n\t" \ "mov %4, %%g6\n\t" \ "ldub [%4 + %8], %%g1\n\t" \ "wrpr %%g1, %%cwp\n\t" \ @@ -180,6 +171,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \ "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \ "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \ "ldx [%%g6 + %9], %%g4\n\t" \ + "wrpr %%g0, 14, %%pil\n\t" \ "brz,pt %%o7, switch_to_pc\n\t" \ " mov %%g7, %0\n\t" \ "sethi %%hi(ret_from_syscall), %%g1\n\t" \ @@ -209,14 +201,12 @@ static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int va unsigned long tmp1, tmp2; __asm__ __volatile__( -" membar #StoreLoad | #LoadLoad\n" " mov %0, %1\n" "1: lduw [%4], %2\n" " cas [%4], %2, %0\n" " cmp %2, %0\n" " bne,a,pn %%icc, 1b\n" " mov %1, %0\n" -" membar #StoreLoad | #StoreStore\n" : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2) : "0" (val), "r" (m) : "cc", "memory"); @@ -228,14 +218,12 @@ static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long unsigned long tmp1, tmp2; __asm__ __volatile__( -" membar #StoreLoad | #LoadLoad\n" " mov %0, %1\n" "1: ldx [%4], %2\n" " casx [%4], %2, %0\n" " cmp %2, %0\n" " bne,a,pn %%xcc, 1b\n" " mov %1, %0\n" -" membar #StoreLoad | #StoreStore\n" : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2) : "0" (val), "r" (m) : "cc", "memory"); @@ -272,9 +260,7 @@ extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noret static inline unsigned long __cmpxchg_u32(volatile int *m, int old, int new) { - __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" - "cas [%2], %3, %0\n\t" - "membar #StoreLoad | #StoreStore" + __asm__ __volatile__("cas [%2], %3, %0" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); @@ -285,9 +271,7 @@ __cmpxchg_u32(volatile int *m, int old, int new) static inline unsigned long __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) { - __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" - "casx [%2], %3, %0\n\t" - "membar #StoreLoad | #StoreStore" + __asm__ __volatile__("casx [%2], %3, %0" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h index 76e4299dd9bc..83c571d8c8a7 100644 --- a/arch/sparc/include/asm/tsb.h +++ b/arch/sparc/include/asm/tsb.h @@ -50,8 +50,6 @@ #define TSB_TAG_INVALID_BIT 46 #define TSB_TAG_INVALID_HIGH (1 << (TSB_TAG_INVALID_BIT - 32)) -#define TSB_MEMBAR membar #StoreStore - /* Some cpus support physical address quad loads. We want to use * those if possible so we don't need to hard-lock the TSB mapping * into the TLB. We encode some instruction patching in order to @@ -128,13 +126,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; cmp REG1, REG2; \ bne,pn %icc, 99b; \ nop; \ - TSB_MEMBAR #define TSB_WRITE(TSB, TTE, TAG) \ add TSB, 0x8, TSB; \ TSB_STORE(TSB, TTE); \ sub TSB, 0x8, TSB; \ - TSB_MEMBAR; \ TSB_STORE(TSB, TAG); #define KTSB_LOAD_QUAD(TSB, REG) \ @@ -153,13 +149,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; cmp REG1, REG2; \ bne,pn %icc, 99b; \ nop; \ - TSB_MEMBAR #define KTSB_WRITE(TSB, TTE, TAG) \ add TSB, 0x8, TSB; \ stxa TTE, [TSB] ASI_N; \ sub TSB, 0x8, TSB; \ - TSB_MEMBAR; \ stxa TAG, [TSB] ASI_N; /* Do a kernel page table walk. Leaves physical PTE pointer in diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h index 5708ba2719fb..48f2807d3265 100644 --- a/arch/sparc/include/asm/ttable.h +++ b/arch/sparc/include/asm/ttable.h @@ -2,6 +2,7 @@ #define _SPARC64_TTABLE_H #include <asm/utrap.h> +#include <asm/pil.h> #ifdef __ASSEMBLY__ #include <asm/thread_info.h> @@ -123,7 +124,7 @@ #define TRAP_IRQ(routine, level) \ rdpr %pil, %g2; \ - wrpr %g0, 15, %pil; \ + wrpr %g0, PIL_NORMAL_MAX, %pil; \ sethi %hi(1f-4), %g7; \ ba,pt %xcc, etrap_irq; \ or %g7, %lo(1f-4), %g7; \ @@ -143,7 +144,7 @@ #define TRAP_IRQ(routine, level) \ rdpr %pil, %g2; \ - wrpr %g0, 15, %pil; \ + wrpr %g0, PIL_NORMAL_MAX, %pil; \ ba,pt %xcc, etrap_irq; \ rd %pc, %g7; \ mov level, %o0; \ @@ -153,6 +154,16 @@ #endif +#define TRAP_NMI_IRQ(routine, level) \ + rdpr %pil, %g2; \ + wrpr %g0, PIL_NMI, %pil; \ + ba,pt %xcc, etrap_irq; \ + rd %pc, %g7; \ + mov level, %o0; \ + call routine; \ + add %sp, PTREGS_OFF, %o1; \ + ba,a,pt %xcc, rtrap_nmi; + #define TRAP_IVEC TRAP_NOSAVE(do_ivec) #define BTRAP(lvl) TRAP_ARG(bad_trap, lvl) diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 4207fb362da0..031f038b19f7 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -1,8 +1,444 @@ -#ifndef ___ASM_SPARC_UNISTD_H -#define ___ASM_SPARC_UNISTD_H -#if defined(__sparc__) && defined(__arch64__) -#include <asm/unistd_64.h> +#ifndef _SPARC_UNISTD_H +#define _SPARC_UNISTD_H + +/* + * System calls under the Sparc. + * + * Don't be scared by the ugly clobbers, it is the only way I can + * think of right now to force the arguments into fixed registers + * before the trap into the system call with gcc 'asm' statements. + * + * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) + * + * SunOS compatibility based upon preliminary work which is: + * + * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) + */ +#ifndef __32bit_syscall_numbers__ +#ifndef __arch64__ +#define __32bit_syscall_numbers__ +#endif +#endif + +#define __NR_restart_syscall 0 /* Linux Specific */ +#define __NR_exit 1 /* Common */ +#define __NR_fork 2 /* Common */ +#define __NR_read 3 /* Common */ +#define __NR_write 4 /* Common */ +#define __NR_open 5 /* Common */ +#define __NR_close 6 /* Common */ +#define __NR_wait4 7 /* Common */ +#define __NR_creat 8 /* Common */ +#define __NR_link 9 /* Common */ +#define __NR_unlink 10 /* Common */ +#define __NR_execv 11 /* SunOS Specific */ +#define __NR_chdir 12 /* Common */ +#define __NR_chown 13 /* Common */ +#define __NR_mknod 14 /* Common */ +#define __NR_chmod 15 /* Common */ +#define __NR_lchown 16 /* Common */ +#define __NR_brk 17 /* Common */ +#define __NR_perfctr 18 /* Performance counter operations */ +#define __NR_lseek 19 /* Common */ +#define __NR_getpid 20 /* Common */ +#define __NR_capget 21 /* Linux Specific */ +#define __NR_capset 22 /* Linux Specific */ +#define __NR_setuid 23 /* Implemented via setreuid in SunOS */ +#define __NR_getuid 24 /* Common */ +#define __NR_vmsplice 25 /* ENOSYS under SunOS */ +#define __NR_ptrace 26 /* Common */ +#define __NR_alarm 27 /* Implemented via setitimer in SunOS */ +#define __NR_sigaltstack 28 /* Common */ +#define __NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */ +#define __NR_utime 30 /* Implemented via utimes() under SunOS */ +#ifdef __32bit_syscall_numbers__ +#define __NR_lchown32 31 /* Linux sparc32 specific */ +#define __NR_fchown32 32 /* Linux sparc32 specific */ +#endif +#define __NR_access 33 /* Common */ +#define __NR_nice 34 /* Implemented via get/setpriority() in SunOS */ +#ifdef __32bit_syscall_numbers__ +#define __NR_chown32 35 /* Linux sparc32 specific */ +#endif +#define __NR_sync 36 /* Common */ +#define __NR_kill 37 /* Common */ +#define __NR_stat 38 /* Common */ +#define __NR_sendfile 39 /* Linux Specific */ +#define __NR_lstat 40 /* Common */ +#define __NR_dup 41 /* Common */ +#define __NR_pipe 42 /* Common */ +#define __NR_times 43 /* Implemented via getrusage() in SunOS */ +#ifdef __32bit_syscall_numbers__ +#define __NR_getuid32 44 /* Linux sparc32 specific */ +#endif +#define __NR_umount2 45 /* Linux Specific */ +#define __NR_setgid 46 /* Implemented via setregid() in SunOS */ +#define __NR_getgid 47 /* Common */ +#define __NR_signal 48 /* Implemented via sigvec() in SunOS */ +#define __NR_geteuid 49 /* SunOS calls getuid() */ +#define __NR_getegid 50 /* SunOS calls getgid() */ +#define __NR_acct 51 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_getgid32 53 /* Linux sparc32 specific */ +#else +#define __NR_memory_ordering 52 /* Linux Specific */ +#endif +#define __NR_ioctl 54 /* Common */ +#define __NR_reboot 55 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_mmap2 56 /* Linux sparc32 Specific */ +#endif +#define __NR_symlink 57 /* Common */ +#define __NR_readlink 58 /* Common */ +#define __NR_execve 59 /* Common */ +#define __NR_umask 60 /* Common */ +#define __NR_chroot 61 /* Common */ +#define __NR_fstat 62 /* Common */ +#define __NR_fstat64 63 /* Linux Specific */ +#define __NR_getpagesize 64 /* Common */ +#define __NR_msync 65 /* Common in newer 1.3.x revs... */ +#define __NR_vfork 66 /* Common */ +#define __NR_pread64 67 /* Linux Specific */ +#define __NR_pwrite64 68 /* Linux Specific */ +#ifdef __32bit_syscall_numbers__ +#define __NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */ +#define __NR_getegid32 70 /* Linux sparc32, sstk under SunOS */ +#endif +#define __NR_mmap 71 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */ +#endif +#define __NR_munmap 73 /* Common */ +#define __NR_mprotect 74 /* Common */ +#define __NR_madvise 75 /* Common */ +#define __NR_vhangup 76 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_truncate64 77 /* Linux sparc32 Specific */ +#endif +#define __NR_mincore 78 /* Common */ +#define __NR_getgroups 79 /* Common */ +#define __NR_setgroups 80 /* Common */ +#define __NR_getpgrp 81 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */ +#endif +#define __NR_setitimer 83 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_ftruncate64 84 /* Linux sparc32 Specific */ +#endif +#define __NR_swapon 85 /* Common */ +#define __NR_getitimer 86 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */ +#endif +#define __NR_sethostname 88 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */ +#endif +#define __NR_dup2 90 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */ +#endif +#define __NR_fcntl 92 /* Common */ +#define __NR_select 93 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */ +#endif +#define __NR_fsync 95 /* Common */ +#define __NR_setpriority 96 /* Common */ +#define __NR_socket 97 /* Common */ +#define __NR_connect 98 /* Common */ +#define __NR_accept 99 /* Common */ +#define __NR_getpriority 100 /* Common */ +#define __NR_rt_sigreturn 101 /* Linux Specific */ +#define __NR_rt_sigaction 102 /* Linux Specific */ +#define __NR_rt_sigprocmask 103 /* Linux Specific */ +#define __NR_rt_sigpending 104 /* Linux Specific */ +#define __NR_rt_sigtimedwait 105 /* Linux Specific */ +#define __NR_rt_sigqueueinfo 106 /* Linux Specific */ +#define __NR_rt_sigsuspend 107 /* Linux Specific */ +#ifdef __32bit_syscall_numbers__ +#define __NR_setresuid32 108 /* Linux Specific, sigvec under SunOS */ +#define __NR_getresuid32 109 /* Linux Specific, sigblock under SunOS */ +#define __NR_setresgid32 110 /* Linux Specific, sigsetmask under SunOS */ +#define __NR_getresgid32 111 /* Linux Specific, sigpause under SunOS */ +#define __NR_setregid32 112 /* Linux sparc32, sigstack under SunOS */ +#else +#define __NR_setresuid 108 /* Linux Specific, sigvec under SunOS */ +#define __NR_getresuid 109 /* Linux Specific, sigblock under SunOS */ +#define __NR_setresgid 110 /* Linux Specific, sigsetmask under SunOS */ +#define __NR_getresgid 111 /* Linux Specific, sigpause under SunOS */ +#endif +#define __NR_recvmsg 113 /* Common */ +#define __NR_sendmsg 114 /* Common */ +#ifdef __32bit_syscall_numbers__ +#define __NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */ +#endif +#define __NR_gettimeofday 116 /* Common */ +#define __NR_getrusage 117 /* Common */ +#define __NR_getsockopt 118 /* Common */ +#define __NR_getcwd 119 /* Linux Specific */ +#define __NR_readv 120 /* Common */ +#define __NR_writev 121 /* Common */ +#define __NR_settimeofday 122 /* Common */ +#define __NR_fchown 123 /* Common */ +#define __NR_fchmod 124 /* Common */ +#define __NR_recvfrom 125 /* Common */ +#define __NR_setreuid 126 /* Common */ +#define __NR_setregid 127 /* Common */ +#define __NR_rename 128 /* Common */ +#define __NR_truncate 129 /* Common */ +#define __NR_ftruncate 130 /* Common */ +#define __NR_flock 131 /* Common */ +#define __NR_lstat64 132 /* Linux Specific */ +#define __NR_sendto 133 /* Common */ +#define __NR_shutdown 134 /* Common */ +#define __NR_socketpair 135 /* Common */ +#define __NR_mkdir 136 /* Common */ +#define __NR_rmdir 137 /* Common */ +#define __NR_utimes 138 /* SunOS Specific */ +#define __NR_stat64 139 /* Linux Specific */ +#define __NR_sendfile64 140 /* adjtime under SunOS */ +#define __NR_getpeername 141 /* Common */ +#define __NR_futex 142 /* gethostid under SunOS */ +#define __NR_gettid 143 /* ENOSYS under SunOS */ +#define __NR_getrlimit 144 /* Common */ +#define __NR_setrlimit 145 /* Common */ +#define __NR_pivot_root 146 /* Linux Specific, killpg under SunOS */ +#define __NR_prctl 147 /* ENOSYS under SunOS */ +#define __NR_pciconfig_read 148 /* ENOSYS under SunOS */ +#define __NR_pciconfig_write 149 /* ENOSYS under SunOS */ +#define __NR_getsockname 150 /* Common */ +#define __NR_inotify_init 151 /* Linux specific */ +#define __NR_inotify_add_watch 152 /* Linux specific */ +#define __NR_poll 153 /* Common */ +#define __NR_getdents64 154 /* Linux specific */ +#ifdef __32bit_syscall_numbers__ +#define __NR_fcntl64 155 /* Linux sparc32 Specific */ +#endif +#define __NR_inotify_rm_watch 156 /* Linux specific */ +#define __NR_statfs 157 /* Common */ +#define __NR_fstatfs 158 /* Common */ +#define __NR_umount 159 /* Common */ +#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS */ +#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS */ +#define __NR_getdomainname 162 /* SunOS Specific */ +#define __NR_setdomainname 163 /* Common */ +#ifndef __32bit_syscall_numbers__ +#define __NR_utrap_install 164 /* SYSV ABI/v9 required */ +#endif +#define __NR_quotactl 165 /* Common */ +#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ +#define __NR_mount 167 /* Common */ +#define __NR_ustat 168 /* Common */ +#define __NR_setxattr 169 /* SunOS: semsys */ +#define __NR_lsetxattr 170 /* SunOS: msgsys */ +#define __NR_fsetxattr 171 /* SunOS: shmsys */ +#define __NR_getxattr 172 /* SunOS: auditsys */ +#define __NR_lgetxattr 173 /* SunOS: rfssys */ +#define __NR_getdents 174 /* Common */ +#define __NR_setsid 175 /* Common */ +#define __NR_fchdir 176 /* Common */ +#define __NR_fgetxattr 177 /* SunOS: fchroot */ +#define __NR_listxattr 178 /* SunOS: vpixsys */ +#define __NR_llistxattr 179 /* SunOS: aioread */ +#define __NR_flistxattr 180 /* SunOS: aiowrite */ +#define __NR_removexattr 181 /* SunOS: aiowait */ +#define __NR_lremovexattr 182 /* SunOS: aiocancel */ +#define __NR_sigpending 183 /* Common */ +#define __NR_query_module 184 /* Linux Specific */ +#define __NR_setpgid 185 /* Common */ +#define __NR_fremovexattr 186 /* SunOS: pathconf */ +#define __NR_tkill 187 /* SunOS: fpathconf */ +#define __NR_exit_group 188 /* Linux specific, sysconf undef SunOS */ +#define __NR_uname 189 /* Linux Specific */ +#define __NR_init_module 190 /* Linux Specific */ +#define __NR_personality 191 /* Linux Specific */ +#define __NR_remap_file_pages 192 /* Linux Specific */ +#define __NR_epoll_create 193 /* Linux Specific */ +#define __NR_epoll_ctl 194 /* Linux Specific */ +#define __NR_epoll_wait 195 /* Linux Specific */ +#define __NR_ioprio_set 196 /* Linux Specific */ +#define __NR_getppid 197 /* Linux Specific */ +#define __NR_sigaction 198 /* Linux Specific */ +#define __NR_sgetmask 199 /* Linux Specific */ +#define __NR_ssetmask 200 /* Linux Specific */ +#define __NR_sigsuspend 201 /* Linux Specific */ +#define __NR_oldlstat 202 /* Linux Specific */ +#define __NR_uselib 203 /* Linux Specific */ +#define __NR_readdir 204 /* Linux Specific */ +#define __NR_readahead 205 /* Linux Specific */ +#define __NR_socketcall 206 /* Linux Specific */ +#define __NR_syslog 207 /* Linux Specific */ +#define __NR_lookup_dcookie 208 /* Linux Specific */ +#define __NR_fadvise64 209 /* Linux Specific */ +#define __NR_fadvise64_64 210 /* Linux Specific */ +#define __NR_tgkill 211 /* Linux Specific */ +#define __NR_waitpid 212 /* Linux Specific */ +#define __NR_swapoff 213 /* Linux Specific */ +#define __NR_sysinfo 214 /* Linux Specific */ +#define __NR_ipc 215 /* Linux Specific */ +#define __NR_sigreturn 216 /* Linux Specific */ +#define __NR_clone 217 /* Linux Specific */ +#define __NR_ioprio_get 218 /* Linux Specific */ +#define __NR_adjtimex 219 /* Linux Specific */ +#define __NR_sigprocmask 220 /* Linux Specific */ +#define __NR_create_module 221 /* Linux Specific */ +#define __NR_delete_module 222 /* Linux Specific */ +#define __NR_get_kernel_syms 223 /* Linux Specific */ +#define __NR_getpgid 224 /* Linux Specific */ +#define __NR_bdflush 225 /* Linux Specific */ +#define __NR_sysfs 226 /* Linux Specific */ +#define __NR_afs_syscall 227 /* Linux Specific */ +#define __NR_setfsuid 228 /* Linux Specific */ +#define __NR_setfsgid 229 /* Linux Specific */ +#define __NR__newselect 230 /* Linux Specific */ +#ifdef __32bit_syscall_numbers__ +#define __NR_time 231 /* Linux Specific */ #else -#include <asm/unistd_32.h> +#ifdef __KERNEL__ +#define __NR_time 231 /* Linux sparc32 */ +#endif +#endif +#define __NR_splice 232 /* Linux Specific */ +#define __NR_stime 233 /* Linux Specific */ +#define __NR_statfs64 234 /* Linux Specific */ +#define __NR_fstatfs64 235 /* Linux Specific */ +#define __NR__llseek 236 /* Linux Specific */ +#define __NR_mlock 237 +#define __NR_munlock 238 +#define __NR_mlockall 239 +#define __NR_munlockall 240 +#define __NR_sched_setparam 241 +#define __NR_sched_getparam 242 +#define __NR_sched_setscheduler 243 +#define __NR_sched_getscheduler 244 +#define __NR_sched_yield 245 +#define __NR_sched_get_priority_max 246 +#define __NR_sched_get_priority_min 247 +#define __NR_sched_rr_get_interval 248 +#define __NR_nanosleep 249 +#define __NR_mremap 250 +#define __NR__sysctl 251 +#define __NR_getsid 252 +#define __NR_fdatasync 253 +#define __NR_nfsservctl 254 +#define __NR_sync_file_range 255 +#define __NR_clock_settime 256 +#define __NR_clock_gettime 257 +#define __NR_clock_getres 258 +#define __NR_clock_nanosleep 259 +#define __NR_sched_getaffinity 260 +#define __NR_sched_setaffinity 261 +#define __NR_timer_settime 262 +#define __NR_timer_gettime 263 +#define __NR_timer_getoverrun 264 +#define __NR_timer_delete 265 +#define __NR_timer_create 266 +/* #define __NR_vserver 267 Reserved for VSERVER */ +#define __NR_io_setup 268 +#define __NR_io_destroy 269 +#define __NR_io_submit 270 +#define __NR_io_cancel 271 +#define __NR_io_getevents 272 +#define __NR_mq_open 273 +#define __NR_mq_unlink 274 +#define __NR_mq_timedsend 275 +#define __NR_mq_timedreceive 276 +#define __NR_mq_notify 277 +#define __NR_mq_getsetattr 278 +#define __NR_waitid 279 +#define __NR_tee 280 +#define __NR_add_key 281 +#define __NR_request_key 282 +#define __NR_keyctl 283 +#define __NR_openat 284 +#define __NR_mkdirat 285 +#define __NR_mknodat 286 +#define __NR_fchownat 287 +#define __NR_futimesat 288 +#define __NR_fstatat64 289 +#define __NR_unlinkat 290 +#define __NR_renameat 291 +#define __NR_linkat 292 +#define __NR_symlinkat 293 +#define __NR_readlinkat 294 +#define __NR_fchmodat 295 +#define __NR_faccessat 296 +#define __NR_pselect6 297 +#define __NR_ppoll 298 +#define __NR_unshare 299 +#define __NR_set_robust_list 300 +#define __NR_get_robust_list 301 +#define __NR_migrate_pages 302 +#define __NR_mbind 303 +#define __NR_get_mempolicy 304 +#define __NR_set_mempolicy 305 +#define __NR_kexec_load 306 +#define __NR_move_pages 307 +#define __NR_getcpu 308 +#define __NR_epoll_pwait 309 +#define __NR_utimensat 310 +#define __NR_signalfd 311 +#define __NR_timerfd_create 312 +#define __NR_eventfd 313 +#define __NR_fallocate 314 +#define __NR_timerfd_settime 315 +#define __NR_timerfd_gettime 316 +#define __NR_signalfd4 317 +#define __NR_eventfd2 318 +#define __NR_epoll_create1 319 +#define __NR_dup3 320 +#define __NR_pipe2 321 +#define __NR_inotify_init1 322 +#define __NR_accept4 323 + +#define NR_SYSCALLS 324 + +#ifdef __32bit_syscall_numbers__ +/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, + * it never had the plain ones and there is no value to adding those + * old versions into the syscall table. + */ +#define __IGNORE_setresuid +#define __IGNORE_getresuid +#define __IGNORE_setresgid +#define __IGNORE_getresgid #endif + +#ifdef __KERNEL__ +#define __ARCH_WANT_IPC_PARSE_VERSION +#define __ARCH_WANT_OLD_READDIR +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_GETHOSTNAME +#define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#define __ARCH_WANT_SYS_SIGNAL +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_FADVISE64 +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGSUSPEND +#ifndef __32bit_syscall_numbers__ +#define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #endif + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") + +#endif /* __KERNEL__ */ +#endif /* _SPARC_UNISTD_H */ diff --git a/arch/sparc/include/asm/unistd_32.h b/arch/sparc/include/asm/unistd_32.h deleted file mode 100644 index 0d13d2a4c76f..000000000000 --- a/arch/sparc/include/asm/unistd_32.h +++ /dev/null @@ -1,385 +0,0 @@ -#ifndef _SPARC_UNISTD_H -#define _SPARC_UNISTD_H - -/* - * System calls under the Sparc. - * - * Don't be scared by the ugly clobbers, it is the only way I can - * think of right now to force the arguments into fixed registers - * before the trap into the system call with gcc 'asm' statements. - * - * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) - * - * SunOS compatibility based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#define __NR_restart_syscall 0 /* Linux Specific */ -#define __NR_exit 1 /* Common */ -#define __NR_fork 2 /* Common */ -#define __NR_read 3 /* Common */ -#define __NR_write 4 /* Common */ -#define __NR_open 5 /* Common */ -#define __NR_close 6 /* Common */ -#define __NR_wait4 7 /* Common */ -#define __NR_creat 8 /* Common */ -#define __NR_link 9 /* Common */ -#define __NR_unlink 10 /* Common */ -#define __NR_execv 11 /* SunOS Specific */ -#define __NR_chdir 12 /* Common */ -#define __NR_chown 13 /* Common */ -#define __NR_mknod 14 /* Common */ -#define __NR_chmod 15 /* Common */ -#define __NR_lchown 16 /* Common */ -#define __NR_brk 17 /* Common */ -#define __NR_perfctr 18 /* Performance counter operations */ -#define __NR_lseek 19 /* Common */ -#define __NR_getpid 20 /* Common */ -#define __NR_capget 21 /* Linux Specific */ -#define __NR_capset 22 /* Linux Specific */ -#define __NR_setuid 23 /* Implemented via setreuid in SunOS */ -#define __NR_getuid 24 /* Common */ -#define __NR_vmsplice 25 /* ENOSYS under SunOS */ -#define __NR_ptrace 26 /* Common */ -#define __NR_alarm 27 /* Implemented via setitimer in SunOS */ -#define __NR_sigaltstack 28 /* Common */ -#define __NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */ -#define __NR_utime 30 /* Implemented via utimes() under SunOS */ -#define __NR_lchown32 31 /* Linux sparc32 specific */ -#define __NR_fchown32 32 /* Linux sparc32 specific */ -#define __NR_access 33 /* Common */ -#define __NR_nice 34 /* Implemented via get/setpriority() in SunOS */ -#define __NR_chown32 35 /* Linux sparc32 specific */ -#define __NR_sync 36 /* Common */ -#define __NR_kill 37 /* Common */ -#define __NR_stat 38 /* Common */ -#define __NR_sendfile 39 /* Linux Specific */ -#define __NR_lstat 40 /* Common */ -#define __NR_dup 41 /* Common */ -#define __NR_pipe 42 /* Common */ -#define __NR_times 43 /* Implemented via getrusage() in SunOS */ -#define __NR_getuid32 44 /* Linux sparc32 specific */ -#define __NR_umount2 45 /* Linux Specific */ -#define __NR_setgid 46 /* Implemented via setregid() in SunOS */ -#define __NR_getgid 47 /* Common */ -#define __NR_signal 48 /* Implemented via sigvec() in SunOS */ -#define __NR_geteuid 49 /* SunOS calls getuid() */ -#define __NR_getegid 50 /* SunOS calls getgid() */ -#define __NR_acct 51 /* Common */ -/* #define __NR_memory_ordering 52 Linux sparc64 specific */ -#define __NR_getgid32 53 /* Linux sparc32 specific */ -#define __NR_ioctl 54 /* Common */ -#define __NR_reboot 55 /* Common */ -#define __NR_mmap2 56 /* Linux sparc32 Specific */ -#define __NR_symlink 57 /* Common */ -#define __NR_readlink 58 /* Common */ -#define __NR_execve 59 /* Common */ -#define __NR_umask 60 /* Common */ -#define __NR_chroot 61 /* Common */ -#define __NR_fstat 62 /* Common */ -#define __NR_fstat64 63 /* Linux Specific */ -#define __NR_getpagesize 64 /* Common */ -#define __NR_msync 65 /* Common in newer 1.3.x revs... */ -#define __NR_vfork 66 /* Common */ -#define __NR_pread64 67 /* Linux Specific */ -#define __NR_pwrite64 68 /* Linux Specific */ -#define __NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */ -#define __NR_getegid32 70 /* Linux sparc32, sstk under SunOS */ -#define __NR_mmap 71 /* Common */ -#define __NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */ -#define __NR_munmap 73 /* Common */ -#define __NR_mprotect 74 /* Common */ -#define __NR_madvise 75 /* Common */ -#define __NR_vhangup 76 /* Common */ -#define __NR_truncate64 77 /* Linux sparc32 Specific */ -#define __NR_mincore 78 /* Common */ -#define __NR_getgroups 79 /* Common */ -#define __NR_setgroups 80 /* Common */ -#define __NR_getpgrp 81 /* Common */ -#define __NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */ -#define __NR_setitimer 83 /* Common */ -#define __NR_ftruncate64 84 /* Linux sparc32 Specific */ -#define __NR_swapon 85 /* Common */ -#define __NR_getitimer 86 /* Common */ -#define __NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */ -#define __NR_sethostname 88 /* Common */ -#define __NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */ -#define __NR_dup2 90 /* Common */ -#define __NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */ -#define __NR_fcntl 92 /* Common */ -#define __NR_select 93 /* Common */ -#define __NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */ -#define __NR_fsync 95 /* Common */ -#define __NR_setpriority 96 /* Common */ -#define __NR_socket 97 /* Common */ -#define __NR_connect 98 /* Common */ -#define __NR_accept 99 /* Common */ -#define __NR_getpriority 100 /* Common */ -#define __NR_rt_sigreturn 101 /* Linux Specific */ -#define __NR_rt_sigaction 102 /* Linux Specific */ -#define __NR_rt_sigprocmask 103 /* Linux Specific */ -#define __NR_rt_sigpending 104 /* Linux Specific */ -#define __NR_rt_sigtimedwait 105 /* Linux Specific */ -#define __NR_rt_sigqueueinfo 106 /* Linux Specific */ -#define __NR_rt_sigsuspend 107 /* Linux Specific */ -#define __NR_setresuid32 108 /* Linux Specific, sigvec under SunOS */ -#define __NR_getresuid32 109 /* Linux Specific, sigblock under SunOS */ -#define __NR_setresgid32 110 /* Linux Specific, sigsetmask under SunOS */ -#define __NR_getresgid32 111 /* Linux Specific, sigpause under SunOS */ -#define __NR_setregid32 112 /* Linux sparc32, sigstack under SunOS */ -#define __NR_recvmsg 113 /* Common */ -#define __NR_sendmsg 114 /* Common */ -#define __NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */ -#define __NR_gettimeofday 116 /* Common */ -#define __NR_getrusage 117 /* Common */ -#define __NR_getsockopt 118 /* Common */ -#define __NR_getcwd 119 /* Linux Specific */ -#define __NR_readv 120 /* Common */ -#define __NR_writev 121 /* Common */ -#define __NR_settimeofday 122 /* Common */ -#define __NR_fchown 123 /* Common */ -#define __NR_fchmod 124 /* Common */ -#define __NR_recvfrom 125 /* Common */ -#define __NR_setreuid 126 /* Common */ -#define __NR_setregid 127 /* Common */ -#define __NR_rename 128 /* Common */ -#define __NR_truncate 129 /* Common */ -#define __NR_ftruncate 130 /* Common */ -#define __NR_flock 131 /* Common */ -#define __NR_lstat64 132 /* Linux Specific */ -#define __NR_sendto 133 /* Common */ -#define __NR_shutdown 134 /* Common */ -#define __NR_socketpair 135 /* Common */ -#define __NR_mkdir 136 /* Common */ -#define __NR_rmdir 137 /* Common */ -#define __NR_utimes 138 /* SunOS Specific */ -#define __NR_stat64 139 /* Linux Specific */ -#define __NR_sendfile64 140 /* adjtime under SunOS */ -#define __NR_getpeername 141 /* Common */ -#define __NR_futex 142 /* gethostid under SunOS */ -#define __NR_gettid 143 /* ENOSYS under SunOS */ -#define __NR_getrlimit 144 /* Common */ -#define __NR_setrlimit 145 /* Common */ -#define __NR_pivot_root 146 /* Linux Specific, killpg under SunOS */ -#define __NR_prctl 147 /* ENOSYS under SunOS */ -#define __NR_pciconfig_read 148 /* ENOSYS under SunOS */ -#define __NR_pciconfig_write 149 /* ENOSYS under SunOS */ -#define __NR_getsockname 150 /* Common */ -#define __NR_inotify_init 151 /* Linux specific */ -#define __NR_inotify_add_watch 152 /* Linux specific */ -#define __NR_poll 153 /* Common */ -#define __NR_getdents64 154 /* Linux specific */ -#define __NR_fcntl64 155 /* Linux sparc32 Specific */ -#define __NR_inotify_rm_watch 156 /* Linux specific */ -#define __NR_statfs 157 /* Common */ -#define __NR_fstatfs 158 /* Common */ -#define __NR_umount 159 /* Common */ -#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS */ -#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS */ -#define __NR_getdomainname 162 /* SunOS Specific */ -#define __NR_setdomainname 163 /* Common */ -/* #define __NR_utrap_install 164 Linux sparc64 specific */ -#define __NR_quotactl 165 /* Common */ -#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ -#define __NR_mount 167 /* Common */ -#define __NR_ustat 168 /* Common */ -#define __NR_setxattr 169 /* SunOS: semsys */ -#define __NR_lsetxattr 170 /* SunOS: msgsys */ -#define __NR_fsetxattr 171 /* SunOS: shmsys */ -#define __NR_getxattr 172 /* SunOS: auditsys */ -#define __NR_lgetxattr 173 /* SunOS: rfssys */ -#define __NR_getdents 174 /* Common */ -#define __NR_setsid 175 /* Common */ -#define __NR_fchdir 176 /* Common */ -#define __NR_fgetxattr 177 /* SunOS: fchroot */ -#define __NR_listxattr 178 /* SunOS: vpixsys */ -#define __NR_llistxattr 179 /* SunOS: aioread */ -#define __NR_flistxattr 180 /* SunOS: aiowrite */ -#define __NR_removexattr 181 /* SunOS: aiowait */ -#define __NR_lremovexattr 182 /* SunOS: aiocancel */ -#define __NR_sigpending 183 /* Common */ -#define __NR_query_module 184 /* Linux Specific */ -#define __NR_setpgid 185 /* Common */ -#define __NR_fremovexattr 186 /* SunOS: pathconf */ -#define __NR_tkill 187 /* SunOS: fpathconf */ -#define __NR_exit_group 188 /* Linux specific, sysconf undef SunOS */ -#define __NR_uname 189 /* Linux Specific */ -#define __NR_init_module 190 /* Linux Specific */ -#define __NR_personality 191 /* Linux Specific */ -#define __NR_remap_file_pages 192 /* Linux Specific */ -#define __NR_epoll_create 193 /* Linux Specific */ -#define __NR_epoll_ctl 194 /* Linux Specific */ -#define __NR_epoll_wait 195 /* Linux Specific */ -#define __NR_ioprio_set 196 /* Linux Specific */ -#define __NR_getppid 197 /* Linux Specific */ -#define __NR_sigaction 198 /* Linux Specific */ -#define __NR_sgetmask 199 /* Linux Specific */ -#define __NR_ssetmask 200 /* Linux Specific */ -#define __NR_sigsuspend 201 /* Linux Specific */ -#define __NR_oldlstat 202 /* Linux Specific */ -#define __NR_uselib 203 /* Linux Specific */ -#define __NR_readdir 204 /* Linux Specific */ -#define __NR_readahead 205 /* Linux Specific */ -#define __NR_socketcall 206 /* Linux Specific */ -#define __NR_syslog 207 /* Linux Specific */ -#define __NR_lookup_dcookie 208 /* Linux Specific */ -#define __NR_fadvise64 209 /* Linux Specific */ -#define __NR_fadvise64_64 210 /* Linux Specific */ -#define __NR_tgkill 211 /* Linux Specific */ -#define __NR_waitpid 212 /* Linux Specific */ -#define __NR_swapoff 213 /* Linux Specific */ -#define __NR_sysinfo 214 /* Linux Specific */ -#define __NR_ipc 215 /* Linux Specific */ -#define __NR_sigreturn 216 /* Linux Specific */ -#define __NR_clone 217 /* Linux Specific */ -#define __NR_ioprio_get 218 /* Linux Specific */ -#define __NR_adjtimex 219 /* Linux Specific */ -#define __NR_sigprocmask 220 /* Linux Specific */ -#define __NR_create_module 221 /* Linux Specific */ -#define __NR_delete_module 222 /* Linux Specific */ -#define __NR_get_kernel_syms 223 /* Linux Specific */ -#define __NR_getpgid 224 /* Linux Specific */ -#define __NR_bdflush 225 /* Linux Specific */ -#define __NR_sysfs 226 /* Linux Specific */ -#define __NR_afs_syscall 227 /* Linux Specific */ -#define __NR_setfsuid 228 /* Linux Specific */ -#define __NR_setfsgid 229 /* Linux Specific */ -#define __NR__newselect 230 /* Linux Specific */ -#define __NR_time 231 /* Linux Specific */ -#define __NR_splice 232 /* Linux Specific */ -#define __NR_stime 233 /* Linux Specific */ -#define __NR_statfs64 234 /* Linux Specific */ -#define __NR_fstatfs64 235 /* Linux Specific */ -#define __NR__llseek 236 /* Linux Specific */ -#define __NR_mlock 237 -#define __NR_munlock 238 -#define __NR_mlockall 239 -#define __NR_munlockall 240 -#define __NR_sched_setparam 241 -#define __NR_sched_getparam 242 -#define __NR_sched_setscheduler 243 -#define __NR_sched_getscheduler 244 -#define __NR_sched_yield 245 -#define __NR_sched_get_priority_max 246 -#define __NR_sched_get_priority_min 247 -#define __NR_sched_rr_get_interval 248 -#define __NR_nanosleep 249 -#define __NR_mremap 250 -#define __NR__sysctl 251 -#define __NR_getsid 252 -#define __NR_fdatasync 253 -#define __NR_nfsservctl 254 -#define __NR_sync_file_range 255 -#define __NR_clock_settime 256 -#define __NR_clock_gettime 257 -#define __NR_clock_getres 258 -#define __NR_clock_nanosleep 259 -#define __NR_sched_getaffinity 260 -#define __NR_sched_setaffinity 261 -#define __NR_timer_settime 262 -#define __NR_timer_gettime 263 -#define __NR_timer_getoverrun 264 -#define __NR_timer_delete 265 -#define __NR_timer_create 266 -/* #define __NR_vserver 267 Reserved for VSERVER */ -#define __NR_io_setup 268 -#define __NR_io_destroy 269 -#define __NR_io_submit 270 -#define __NR_io_cancel 271 -#define __NR_io_getevents 272 -#define __NR_mq_open 273 -#define __NR_mq_unlink 274 -#define __NR_mq_timedsend 275 -#define __NR_mq_timedreceive 276 -#define __NR_mq_notify 277 -#define __NR_mq_getsetattr 278 -#define __NR_waitid 279 -#define __NR_tee 280 -#define __NR_add_key 281 -#define __NR_request_key 282 -#define __NR_keyctl 283 -#define __NR_openat 284 -#define __NR_mkdirat 285 -#define __NR_mknodat 286 -#define __NR_fchownat 287 -#define __NR_futimesat 288 -#define __NR_fstatat64 289 -#define __NR_unlinkat 290 -#define __NR_renameat 291 -#define __NR_linkat 292 -#define __NR_symlinkat 293 -#define __NR_readlinkat 294 -#define __NR_fchmodat 295 -#define __NR_faccessat 296 -#define __NR_pselect6 297 -#define __NR_ppoll 298 -#define __NR_unshare 299 -#define __NR_set_robust_list 300 -#define __NR_get_robust_list 301 -#define __NR_migrate_pages 302 -#define __NR_mbind 303 -#define __NR_get_mempolicy 304 -#define __NR_set_mempolicy 305 -#define __NR_kexec_load 306 -#define __NR_move_pages 307 -#define __NR_getcpu 308 -#define __NR_epoll_pwait 309 -#define __NR_utimensat 310 -#define __NR_signalfd 311 -#define __NR_timerfd_create 312 -#define __NR_eventfd 313 -#define __NR_fallocate 314 -#define __NR_timerfd_settime 315 -#define __NR_timerfd_gettime 316 -#define __NR_signalfd4 317 -#define __NR_eventfd2 318 -#define __NR_epoll_create1 319 -#define __NR_dup3 320 -#define __NR_pipe2 321 -#define __NR_inotify_init1 322 -#define __NR_accept4 323 - -#define NR_SYSCALLS 324 - -/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, - * it never had the plain ones and there is no value to adding those - * old versions into the syscall table. - */ -#define __IGNORE_setresuid -#define __IGNORE_getresuid -#define __IGNORE_setresgid -#define __IGNORE_getresgid - -#ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGSUSPEND - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") - -#endif /* __KERNEL__ */ -#endif /* _SPARC_UNISTD_H */ diff --git a/arch/sparc/include/asm/unistd_64.h b/arch/sparc/include/asm/unistd_64.h deleted file mode 100644 index fa5d3c0343c7..000000000000 --- a/arch/sparc/include/asm/unistd_64.h +++ /dev/null @@ -1,380 +0,0 @@ -#ifndef _SPARC64_UNISTD_H -#define _SPARC64_UNISTD_H - -/* - * System calls under the Sparc. - * - * Don't be scared by the ugly clobbers, it is the only way I can - * think of right now to force the arguments into fixed registers - * before the trap into the system call with gcc 'asm' statements. - * - * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) - * - * SunOS compatibility based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#define __NR_restart_syscall 0 /* Linux Specific */ -#define __NR_exit 1 /* Common */ -#define __NR_fork 2 /* Common */ -#define __NR_read 3 /* Common */ -#define __NR_write 4 /* Common */ -#define __NR_open 5 /* Common */ -#define __NR_close 6 /* Common */ -#define __NR_wait4 7 /* Common */ -#define __NR_creat 8 /* Common */ -#define __NR_link 9 /* Common */ -#define __NR_unlink 10 /* Common */ -#define __NR_execv 11 /* SunOS Specific */ -#define __NR_chdir 12 /* Common */ -#define __NR_chown 13 /* Common */ -#define __NR_mknod 14 /* Common */ -#define __NR_chmod 15 /* Common */ -#define __NR_lchown 16 /* Common */ -#define __NR_brk 17 /* Common */ -#define __NR_perfctr 18 /* Performance counter operations */ -#define __NR_lseek 19 /* Common */ -#define __NR_getpid 20 /* Common */ -#define __NR_capget 21 /* Linux Specific */ -#define __NR_capset 22 /* Linux Specific */ -#define __NR_setuid 23 /* Implemented via setreuid in SunOS */ -#define __NR_getuid 24 /* Common */ -#define __NR_vmsplice 25 /* ENOSYS under SunOS */ -#define __NR_ptrace 26 /* Common */ -#define __NR_alarm 27 /* Implemented via setitimer in SunOS */ -#define __NR_sigaltstack 28 /* Common */ -#define __NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */ -#define __NR_utime 30 /* Implemented via utimes() under SunOS */ -/* #define __NR_lchown32 31 Linux sparc32 specific */ -/* #define __NR_fchown32 32 Linux sparc32 specific */ -#define __NR_access 33 /* Common */ -#define __NR_nice 34 /* Implemented via get/setpriority() in SunOS */ -/* #define __NR_chown32 35 Linux sparc32 specific */ -#define __NR_sync 36 /* Common */ -#define __NR_kill 37 /* Common */ -#define __NR_stat 38 /* Common */ -#define __NR_sendfile 39 /* Linux Specific */ -#define __NR_lstat 40 /* Common */ -#define __NR_dup 41 /* Common */ -#define __NR_pipe 42 /* Common */ -#define __NR_times 43 /* Implemented via getrusage() in SunOS */ -/* #define __NR_getuid32 44 Linux sparc32 specific */ -#define __NR_umount2 45 /* Linux Specific */ -#define __NR_setgid 46 /* Implemented via setregid() in SunOS */ -#define __NR_getgid 47 /* Common */ -#define __NR_signal 48 /* Implemented via sigvec() in SunOS */ -#define __NR_geteuid 49 /* SunOS calls getuid() */ -#define __NR_getegid 50 /* SunOS calls getgid() */ -#define __NR_acct 51 /* Common */ -#define __NR_memory_ordering 52 /* Linux Specific */ -/* #define __NR_getgid32 53 Linux sparc32 specific */ -#define __NR_ioctl 54 /* Common */ -#define __NR_reboot 55 /* Common */ -/* #define __NR_mmap2 56 Linux sparc32 Specific */ -#define __NR_symlink 57 /* Common */ -#define __NR_readlink 58 /* Common */ -#define __NR_execve 59 /* Common */ -#define __NR_umask 60 /* Common */ -#define __NR_chroot 61 /* Common */ -#define __NR_fstat 62 /* Common */ -#define __NR_fstat64 63 /* Linux Specific */ -#define __NR_getpagesize 64 /* Common */ -#define __NR_msync 65 /* Common in newer 1.3.x revs... */ -#define __NR_vfork 66 /* Common */ -#define __NR_pread64 67 /* Linux Specific */ -#define __NR_pwrite64 68 /* Linux Specific */ -/* #define __NR_geteuid32 69 Linux sparc32, sbrk under SunOS */ -/* #define __NR_getegid32 70 Linux sparc32, sstk under SunOS */ -#define __NR_mmap 71 /* Common */ -/* #define __NR_setreuid32 72 Linux sparc32, vadvise under SunOS */ -#define __NR_munmap 73 /* Common */ -#define __NR_mprotect 74 /* Common */ -#define __NR_madvise 75 /* Common */ -#define __NR_vhangup 76 /* Common */ -/* #define __NR_truncate64 77 Linux sparc32 Specific */ -#define __NR_mincore 78 /* Common */ -#define __NR_getgroups 79 /* Common */ -#define __NR_setgroups 80 /* Common */ -#define __NR_getpgrp 81 /* Common */ -/* #define __NR_setgroups32 82 Linux sparc32, setpgrp under SunOS */ -#define __NR_setitimer 83 /* Common */ -/* #define __NR_ftruncate64 84 Linux sparc32 Specific */ -#define __NR_swapon 85 /* Common */ -#define __NR_getitimer 86 /* Common */ -/* #define __NR_setuid32 87 Linux sparc32, gethostname under SunOS */ -#define __NR_sethostname 88 /* Common */ -/* #define __NR_setgid32 89 Linux sparc32, getdtablesize under SunOS */ -#define __NR_dup2 90 /* Common */ -/* #define __NR_setfsuid32 91 Linux sparc32, getdopt under SunOS */ -#define __NR_fcntl 92 /* Common */ -#define __NR_select 93 /* Common */ -/* #define __NR_setfsgid32 94 Linux sparc32, setdopt under SunOS */ -#define __NR_fsync 95 /* Common */ -#define __NR_setpriority 96 /* Common */ -#define __NR_socket 97 /* Common */ -#define __NR_connect 98 /* Common */ -#define __NR_accept 99 /* Common */ -#define __NR_getpriority 100 /* Common */ -#define __NR_rt_sigreturn 101 /* Linux Specific */ -#define __NR_rt_sigaction 102 /* Linux Specific */ -#define __NR_rt_sigprocmask 103 /* Linux Specific */ -#define __NR_rt_sigpending 104 /* Linux Specific */ -#define __NR_rt_sigtimedwait 105 /* Linux Specific */ -#define __NR_rt_sigqueueinfo 106 /* Linux Specific */ -#define __NR_rt_sigsuspend 107 /* Linux Specific */ -#define __NR_setresuid 108 /* Linux Specific, sigvec under SunOS */ -#define __NR_getresuid 109 /* Linux Specific, sigblock under SunOS */ -#define __NR_setresgid 110 /* Linux Specific, sigsetmask under SunOS */ -#define __NR_getresgid 111 /* Linux Specific, sigpause under SunOS */ -/* #define __NR_setregid32 75 Linux sparc32, sigstack under SunOS */ -#define __NR_recvmsg 113 /* Common */ -#define __NR_sendmsg 114 /* Common */ -/* #define __NR_getgroups32 115 Linux sparc32, vtrace under SunOS */ -#define __NR_gettimeofday 116 /* Common */ -#define __NR_getrusage 117 /* Common */ -#define __NR_getsockopt 118 /* Common */ -#define __NR_getcwd 119 /* Linux Specific */ -#define __NR_readv 120 /* Common */ -#define __NR_writev 121 /* Common */ -#define __NR_settimeofday 122 /* Common */ -#define __NR_fchown 123 /* Common */ -#define __NR_fchmod 124 /* Common */ -#define __NR_recvfrom 125 /* Common */ -#define __NR_setreuid 126 /* Common */ -#define __NR_setregid 127 /* Common */ -#define __NR_rename 128 /* Common */ -#define __NR_truncate 129 /* Common */ -#define __NR_ftruncate 130 /* Common */ -#define __NR_flock 131 /* Common */ -#define __NR_lstat64 132 /* Linux Specific */ -#define __NR_sendto 133 /* Common */ -#define __NR_shutdown 134 /* Common */ -#define __NR_socketpair 135 /* Common */ -#define __NR_mkdir 136 /* Common */ -#define __NR_rmdir 137 /* Common */ -#define __NR_utimes 138 /* SunOS Specific */ -#define __NR_stat64 139 /* Linux Specific */ -#define __NR_sendfile64 140 /* adjtime under SunOS */ -#define __NR_getpeername 141 /* Common */ -#define __NR_futex 142 /* gethostid under SunOS */ -#define __NR_gettid 143 /* ENOSYS under SunOS */ -#define __NR_getrlimit 144 /* Common */ -#define __NR_setrlimit 145 /* Common */ -#define __NR_pivot_root 146 /* Linux Specific, killpg under SunOS */ -#define __NR_prctl 147 /* ENOSYS under SunOS */ -#define __NR_pciconfig_read 148 /* ENOSYS under SunOS */ -#define __NR_pciconfig_write 149 /* ENOSYS under SunOS */ -#define __NR_getsockname 150 /* Common */ -#define __NR_inotify_init 151 /* Linux specific */ -#define __NR_inotify_add_watch 152 /* Linux specific */ -#define __NR_poll 153 /* Common */ -#define __NR_getdents64 154 /* Linux specific */ -/* #define __NR_fcntl64 155 Linux sparc32 Specific */ -#define __NR_inotify_rm_watch 156 /* Linux specific */ -#define __NR_statfs 157 /* Common */ -#define __NR_fstatfs 158 /* Common */ -#define __NR_umount 159 /* Common */ -#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS */ -#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS */ -#define __NR_getdomainname 162 /* SunOS Specific */ -#define __NR_setdomainname 163 /* Common */ -#define __NR_utrap_install 164 /* SYSV ABI/v9 required */ -#define __NR_quotactl 165 /* Common */ -#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ -#define __NR_mount 167 /* Common */ -#define __NR_ustat 168 /* Common */ -#define __NR_setxattr 169 /* SunOS: semsys */ -#define __NR_lsetxattr 170 /* SunOS: msgsys */ -#define __NR_fsetxattr 171 /* SunOS: shmsys */ -#define __NR_getxattr 172 /* SunOS: auditsys */ -#define __NR_lgetxattr 173 /* SunOS: rfssys */ -#define __NR_getdents 174 /* Common */ -#define __NR_setsid 175 /* Common */ -#define __NR_fchdir 176 /* Common */ -#define __NR_fgetxattr 177 /* SunOS: fchroot */ -#define __NR_listxattr 178 /* SunOS: vpixsys */ -#define __NR_llistxattr 179 /* SunOS: aioread */ -#define __NR_flistxattr 180 /* SunOS: aiowrite */ -#define __NR_removexattr 181 /* SunOS: aiowait */ -#define __NR_lremovexattr 182 /* SunOS: aiocancel */ -#define __NR_sigpending 183 /* Common */ -#define __NR_query_module 184 /* Linux Specific */ -#define __NR_setpgid 185 /* Common */ -#define __NR_fremovexattr 186 /* SunOS: pathconf */ -#define __NR_tkill 187 /* SunOS: fpathconf */ -#define __NR_exit_group 188 /* Linux specific, sysconf undef SunOS */ -#define __NR_uname 189 /* Linux Specific */ -#define __NR_init_module 190 /* Linux Specific */ -#define __NR_personality 191 /* Linux Specific */ -#define __NR_remap_file_pages 192 /* Linux Specific */ -#define __NR_epoll_create 193 /* Linux Specific */ -#define __NR_epoll_ctl 194 /* Linux Specific */ -#define __NR_epoll_wait 195 /* Linux Specific */ -#define __NR_ioprio_set 196 /* Linux Specific */ -#define __NR_getppid 197 /* Linux Specific */ -#define __NR_sigaction 198 /* Linux Specific */ -#define __NR_sgetmask 199 /* Linux Specific */ -#define __NR_ssetmask 200 /* Linux Specific */ -#define __NR_sigsuspend 201 /* Linux Specific */ -#define __NR_oldlstat 202 /* Linux Specific */ -#define __NR_uselib 203 /* Linux Specific */ -#define __NR_readdir 204 /* Linux Specific */ -#define __NR_readahead 205 /* Linux Specific */ -#define __NR_socketcall 206 /* Linux Specific */ -#define __NR_syslog 207 /* Linux Specific */ -#define __NR_lookup_dcookie 208 /* Linux Specific */ -#define __NR_fadvise64 209 /* Linux Specific */ -#define __NR_fadvise64_64 210 /* Linux Specific */ -#define __NR_tgkill 211 /* Linux Specific */ -#define __NR_waitpid 212 /* Linux Specific */ -#define __NR_swapoff 213 /* Linux Specific */ -#define __NR_sysinfo 214 /* Linux Specific */ -#define __NR_ipc 215 /* Linux Specific */ -#define __NR_sigreturn 216 /* Linux Specific */ -#define __NR_clone 217 /* Linux Specific */ -#define __NR_ioprio_get 218 /* Linux Specific */ -#define __NR_adjtimex 219 /* Linux Specific */ -#define __NR_sigprocmask 220 /* Linux Specific */ -#define __NR_create_module 221 /* Linux Specific */ -#define __NR_delete_module 222 /* Linux Specific */ -#define __NR_get_kernel_syms 223 /* Linux Specific */ -#define __NR_getpgid 224 /* Linux Specific */ -#define __NR_bdflush 225 /* Linux Specific */ -#define __NR_sysfs 226 /* Linux Specific */ -#define __NR_afs_syscall 227 /* Linux Specific */ -#define __NR_setfsuid 228 /* Linux Specific */ -#define __NR_setfsgid 229 /* Linux Specific */ -#define __NR__newselect 230 /* Linux Specific */ -#ifdef __KERNEL__ -#define __NR_time 231 /* Linux sparc32 */ -#endif -#define __NR_splice 232 /* Linux Specific */ -#define __NR_stime 233 /* Linux Specific */ -#define __NR_statfs64 234 /* Linux Specific */ -#define __NR_fstatfs64 235 /* Linux Specific */ -#define __NR__llseek 236 /* Linux Specific */ -#define __NR_mlock 237 -#define __NR_munlock 238 -#define __NR_mlockall 239 -#define __NR_munlockall 240 -#define __NR_sched_setparam 241 -#define __NR_sched_getparam 242 -#define __NR_sched_setscheduler 243 -#define __NR_sched_getscheduler 244 -#define __NR_sched_yield 245 -#define __NR_sched_get_priority_max 246 -#define __NR_sched_get_priority_min 247 -#define __NR_sched_rr_get_interval 248 -#define __NR_nanosleep 249 -#define __NR_mremap 250 -#define __NR__sysctl 251 -#define __NR_getsid 252 -#define __NR_fdatasync 253 -#define __NR_nfsservctl 254 -#define __NR_sync_file_range 255 -#define __NR_clock_settime 256 -#define __NR_clock_gettime 257 -#define __NR_clock_getres 258 -#define __NR_clock_nanosleep 259 -#define __NR_sched_getaffinity 260 -#define __NR_sched_setaffinity 261 -#define __NR_timer_settime 262 -#define __NR_timer_gettime 263 -#define __NR_timer_getoverrun 264 -#define __NR_timer_delete 265 -#define __NR_timer_create 266 -/* #define __NR_vserver 267 Reserved for VSERVER */ -#define __NR_io_setup 268 -#define __NR_io_destroy 269 -#define __NR_io_submit 270 -#define __NR_io_cancel 271 -#define __NR_io_getevents 272 -#define __NR_mq_open 273 -#define __NR_mq_unlink 274 -#define __NR_mq_timedsend 275 -#define __NR_mq_timedreceive 276 -#define __NR_mq_notify 277 -#define __NR_mq_getsetattr 278 -#define __NR_waitid 279 -#define __NR_tee 280 -#define __NR_add_key 281 -#define __NR_request_key 282 -#define __NR_keyctl 283 -#define __NR_openat 284 -#define __NR_mkdirat 285 -#define __NR_mknodat 286 -#define __NR_fchownat 287 -#define __NR_futimesat 288 -#define __NR_fstatat64 289 -#define __NR_unlinkat 290 -#define __NR_renameat 291 -#define __NR_linkat 292 -#define __NR_symlinkat 293 -#define __NR_readlinkat 294 -#define __NR_fchmodat 295 -#define __NR_faccessat 296 -#define __NR_pselect6 297 -#define __NR_ppoll 298 -#define __NR_unshare 299 -#define __NR_set_robust_list 300 -#define __NR_get_robust_list 301 -#define __NR_migrate_pages 302 -#define __NR_mbind 303 -#define __NR_get_mempolicy 304 -#define __NR_set_mempolicy 305 -#define __NR_kexec_load 306 -#define __NR_move_pages 307 -#define __NR_getcpu 308 -#define __NR_epoll_pwait 309 -#define __NR_utimensat 310 -#define __NR_signalfd 311 -#define __NR_timerfd_create 312 -#define __NR_eventfd 313 -#define __NR_fallocate 314 -#define __NR_timerfd_settime 315 -#define __NR_timerfd_gettime 316 -#define __NR_signalfd4 317 -#define __NR_eventfd2 318 -#define __NR_epoll_create1 319 -#define __NR_dup3 320 -#define __NR_pipe2 321 -#define __NR_inotify_init1 322 -#define __NR_accept4 323 - -#define NR_SYSCALLS 324 - -#ifdef __KERNEL__ -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_COMPAT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") - -#endif /* __KERNEL__ */ -#endif /* _SPARC64_UNISTD_H */ diff --git a/arch/sparc/kernel/.gitignore b/arch/sparc/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/sparc/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 2d6582095099..53adcaa0348b 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -2,25 +2,98 @@ # Makefile for the linux kernel. # -extra-y := head.o init_task.o vmlinux.lds - -EXTRA_AFLAGS := -ansi - -IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o -obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ - process.o signal.o ioport.o setup.o idprom.o \ - sys_sparc.o systbls.o \ - time.o windows.o cpu.o devices.o \ - tadpole.o tick14.o ptrace.o \ - unaligned.o una_asm.o muldiv.o \ - prom.o of_device.o devres.o dma.o - -devres-y = ../../../kernel/irq/devres.o - -obj-$(CONFIG_PCI) += pcic.o -obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o -obj-$(CONFIG_SUN_AUXIO) += auxio.o -obj-$(CONFIG_SUN_PM) += apc.o pmc.o -obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o -obj-$(CONFIG_SPARC_LED) += led.o -obj-$(CONFIG_KGDB) += kgdb.o +asflags-y := -ansi +ccflags-y := -Werror + +extra-y := head_$(BITS).o +extra-y += init_task.o +extra-y += vmlinux.lds + +obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o +obj-$(CONFIG_SPARC32) += etrap_32.o +obj-$(CONFIG_SPARC32) += rtrap_32.o +obj-y += traps_$(BITS).o + +# IRQ +obj-y += irq_$(BITS).o +obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o + +obj-y += process_$(BITS).o +obj-y += signal_$(BITS).o +obj-$(CONFIG_SPARC32) += ioport.o +obj-y += setup_$(BITS).o +obj-y += idprom.o +obj-y += sys_sparc_$(BITS).o +obj-$(CONFIG_SPARC32) += systbls_32.o +obj-y += time_$(BITS).o +obj-$(CONFIG_SPARC32) += windows.o +obj-y += cpu.o +obj-$(CONFIG_SPARC32) += devices.o +obj-$(CONFIG_SPARC32) += tadpole.o +obj-$(CONFIG_SPARC32) += tick14.o +obj-y += ptrace_$(BITS).o +obj-y += unaligned_$(BITS).o +obj-y += una_asm_$(BITS).o +obj-$(CONFIG_SPARC32) += muldiv.o +obj-y += prom_common.o +obj-y += prom_$(BITS).o +obj-y += of_device_$(BITS).o +obj-$(CONFIG_SPARC64) += prom_irqtrans.o + +obj-$(CONFIG_SPARC64) += reboot.o +obj-$(CONFIG_SPARC64) += sysfs.o +obj-$(CONFIG_SPARC64) += iommu.o +obj-$(CONFIG_SPARC64) += central.o +obj-$(CONFIG_SPARC64) += starfire.o +obj-$(CONFIG_SPARC64) += power.o +obj-$(CONFIG_SPARC64) += sbus.o +obj-$(CONFIG_SPARC64) += ebus.o +obj-$(CONFIG_SPARC64) += visemul.o +obj-$(CONFIG_SPARC64) += hvapi.o +obj-$(CONFIG_SPARC64) += sstate.o +obj-$(CONFIG_SPARC64) += mdesc.o + +# sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation +obj-$(CONFIG_SPARC32) += devres.o +devres-y := ../../../kernel/irq/devres.o + +obj-$(CONFIG_SPARC32) += dma.o + +obj-$(CONFIG_SPARC32_PCI) += pcic.o + +obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o +obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o +obj-$(CONFIG_SPARC64_SMP) += hvtramp.o + +obj-y += auxio_$(BITS).o +obj-$(CONFIG_SUN_PM) += apc.o pmc.o + +obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_MODULES) += sparc_ksyms_$(BITS).o +obj-$(CONFIG_SPARC_LED) += led.o +obj-$(CONFIG_KGDB) += kgdb_$(BITS).o + + +obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o +CFLAGS_REMOVE_ftrace.o := -pg + +obj-$(CONFIG_STACKTRACE) += stacktrace.o +# sparc64 PCI +obj-$(CONFIG_SPARC64_PCI) += pci.o pci_common.o psycho_common.o +obj-$(CONFIG_SPARC64_PCI) += pci_psycho.o pci_sabre.o pci_schizo.o +obj-$(CONFIG_SPARC64_PCI) += pci_sun4v.o pci_sun4v_asm.o pci_fire.o +obj-$(CONFIG_PCI_MSI) += pci_msi.o + +obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o + +# sparc64 cpufreq +obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o +obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o +obj-$(CONFIG_US3_MC) += chmc.o + +obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o + +obj-$(CONFIG_AUDIT) += audit.o +audit--$(CONFIG_AUDIT) := compat_audit.o +obj-$(CONFIG_COMPAT) += $(audit--y) diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c index b5bb99ed892c..68f7e1118e9b 100644 --- a/arch/sparc/kernel/asm-offsets.c +++ b/arch/sparc/kernel/asm-offsets.c @@ -14,15 +14,28 @@ // #include <linux/mm.h> #include <linux/kbuild.h> -int foo(void) +#ifdef CONFIG_SPARC32 +int sparc32_foo(void) { - DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread)); - BLANK(); DEFINE(AOFF_thread_fork_kpsr, offsetof(struct thread_struct, fork_kpsr)); + return 0; +} +#else +int sparc64_foo(void) +{ + return 0; +} +#endif + +int foo(void) +{ + BLANK(); + DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread)); BLANK(); DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context)); /* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */ return 0; } + diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc/kernel/audit.c index 8fff0ac63d56..8fff0ac63d56 100644 --- a/arch/sparc64/kernel/audit.c +++ b/arch/sparc/kernel/audit.c diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio_32.c index 09c857215a52..09c857215a52 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio_32.c diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc/kernel/auxio_64.c index 858beda86524..8b67347d4221 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc/kernel/auxio_64.c @@ -27,73 +27,55 @@ enum auxio_type { static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV; static DEFINE_SPINLOCK(auxio_lock); -static void __auxio_sbus_set(u8 bits_on, u8 bits_off) +static void __auxio_rmw(u8 bits_on, u8 bits_off, int ebus) { if (auxio_register) { - unsigned char regval; unsigned long flags; - unsigned char newval; + u8 regval, newval; spin_lock_irqsave(&auxio_lock, flags); - regval = sbus_readb(auxio_register); + regval = (ebus ? + (u8) readl(auxio_register) : + sbus_readb(auxio_register)); newval = regval | bits_on; newval &= ~bits_off; - newval &= ~AUXIO_AUX1_MASK; - sbus_writeb(newval, auxio_register); + if (!ebus) + newval &= ~AUXIO_AUX1_MASK; + if (ebus) + writel((u32) newval, auxio_register); + else + sbus_writeb(newval, auxio_register); spin_unlock_irqrestore(&auxio_lock, flags); } } -static void __auxio_ebus_set(u8 bits_on, u8 bits_off) +static void __auxio_set_bit(u8 bit, int on, int ebus) { - if (auxio_register) { - unsigned char regval; - unsigned long flags; - unsigned char newval; - - spin_lock_irqsave(&auxio_lock, flags); - - regval = (u8)readl(auxio_register); - newval = regval | bits_on; - newval &= ~bits_off; - writel((u32)newval, auxio_register); + u8 bits_on = (ebus ? AUXIO_PCIO_LED : AUXIO_AUX1_LED); + u8 bits_off = 0; - spin_unlock_irqrestore(&auxio_lock, flags); + if (!on) { + u8 tmp = bits_off; + bits_off = bits_on; + bits_on = tmp; } -} - -static inline void __auxio_ebus_set_led(int on) -{ - (on) ? __auxio_ebus_set(AUXIO_PCIO_LED, 0) : - __auxio_ebus_set(0, AUXIO_PCIO_LED) ; -} - -static inline void __auxio_sbus_set_led(int on) -{ - (on) ? __auxio_sbus_set(AUXIO_AUX1_LED, 0) : - __auxio_sbus_set(0, AUXIO_AUX1_LED) ; + __auxio_rmw(bits_on, bits_off, ebus); } void auxio_set_led(int on) { - switch(auxio_devtype) { - case AUXIO_TYPE_SBUS: - __auxio_sbus_set_led(on); - break; - case AUXIO_TYPE_EBUS: - __auxio_ebus_set_led(on); - break; - default: - break; - } + int ebus = auxio_devtype == AUXIO_TYPE_EBUS; + u8 bit; + + bit = (ebus ? AUXIO_PCIO_LED : AUXIO_AUX1_LED); + __auxio_set_bit(bit, on, ebus); } -static inline void __auxio_sbus_set_lte(int on) +static void __auxio_sbus_set_lte(int on) { - (on) ? __auxio_sbus_set(AUXIO_AUX1_LTE, 0) : - __auxio_sbus_set(0, AUXIO_AUX1_LTE) ; + __auxio_set_bit(AUXIO_AUX1_LTE, on, 0); } void auxio_set_lte(int on) diff --git a/arch/sparc64/kernel/central.c b/arch/sparc/kernel/central.c index 05f1c916db06..05f1c916db06 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc/kernel/central.c diff --git a/arch/sparc64/kernel/cherrs.S b/arch/sparc/kernel/cherrs.S index 89afebd7eca0..4ee1ad420862 100644 --- a/arch/sparc64/kernel/cherrs.S +++ b/arch/sparc/kernel/cherrs.S @@ -102,7 +102,7 @@ cheetah_plus_dcpe_trap_vector: .type do_cheetah_plus_data_parity,#function do_cheetah_plus_data_parity: rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS @@ -144,7 +144,7 @@ cheetah_plus_icpe_trap_vector: .type do_cheetah_plus_insn_parity,#function do_cheetah_plus_insn_parity: rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS @@ -492,7 +492,7 @@ cheetah_fast_ecc: .type c_fast_ecc,#function c_fast_ecc: rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS @@ -528,7 +528,7 @@ cheetah_cee: .type c_cee,#function c_cee: rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS @@ -564,7 +564,7 @@ cheetah_deferred_trap: .type c_deferred,#function c_deferred: rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 3b9f4d6e14a9..3b9f4d6e14a9 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc/kernel/compat_audit.c index c831b0a4e660..d865575b25bf 100644 --- a/arch/sparc64/kernel/compat_audit.c +++ b/arch/sparc/kernel/compat_audit.c @@ -1,4 +1,5 @@ -#include <asm/unistd_32.h> +#define __32bit_syscall_numbers__ +#include <asm/unistd.h> unsigned sparc32_dir_class[] = { #include <asm-generic/audit_dir_write.h> diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 1fc17f59c6bf..6c2da2420f76 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -8,6 +8,8 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/threads.h> + +#include <asm/spitfire.h> #include <asm/oplib.h> #include <asm/page.h> #include <asm/head.h> @@ -15,153 +17,322 @@ #include <asm/mbus.h> #include <asm/cpudata.h> +#include "kernel.h" + DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; -struct cpu_iu_info { - int psr_impl; - int psr_vers; - char* cpu_name; /* should be enough I hope... */ +struct cpu_info { + int psr_vers; + const char *name; +}; + +struct fpu_info { + int fp_vers; + const char *name; }; -struct cpu_fp_info { - int psr_impl; - int fp_vers; - char* fp_name; +#define NOCPU 8 +#define NOFPU 8 + +struct manufacturer_info { + int psr_impl; + struct cpu_info cpu_info[NOCPU]; + struct fpu_info fpu_info[NOFPU]; }; +#define CPU(ver, _name) \ +{ .psr_vers = ver, .name = _name } + +#define FPU(ver, _name) \ +{ .fp_vers = ver, .name = _name } + +static const struct manufacturer_info __initconst manufacturer_info[] = { +{ + 0, + /* Sun4/100, 4/200, SLC */ + .cpu_info = { + CPU(0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"), + /* borned STP1012PGA */ + CPU(4, "Fujitsu MB86904"), + CPU(5, "Fujitsu TurboSparc MB86907"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"), + FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"), + FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"), + /* SparcStation SLC, SparcStation1 */ + FPU(3, "Weitek WTL3170/2"), + /* SPARCstation-5 */ + FPU(4, "Lsi Logic/Meiko L64804 or compatible"), + FPU(-1, NULL) + } +},{ + 1, + .cpu_info = { + /* SparcStation2, SparcServer 490 & 690 */ + CPU(0, "LSI Logic Corporation - L64811"), + /* SparcStation2 */ + CPU(1, "Cypress/ROSS CY7C601"), + /* Embedded controller */ + CPU(3, "Cypress/ROSS CY7C611"), + /* Ross Technologies HyperSparc */ + CPU(0xf, "ROSS HyperSparc RT620"), + CPU(0xe, "ROSS HyperSparc RT625 or RT626"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0, "ROSS HyperSparc combined IU/FPU"), + FPU(1, "Lsi Logic L64814"), + FPU(2, "Texas Instruments TMS390-C602A"), + FPU(3, "Cypress CY7C602 FPU"), + FPU(-1, NULL) + } +},{ + 2, + .cpu_info = { + /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ + /* Someone please write the code to support this beast! ;) */ + CPU(0, "Bipolar Integrated Technology - B5010"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(-1, NULL) + } +},{ + 3, + .cpu_info = { + CPU(0, "LSI Logic Corporation - unknown-type"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(-1, NULL) + } +},{ + 4, + .cpu_info = { + CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"), + /* SparcClassic -- borned STP1010TAB-50*/ + CPU(1, "Texas Instruments, Inc. - MicroSparc"), + CPU(2, "Texas Instruments, Inc. - MicroSparc II"), + CPU(3, "Texas Instruments, Inc. - SuperSparc 51"), + CPU(4, "Texas Instruments, Inc. - SuperSparc 61"), + CPU(5, "Texas Instruments, Inc. - unknown"), + CPU(-1, NULL) + }, + .fpu_info = { + /* SuperSparc 50 module */ + FPU(0, "SuperSparc on-chip FPU"), + /* SparcClassic */ + FPU(4, "TI MicroSparc on chip FPU"), + FPU(-1, NULL) + } +},{ + 5, + .cpu_info = { + CPU(0, "Matsushita - MN10501"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0, "Matsushita MN10501"), + FPU(-1, NULL) + } +},{ + 6, + .cpu_info = { + CPU(0, "Philips Corporation - unknown"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(-1, NULL) + } +},{ + 7, + .cpu_info = { + CPU(0, "Harvest VLSI Design Center, Inc. - unknown"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(-1, NULL) + } +},{ + 8, + .cpu_info = { + CPU(0, "Systems and Processes Engineering Corporation (SPEC)"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(-1, NULL) + } +},{ + 9, + .cpu_info = { + /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ + CPU(0, "Fujitsu or Weitek Power-UP"), + CPU(1, "Fujitsu or Weitek Power-UP"), + CPU(2, "Fujitsu or Weitek Power-UP"), + CPU(3, "Fujitsu or Weitek Power-UP"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(3, "Fujitsu or Weitek on-chip FPU"), + FPU(-1, NULL) + } +},{ + 0x17, + .cpu_info = { + CPU(0x10, "TI UltraSparc I (SpitFire)"), + CPU(0x11, "TI UltraSparc II (BlackBird)"), + CPU(0x12, "TI UltraSparc IIi (Sabre)"), + CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0x10, "UltraSparc I integrated FPU"), + FPU(0x11, "UltraSparc II integrated FPU"), + FPU(0x12, "UltraSparc IIi integrated FPU"), + FPU(0x13, "UltraSparc IIe integrated FPU"), + FPU(-1, NULL) + } +},{ + 0x22, + .cpu_info = { + CPU(0x10, "TI UltraSparc I (SpitFire)"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0x10, "UltraSparc I integrated FPU"), + FPU(-1, NULL) + } +},{ + 0x3e, + .cpu_info = { + CPU(0x14, "TI UltraSparc III (Cheetah)"), + CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), + CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), + CPU(0x18, "TI UltraSparc IV (Jaguar)"), + CPU(0x19, "TI UltraSparc IV+ (Panther)"), + CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), + CPU(-1, NULL) + }, + .fpu_info = { + FPU(0x14, "UltraSparc III integrated FPU"), + FPU(0x15, "UltraSparc III+ integrated FPU"), + FPU(0x16, "UltraSparc IIIi integrated FPU"), + FPU(0x18, "UltraSparc IV integrated FPU"), + FPU(0x19, "UltraSparc IV+ integrated FPU"), + FPU(0x22, "UltraSparc IIIi+ integrated FPU"), + FPU(-1, NULL) + } +}}; + /* In order to get the fpu type correct, you need to take the IDPROM's * machine type value into consideration too. I will fix this. */ -static struct cpu_fp_info linux_sparc_fpu[] = { - { 0, 0, "Fujitsu MB86910 or Weitek WTL1164/5"}, - { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"}, - { 0, 2, "LSI Logic L64802 or Texas Instruments ACT8847"}, - /* SparcStation SLC, SparcStation1 */ - { 0, 3, "Weitek WTL3170/2"}, - /* SPARCstation-5 */ - { 0, 4, "Lsi Logic/Meiko L64804 or compatible"}, - { 0, 5, "reserved"}, - { 0, 6, "reserved"}, - { 0, 7, "No FPU"}, - { 1, 0, "ROSS HyperSparc combined IU/FPU"}, - { 1, 1, "Lsi Logic L64814"}, - { 1, 2, "Texas Instruments TMS390-C602A"}, - { 1, 3, "Cypress CY7C602 FPU"}, - { 1, 4, "reserved"}, - { 1, 5, "reserved"}, - { 1, 6, "reserved"}, - { 1, 7, "No FPU"}, - { 2, 0, "BIT B5010 or B5110/20 or B5210"}, - { 2, 1, "reserved"}, - { 2, 2, "reserved"}, - { 2, 3, "reserved"}, - { 2, 4, "reserved"}, - { 2, 5, "reserved"}, - { 2, 6, "reserved"}, - { 2, 7, "No FPU"}, - /* SuperSparc 50 module */ - { 4, 0, "SuperSparc on-chip FPU"}, - /* SparcClassic */ - { 4, 4, "TI MicroSparc on chip FPU"}, - { 5, 0, "Matsushita MN10501"}, - { 5, 1, "reserved"}, - { 5, 2, "reserved"}, - { 5, 3, "reserved"}, - { 5, 4, "reserved"}, - { 5, 5, "reserved"}, - { 5, 6, "reserved"}, - { 5, 7, "No FPU"}, - { 9, 3, "Fujitsu or Weitek on-chip FPU"}, -}; -#define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) - -static struct cpu_iu_info linux_sparc_chips[] = { - /* Sun4/100, 4/200, SLC */ - { 0, 0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"}, - /* borned STP1012PGA */ - { 0, 4, "Fujitsu MB86904"}, - { 0, 5, "Fujitsu TurboSparc MB86907"}, - /* SparcStation2, SparcServer 490 & 690 */ - { 1, 0, "LSI Logic Corporation - L64811"}, - /* SparcStation2 */ - { 1, 1, "Cypress/ROSS CY7C601"}, - /* Embedded controller */ - { 1, 3, "Cypress/ROSS CY7C611"}, - /* Ross Technologies HyperSparc */ - { 1, 0xf, "ROSS HyperSparc RT620"}, - { 1, 0xe, "ROSS HyperSparc RT625 or RT626"}, - /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ - /* Someone please write the code to support this beast! ;) */ - { 2, 0, "Bipolar Integrated Technology - B5010"}, - { 3, 0, "LSI Logic Corporation - unknown-type"}, - { 4, 0, "Texas Instruments, Inc. - SuperSparc-(II)"}, - /* SparcClassic -- borned STP1010TAB-50*/ - { 4, 1, "Texas Instruments, Inc. - MicroSparc"}, - { 4, 2, "Texas Instruments, Inc. - MicroSparc II"}, - { 4, 3, "Texas Instruments, Inc. - SuperSparc 51"}, - { 4, 4, "Texas Instruments, Inc. - SuperSparc 61"}, - { 4, 5, "Texas Instruments, Inc. - unknown"}, - { 5, 0, "Matsushita - MN10501"}, - { 6, 0, "Philips Corporation - unknown"}, - { 7, 0, "Harvest VLSI Design Center, Inc. - unknown"}, - /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ - { 8, 0, "Systems and Processes Engineering Corporation (SPEC)"}, - { 9, 0, "Fujitsu or Weitek Power-UP"}, - { 9, 1, "Fujitsu or Weitek Power-UP"}, - { 9, 2, "Fujitsu or Weitek Power-UP"}, - { 9, 3, "Fujitsu or Weitek Power-UP"}, - { 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"}, - { 0xb, 0, "UNKNOWN CPU-VENDOR/TYPE"}, - { 0xc, 0, "UNKNOWN CPU-VENDOR/TYPE"}, - { 0xd, 0, "UNKNOWN CPU-VENDOR/TYPE"}, - { 0xe, 0, "UNKNOWN CPU-VENDOR/TYPE"}, - { 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"}, -}; +const char *sparc_cpu_type; +const char *sparc_fpu_type; -#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) +unsigned int fsr_storage; -char *sparc_cpu_type; -char *sparc_fpu_type; +static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) +{ + sparc_cpu_type = NULL; + sparc_fpu_type = NULL; + if (psr_impl < ARRAY_SIZE(manufacturer_info)) + { + const struct cpu_info *cpu; + const struct fpu_info *fpu; -unsigned int fsr_storage; + cpu = &manufacturer_info[psr_impl].cpu_info[0]; + while (cpu->psr_vers != -1) + { + if (cpu->psr_vers == psr_vers) { + sparc_cpu_type = cpu->name; + sparc_fpu_type = "No FPU"; + break; + } + cpu++; + } + fpu = &manufacturer_info[psr_impl].fpu_info[0]; + while (fpu->fp_vers != -1) + { + if (fpu->fp_vers == fpu_vers) { + sparc_fpu_type = fpu->name; + break; + } + fpu++; + } + } + if (sparc_cpu_type == NULL) + { + printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", + psr_impl, psr_vers); + sparc_cpu_type = "Unknown CPU"; + } + if (sparc_fpu_type == NULL) + { + printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", + psr_impl, fpu_vers); + sparc_fpu_type = "Unknown FPU"; + } +} +#ifdef CONFIG_SPARC32 void __cpuinit cpu_probe(void) { int psr_impl, psr_vers, fpu_vers; - int i, psr; + int psr; - psr_impl = ((get_psr()>>28)&0xf); - psr_vers = ((get_psr()>>24)&0xf); + psr_impl = ((get_psr() >> 28) & 0xf); + psr_vers = ((get_psr() >> 24) & 0xf); psr = get_psr(); put_psr(psr | PSR_EF); - fpu_vers = ((get_fsr()>>17)&0x7); + fpu_vers = ((get_fsr() >> 17) & 0x7); put_psr(psr); - for(i = 0; i<NSPARCCHIPS; i++) { - if(linux_sparc_chips[i].psr_impl == psr_impl) - if(linux_sparc_chips[i].psr_vers == psr_vers) { - sparc_cpu_type = linux_sparc_chips[i].cpu_name; - break; - } - } + set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); +} +#else +static void __init sun4v_cpu_probe(void) +{ + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + sparc_cpu_type = "UltraSparc T1 (Niagara)"; + sparc_fpu_type = "UltraSparc T1 integrated FPU"; + break; - if(i==NSPARCCHIPS) - printk("DEBUG: psr.impl = 0x%x psr.vers = 0x%x\n", psr_impl, - psr_vers); + case SUN4V_CHIP_NIAGARA2: + sparc_cpu_type = "UltraSparc T2 (Niagara2)"; + sparc_fpu_type = "UltraSparc T2 integrated FPU"; + break; - for(i = 0; i<NSPARCFPU; i++) { - if(linux_sparc_fpu[i].psr_impl == psr_impl) - if(linux_sparc_fpu[i].fp_vers == fpu_vers) { - sparc_fpu_type = linux_sparc_fpu[i].fp_name; - break; - } + default: + printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", + prom_cpu_compatible); + sparc_cpu_type = "Unknown SUN4V CPU"; + sparc_fpu_type = "Unknown SUN4V FPU"; + break; } +} + +static int __init cpu_type_probe(void) +{ + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + } else { + unsigned long ver; + int manuf, impl; - if(i == NSPARCFPU) { - printk("DEBUG: psr.impl = 0x%x fsr.vers = 0x%x\n", psr_impl, - fpu_vers); - sparc_fpu_type = linux_sparc_fpu[31].fp_name; + __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); + + manuf = ((ver >> 48) & 0xffff); + impl = ((ver >> 32) & 0xffff); + set_cpu_and_fpu(manuf, impl, impl); } + return 0; } + +arch_initcall(cpu_type_probe); +#endif diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index ad656b044b8c..b171ae8de90d 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -133,14 +133,12 @@ void __init device_scan(void) #endif /* !CONFIG_SMP */ cpu_probe(); -#ifdef CONFIG_SUN_AUXIO { extern void auxio_probe(void); extern void auxio_power_probe(void); auxio_probe(); auxio_power_probe(); } -#endif clock_stop_probe(); if (ARCH_SUN4C) diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc/kernel/ds.c index f52e0534d91d..f52e0534d91d 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc/kernel/ds.c diff --git a/arch/sparc64/kernel/dtlb_miss.S b/arch/sparc/kernel/dtlb_miss.S index 09a6a15a7105..09a6a15a7105 100644 --- a/arch/sparc64/kernel/dtlb_miss.S +++ b/arch/sparc/kernel/dtlb_miss.S diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc/kernel/dtlb_prot.S index b2c2c5be281c..b2c2c5be281c 100644 --- a/arch/sparc64/kernel/dtlb_prot.S +++ b/arch/sparc/kernel/dtlb_prot.S diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 77dbf6d45faf..77dbf6d45faf 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc/kernel/entry.h index 34d7ab5e10d2..4f53a2395ac6 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -5,9 +5,43 @@ #include <linux/types.h> #include <linux/init.h> -extern const char *sparc_cpu_type; -extern const char *sparc_fpu_type; +/* irq */ +extern void handler_irq(int irq, struct pt_regs *regs); +#ifdef CONFIG_SPARC32 +/* traps */ +extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type); +extern void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); + +extern void do_priv_instruction(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, + unsigned long npc, + unsigned long psr); +extern void do_fpd_trap(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void do_fpe_trap(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void handle_watchpoint(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void handle_reg_access(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +extern void handle_cp_exception(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); + + + +/* entry.S */ +extern void fpsave(unsigned long *fpregs, unsigned long *fsr, + void *fpqueue, unsigned long *fpqdepth); +extern void fpload(unsigned long *fpregs, unsigned long *fsr); + +#else /* CONFIG_SPARC32 */ extern void __init per_cpu_patch(void); extern void __init sun4v_patch(void); extern void __init boot_cpu_id_too_large(int cpu); @@ -188,8 +222,8 @@ struct ino_bucket { extern struct ino_bucket *ivector_table; extern unsigned long ivector_table_pa; -extern void handler_irq(int irq, struct pt_regs *regs); extern void init_irqwork_curcpu(void); extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); +#endif /* CONFIG_SPARC32 */ #endif /* _ENTRY_H */ diff --git a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap_32.S index e806fcdc46db..e806fcdc46db 100644 --- a/arch/sparc/kernel/etrap.S +++ b/arch/sparc/kernel/etrap_32.S diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc/kernel/etrap_64.S index 29ce489bc188..786b185e6e3f 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc/kernel/etrap_64.S @@ -16,9 +16,9 @@ #include <asm/mmu.h> #define TASK_REGOFF (THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ) -#define ETRAP_PSTATE1 (PSTATE_RMO | PSTATE_PRIV) +#define ETRAP_PSTATE1 (PSTATE_TSO | PSTATE_PRIV) #define ETRAP_PSTATE2 \ - (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) + (PSTATE_TSO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) /* * On entry, %g7 is return address - 0x4. @@ -130,7 +130,7 @@ etrap_save: save %g2, -STACK_BIAS, %sp stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] or %l7, %l0, %l7 - sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 + sethi %hi(TSTATE_TSO | TSTATE_PEF), %l0 or %l7, %l0, %l7 wrpr %l2, %tnpc wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate diff --git a/arch/sparc64/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S index a6864826a4bd..a6864826a4bd 100644 --- a/arch/sparc64/kernel/fpu_traps.S +++ b/arch/sparc/kernel/fpu_traps.S diff --git a/arch/sparc64/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index d0218e73f982..d0218e73f982 100644 --- a/arch/sparc64/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c diff --git a/arch/sparc64/kernel/getsetcc.S b/arch/sparc/kernel/getsetcc.S index a14d272d2061..a14d272d2061 100644 --- a/arch/sparc64/kernel/getsetcc.S +++ b/arch/sparc/kernel/getsetcc.S diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head_32.S index 51b40426f9c6..f0b4b516304f 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head_32.S @@ -990,7 +990,7 @@ sun4c_continue_boot: /* Zero out our BSS section. */ set __bss_start , %o0 ! First address of BSS - set end , %o1 ! Last address of BSS + set _end , %o1 ! Last address of BSS add %o0, 0x1, %o0 1: stb %g0, [%o0] diff --git a/arch/sparc64/kernel/head.S b/arch/sparc/kernel/head_64.S index 353226fa0239..8ffee714f932 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc/kernel/head_64.S @@ -706,7 +706,7 @@ setup_trap_table: andn %l0, PSTATE_IE, %o1 wrpr %o1, 0x0, %pstate rdpr %pil, %l1 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil /* Make the firmware call to jump over to the Linux trap table. */ sethi %hi(is_sun4v), %o0 @@ -825,8 +825,8 @@ setup_tba: restore sparc64_boot_end: -#include "etrap.S" -#include "rtrap.S" +#include "etrap_64.S" +#include "rtrap_64.S" #include "winfixup.S" #include "fpu_traps.S" #include "ivec.S" @@ -882,7 +882,7 @@ swapper_4m_tsb: ! 0x0000000000428000 -#include "systbls.S" +#include "systbls_64.S" .data .align 8 diff --git a/arch/sparc64/kernel/helpers.S b/arch/sparc/kernel/helpers.S index 314dd0c9fc5b..314dd0c9fc5b 100644 --- a/arch/sparc64/kernel/helpers.S +++ b/arch/sparc/kernel/helpers.S diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c index 1d272c3b5740..1d272c3b5740 100644 --- a/arch/sparc64/kernel/hvapi.c +++ b/arch/sparc/kernel/hvapi.c diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S index e066269d1594..8a5f35ffb15e 100644 --- a/arch/sparc64/kernel/hvcalls.S +++ b/arch/sparc/kernel/hvcalls.S @@ -766,3 +766,35 @@ ENTRY(sun4v_mmu_demap_all) retl nop ENDPROC(sun4v_mmu_demap_all) + +ENTRY(sun4v_niagara_getperf) + mov %o0, %o4 + mov HV_FAST_GET_PERFREG, %o5 + ta HV_FAST_TRAP + stx %o1, [%o4] + retl + nop +ENDPROC(sun4v_niagara_getperf) + +ENTRY(sun4v_niagara_setperf) + mov HV_FAST_SET_PERFREG, %o5 + ta HV_FAST_TRAP + retl + nop +ENDPROC(sun4v_niagara_setperf) + +ENTRY(sun4v_niagara2_getperf) + mov %o0, %o4 + mov HV_FAST_N2_GET_PERFREG, %o5 + ta HV_FAST_TRAP + stx %o1, [%o4] + retl + nop +ENDPROC(sun4v_niagara2_getperf) + +ENTRY(sun4v_niagara2_setperf) + mov HV_FAST_N2_SET_PERFREG, %o5 + ta HV_FAST_TRAP + retl + nop +ENDPROC(sun4v_niagara2_setperf) diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S index 0236c43772fa..9365432904d6 100644 --- a/arch/sparc64/kernel/hvtramp.S +++ b/arch/sparc/kernel/hvtramp.S @@ -1,6 +1,6 @@ /* hvtramp.S: Hypervisor start-cpu trampoline code. * - * Copyright (C) 2007 David S. Miller <davem@davemloft.net> + * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> */ #include <linux/init.h> @@ -14,6 +14,7 @@ #include <asm/ptrace.h> #include <asm/head.h> #include <asm/asi.h> +#include <asm/pil.h> __CPUINIT .align 8 @@ -32,7 +33,7 @@ */ hv_cpu_startup: SET_GL(0) - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil wrpr %g0, 0, %canrestore wrpr %g0, 0, %otherwin wrpr %g0, 6, %cansave diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c index 223a6582e1e2..c16135e0c151 100644 --- a/arch/sparc/kernel/idprom.c +++ b/arch/sparc/kernel/idprom.c @@ -11,35 +11,37 @@ #include <asm/oplib.h> #include <asm/idprom.h> -#include <asm/machines.h> /* Fun with Sun released architectures. */ struct idprom *idprom; static struct idprom idprom_buffer; +#ifdef CONFIG_SPARC32 +#include <asm/machines.h> /* Fun with Sun released architectures. */ + /* Here is the master table of Sun machines which use some implementation * of the Sparc CPU and have a meaningful IDPROM machtype value that we * know about. See asm-sparc/machines.h for empirical constants. */ static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = { /* First, Sun4's */ -{ "Sun 4/100 Series", (SM_SUN4 | SM_4_110) }, -{ "Sun 4/200 Series", (SM_SUN4 | SM_4_260) }, -{ "Sun 4/300 Series", (SM_SUN4 | SM_4_330) }, -{ "Sun 4/400 Series", (SM_SUN4 | SM_4_470) }, +{ .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) }, +{ .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) }, +{ .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) }, +{ .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) }, /* Now, Sun4c's */ -{ "Sun4c SparcStation 1", (SM_SUN4C | SM_4C_SS1) }, -{ "Sun4c SparcStation IPC", (SM_SUN4C | SM_4C_IPC) }, -{ "Sun4c SparcStation 1+", (SM_SUN4C | SM_4C_SS1PLUS) }, -{ "Sun4c SparcStation SLC", (SM_SUN4C | SM_4C_SLC) }, -{ "Sun4c SparcStation 2", (SM_SUN4C | SM_4C_SS2) }, -{ "Sun4c SparcStation ELC", (SM_SUN4C | SM_4C_ELC) }, -{ "Sun4c SparcStation IPX", (SM_SUN4C | SM_4C_IPX) }, +{ .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) }, +{ .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) }, +{ .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) }, +{ .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) }, +{ .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) }, +{ .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) }, +{ .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) }, /* Finally, early Sun4m's */ -{ "Sun4m SparcSystem600", (SM_SUN4M | SM_4M_SS60) }, -{ "Sun4m SparcStation10/20", (SM_SUN4M | SM_4M_SS50) }, -{ "Sun4m SparcStation5", (SM_SUN4M | SM_4M_SS40) }, +{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) }, +{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) }, +{ .name = "Sun4m SparcStation5", .id_machtype = (SM_SUN4M | SM_4M_SS40) }, /* One entry for the OBP arch's which are sun4d, sun4e, and newer sun4m's */ -{ "Sun4M OBP based system", (SM_SUN4M_OBP | 0x0) } }; +{ .name = "Sun4M OBP based system", .id_machtype = (SM_SUN4M_OBP | 0x0) } }; static void __init display_system_type(unsigned char machtype) { @@ -47,21 +49,25 @@ static void __init display_system_type(unsigned char machtype) register int i; for (i = 0; i < NUM_SUN_MACHINES; i++) { - if(Sun_Machines[i].id_machtype == machtype) { + if (Sun_Machines[i].id_machtype == machtype) { if (machtype != (SM_SUN4M_OBP | 0x00) || prom_getproperty(prom_root_node, "banner-name", sysname, sizeof(sysname)) <= 0) - printk("TYPE: %s\n", Sun_Machines[i].name); + printk(KERN_WARNING "TYPE: %s\n", + Sun_Machines[i].name); else - printk("TYPE: %s\n", sysname); + printk(KERN_WARNING "TYPE: %s\n", sysname); return; } } - prom_printf("IDPROM: Bogus id_machtype value, 0x%x\n", machtype); - prom_halt(); + prom_printf("IDPROM: Warning, bogus id_machtype value, 0x%x\n", machtype); } - +#else +static void __init display_system_type(unsigned char machtype) +{ +} +#endif /* Calculate the IDPROM checksum (xor of the data bytes). */ static unsigned char __init calc_idprom_cksum(struct idprom *idprom) { @@ -80,21 +86,14 @@ void __init idprom_init(void) idprom = &idprom_buffer; - if (idprom->id_format != 0x01) { - prom_printf("IDPROM: Unknown format type!\n"); - prom_halt(); - } + if (idprom->id_format != 0x01) + prom_printf("IDPROM: Warning, unknown format type!\n"); - if (idprom->id_cksum != calc_idprom_cksum(idprom)) { - prom_printf("IDPROM: Checksum failure (nvram=%x, calc=%x)!\n", + if (idprom->id_cksum != calc_idprom_cksum(idprom)) + prom_printf("IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n", idprom->id_cksum, calc_idprom_cksum(idprom)); - prom_halt(); - } display_system_type(idprom->id_machtype); - printk("Ethernet address: %x:%x:%x:%x:%x:%x\n", - idprom->id_ethaddr[0], idprom->id_ethaddr[1], - idprom->id_ethaddr[2], idprom->id_ethaddr[3], - idprom->id_ethaddr[4], idprom->id_ethaddr[5]); + printk(KERN_WARNING "Ethernet address: %pM\n", idprom->id_ethaddr); } diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index 8e64ebc445ef..62126e4cec54 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c @@ -23,6 +23,5 @@ EXPORT_SYMBOL(init_task); * in etrap.S which assumes it. */ union thread_union init_thread_union - __attribute__((section (".text\"\n\t#"))) - __attribute__((aligned (THREAD_SIZE))) + __attribute__((section (".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 1cc1995531e2..1cc1995531e2 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc/kernel/iommu_common.h index 591f5879039c..591f5879039c 100644 --- a/arch/sparc64/kernel/iommu_common.h +++ b/arch/sparc/kernel/iommu_common.h diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 4f025b36934b..7ce14f05eb48 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -552,8 +552,8 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, /* IIep is write-through, not flushing. */ for_each_sg(sgl, sg, nents, n) { BUG_ON(page_address(sg_page(sg)) == NULL); - sg->dvma_address = virt_to_phys(sg_virt(sg)); - sg->dvma_length = sg->length; + sg->dma_address = virt_to_phys(sg_virt(sg)); + sg->dma_length = sg->length; } return nents; } diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq_32.c index 93e1d1c65290..f3488c45d57a 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq_32.c @@ -46,6 +46,7 @@ #include <asm/cacheflush.h> #include <asm/irq_regs.h> +#include "kernel.h" #include "irq.h" #ifdef CONFIG_SMP @@ -592,19 +593,19 @@ EXPORT_SYMBOL(request_irq); void disable_irq_nosync(unsigned int irq) { - return __disable_irq(irq); + __disable_irq(irq); } EXPORT_SYMBOL(disable_irq_nosync); void disable_irq(unsigned int irq) { - return __disable_irq(irq); + __disable_irq(irq); } EXPORT_SYMBOL(disable_irq); void enable_irq(unsigned int irq) { - return __enable_irq(irq); + __enable_irq(irq); } EXPORT_SYMBOL(enable_irq); diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc/kernel/irq_64.c index 52fc836f464d..a3ea2bcb95de 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc/kernel/irq_64.c @@ -775,6 +775,69 @@ void do_softirq(void) local_irq_restore(flags); } +static void unhandled_perf_irq(struct pt_regs *regs) +{ + unsigned long pcr, pic; + + read_pcr(pcr); + read_pic(pic); + + write_pcr(0); + + printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n", + smp_processor_id()); + printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n", + smp_processor_id(), pcr, pic); +} + +/* Almost a direct copy of the powerpc PMC code. */ +static DEFINE_SPINLOCK(perf_irq_lock); +static void *perf_irq_owner_caller; /* mostly for debugging */ +static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq; + +/* Invoked from level 15 PIL handler in trap table. */ +void perfctr_irq(int irq, struct pt_regs *regs) +{ + clear_softint(1 << irq); + perf_irq(regs); +} + +int register_perfctr_intr(void (*handler)(struct pt_regs *)) +{ + int ret; + + if (!handler) + return -EINVAL; + + spin_lock(&perf_irq_lock); + if (perf_irq != unhandled_perf_irq) { + printk(KERN_WARNING "register_perfctr_intr: " + "perf IRQ busy (reserved by caller %p)\n", + perf_irq_owner_caller); + ret = -EBUSY; + goto out; + } + + perf_irq_owner_caller = __builtin_return_address(0); + perf_irq = handler; + + ret = 0; +out: + spin_unlock(&perf_irq_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(register_perfctr_intr); + +void release_perfctr_intr(void (*handler)(struct pt_regs *)) +{ + spin_lock(&perf_irq_lock); + perf_irq_owner_caller = NULL; + perf_irq = unhandled_perf_irq; + spin_unlock(&perf_irq_lock); +} +EXPORT_SYMBOL_GPL(release_perfctr_intr); + #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) { diff --git a/arch/sparc64/kernel/itlb_miss.S b/arch/sparc/kernel/itlb_miss.S index 5a8377b54955..5a8377b54955 100644 --- a/arch/sparc64/kernel/itlb_miss.S +++ b/arch/sparc/kernel/itlb_miss.S diff --git a/arch/sparc64/kernel/ivec.S b/arch/sparc/kernel/ivec.S index d29f92ebca5e..d29f92ebca5e 100644 --- a/arch/sparc64/kernel/ivec.S +++ b/arch/sparc/kernel/ivec.S diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h new file mode 100644 index 000000000000..81a972e8d8ea --- /dev/null +++ b/arch/sparc/kernel/kernel.h @@ -0,0 +1,31 @@ +#ifndef __SPARC_KERNEL_H +#define __SPARC_KERNEL_H + +#include <linux/interrupt.h> + +/* cpu.c */ +extern const char *sparc_cpu_type; +extern const char *sparc_fpu_type; + +extern unsigned int fsr_storage; + +#ifdef CONFIG_SPARC32 +/* cpu.c */ +extern void cpu_probe(void); + +/* traps_32.c */ +extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr); +/* muldiv.c */ +extern int do_user_muldiv (struct pt_regs *, unsigned long); + +/* irq_32.c */ +extern struct irqaction static_irqaction[]; +extern int static_irq_count; +extern spinlock_t irq_action_lock; + +extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); + +#else /* CONFIG_SPARC32 */ +#endif /* CONFIG_SPARC32 */ +#endif /* !(__SPARC_KERNEL_H) */ diff --git a/arch/sparc/kernel/kgdb.c b/arch/sparc/kernel/kgdb_32.c index 757805ce02ee..757805ce02ee 100644 --- a/arch/sparc/kernel/kgdb.c +++ b/arch/sparc/kernel/kgdb_32.c diff --git a/arch/sparc64/kernel/kgdb.c b/arch/sparc/kernel/kgdb_64.c index fefbe6dc51be..fefbe6dc51be 100644 --- a/arch/sparc64/kernel/kgdb.c +++ b/arch/sparc/kernel/kgdb_64.c diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index 201a6e547e4a..201a6e547e4a 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c diff --git a/arch/sparc64/kernel/kstack.h b/arch/sparc/kernel/kstack.h index 4248d969272f..4248d969272f 100644 --- a/arch/sparc64/kernel/kstack.h +++ b/arch/sparc/kernel/kstack.h diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S index cef8defcd7a9..cef8defcd7a9 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc/kernel/ktlb.S diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc/kernel/ldc.c index d68982330f66..d68982330f66 100644 --- a/arch/sparc64/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index dde52bcf5c64..3c539a6d7c18 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -11,6 +11,7 @@ #include <linux/mm.h> #include <linux/miscdevice.h> +#include <asm/cpudata.h> #include <asm/hypervisor.h> #include <asm/mdesc.h> #include <asm/prom.h> diff --git a/arch/sparc64/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S index 753b4f031bfb..753b4f031bfb 100644 --- a/arch/sparc64/kernel/misctrap.S +++ b/arch/sparc/kernel/misctrap.S diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 598682f31ebf..90273765e81f 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -1,4 +1,4 @@ -/* Kernel module help for sparc32. +/* Kernel module help for sparc64. * * Copyright (C) 2001 Rusty Russell. * Copyright (C) 2002 David S. Miller. @@ -11,6 +11,48 @@ #include <linux/fs.h> #include <linux/string.h> #include <linux/ctype.h> +#include <linux/slab.h> +#include <linux/mm.h> + +#include <asm/processor.h> +#include <asm/spitfire.h> + +#ifdef CONFIG_SPARC64 +static void *module_map(unsigned long size) +{ + struct vm_struct *area; + + size = PAGE_ALIGN(size); + if (!size || size > MODULES_LEN) + return NULL; + + area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); + if (!area) + return NULL; + + return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); +} + +static char *dot2underscore(char *name) +{ + return name; +} +#else +static void *module_map(unsigned long size) +{ + return vmalloc(size); +} + +/* Replace references to .func with _Func */ +static char *dot2underscore(char *name) +{ + if (name[0] == '.') { + name[0] = '_'; + name[1] = toupper(name[1]); + } + return name; +} +#endif /* CONFIG_SPARC64 */ void *module_alloc(unsigned long size) { @@ -20,7 +62,7 @@ void *module_alloc(unsigned long size) if (size == 0) return NULL; - ret = vmalloc(size); + ret = module_map(size); if (!ret) ret = ERR_PTR(-ENOMEM); else @@ -37,16 +79,14 @@ void module_free(struct module *mod, void *module_region) table entries. */ } -/* Make generic code ignore STT_REGISTER dummy undefined symbols, - * and replace references to .func with _Func - */ +/* Make generic code ignore STT_REGISTER dummy undefined symbols. */ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod) { unsigned int symidx; - Elf32_Sym *sym; + Elf_Sym *sym; char *strtab; int i; @@ -56,26 +96,23 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, return -ENOEXEC; } } - sym = (Elf32_Sym *)sechdrs[symidx].sh_addr; + sym = (Elf_Sym *)sechdrs[symidx].sh_addr; strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr; for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { if (sym[i].st_shndx == SHN_UNDEF) { - if (ELF32_ST_TYPE(sym[i].st_info) == STT_REGISTER) + if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER) { sym[i].st_shndx = SHN_ABS; - else { + } else { char *name = strtab + sym[i].st_name; - if (name[0] == '.') { - name[0] = '_'; - name[1] = toupper(name[1]); - } + dot2underscore(name); } } } return 0; } -int apply_relocate(Elf32_Shdr *sechdrs, +int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, @@ -86,32 +123,68 @@ int apply_relocate(Elf32_Shdr *sechdrs, return -ENOEXEC; } -int apply_relocate_add(Elf32_Shdr *sechdrs, +int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) { unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; + Elf_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf_Sym *sym; u8 *location; u32 *loc32; for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - Elf32_Addr v; + Elf_Addr v; /* This is where to make the change */ location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; loc32 = (u32 *) location; + +#ifdef CONFIG_SPARC64 + BUG_ON(((u64)location >> (u64)32) != (u64)0); +#endif /* CONFIG_SPARC64 */ + /* This is the symbol it is referring to. Note that all undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); + sym = (Elf_Sym *)sechdrs[symindex].sh_addr + + ELF_R_SYM(rel[i].r_info); v = sym->st_value + rel[i].r_addend; - switch (ELF32_R_TYPE(rel[i].r_info)) { + switch (ELF_R_TYPE(rel[i].r_info) & 0xff) { +#ifdef CONFIG_SPARC64 + case R_SPARC_64: + location[0] = v >> 56; + location[1] = v >> 48; + location[2] = v >> 40; + location[3] = v >> 32; + location[4] = v >> 24; + location[5] = v >> 16; + location[6] = v >> 8; + location[7] = v >> 0; + break; + + case R_SPARC_DISP32: + v -= (Elf_Addr) location; + *loc32 = v; + break; + + case R_SPARC_WDISP19: + v -= (Elf_Addr) location; + *loc32 = (*loc32 & ~0x7ffff) | + ((v >> 2) & 0x7ffff); + break; + + case R_SPARC_OLO10: + *loc32 = (*loc32 & ~0x1fff) | + (((v & 0x3ff) + + (ELF_R_TYPE(rel[i].r_info) >> 8)) + & 0x1fff); + break; +#endif /* CONFIG_SPARC64 */ + case R_SPARC_32: case R_SPARC_UA32: location[0] = v >> 24; @@ -121,13 +194,13 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, break; case R_SPARC_WDISP30: - v -= (Elf32_Addr) location; + v -= (Elf_Addr) location; *loc32 = (*loc32 & ~0x3fffffff) | ((v >> 2) & 0x3fffffff); break; case R_SPARC_WDISP22: - v -= (Elf32_Addr) location; + v -= (Elf_Addr) location; *loc32 = (*loc32 & ~0x3fffff) | ((v >> 2) & 0x3fffff); break; @@ -144,19 +217,38 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, default: printk(KERN_ERR "module %s: Unknown relocation: %x\n", me->name, - (int) (ELF32_R_TYPE(rel[i].r_info) & 0xff)); + (int) (ELF_R_TYPE(rel[i].r_info) & 0xff)); return -ENOEXEC; }; } return 0; } +#ifdef CONFIG_SPARC64 int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { + /* Cheetah's I-cache is fully coherent. */ + if (tlb_type == spitfire) { + unsigned long va; + + flushw_all(); + for (va = 0; va < (PAGE_SIZE << 1); va += 32) + spitfire_put_icache_tag(va, 0x0); + __asm__ __volatile__("flush %g6"); + } + return 0; } +#else +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} +#endif /* CONFIG_SPARC64 */ void module_arch_cleanup(struct module *mod) { diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c index e352239e72c8..ba960c02bb55 100644 --- a/arch/sparc/kernel/muldiv.c +++ b/arch/sparc/kernel/muldiv.c @@ -17,6 +17,8 @@ #include <asm/system.h> #include <asm/uaccess.h> +#include "kernel.h" + /* #define DEBUG_MULDIV */ static inline int has_imm13(int insn) @@ -88,9 +90,6 @@ store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs) return (put_user(result, &win->locals[reg - 16])); } } - -extern void handle_hw_divzero (struct pt_regs *regs, unsigned long pc, - unsigned long npc, unsigned long psr); /* Should return 0 if mul/div emulation succeeded and SIGILL should * not be issued. diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device_32.c index 0a83bd737654..0a83bd737654 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device_32.c diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc/kernel/of_device_64.c index 0f616ae3246c..46e231f7c5ce 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc/kernel/of_device_64.c @@ -811,20 +811,20 @@ static struct of_device * __init scan_one_device(struct device_node *dp, irq = of_get_property(dp, "interrupts", &len); if (irq) { - memcpy(op->irqs, irq, len); op->num_irqs = len / 4; + + /* Prevent overrunning the op->irqs[] array. */ + if (op->num_irqs > PROMINTR_MAX) { + printk(KERN_WARNING "%s: Too many irqs (%d), " + "limiting to %d.\n", + dp->full_name, op->num_irqs, PROMINTR_MAX); + op->num_irqs = PROMINTR_MAX; + } + memcpy(op->irqs, irq, op->num_irqs * 4); } else { op->num_irqs = 0; } - /* Prevent overrunning the op->irqs[] array. */ - if (op->num_irqs > PROMINTR_MAX) { - printk(KERN_WARNING "%s: Too many irqs (%d), " - "limiting to %d.\n", - dp->full_name, op->num_irqs, PROMINTR_MAX); - op->num_irqs = PROMINTR_MAX; - } - build_device_resources(op, parent); for (i = 0; i < op->num_irqs; i++) op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc/kernel/pci.c index bdb7c0a6d83d..bdb7c0a6d83d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc/kernel/pci.c diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index 23b88082d0b2..23b88082d0b2 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c index 9462b68f4894..9462b68f4894 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc/kernel/pci_fire.c diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index 03186824327e..03186824327e 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c index 2e680f34f727..2e680f34f727 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc/kernel/pci_msi.c diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index dfb3ec892987..dfb3ec892987 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 713257b6963c..713257b6963c 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 45d9dba1ba11..45d9dba1ba11 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 34a1fded3941..34a1fded3941 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c diff --git a/arch/sparc64/kernel/pci_sun4v.h b/arch/sparc/kernel/pci_sun4v.h index 8e9fc3a5b4f5..8e9fc3a5b4f5 100644 --- a/arch/sparc64/kernel/pci_sun4v.h +++ b/arch/sparc/kernel/pci_sun4v.h diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc/kernel/pci_sun4v_asm.S index e606d46c6815..e606d46c6815 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc/kernel/pci_sun4v_asm.S diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 462584e55fba..75ed98be3edf 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -436,7 +436,7 @@ int pcic_present(void) return pcic0_up; } -static int __init pdev_to_pnode(struct linux_pbm_info *pbm, +static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm, struct pci_dev *pdev) { struct linux_prom_pci_registers regs[PROMREG_MAX]; diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 2afcfab4f11c..5e4563d86f19 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -24,32 +24,32 @@ */ #define PMC_OBPNAME "SUNW,pmc" -#define PMC_DEVNAME "pmc" +#define PMC_DEVNAME "pmc" #define PMC_IDLE_REG 0x00 -#define PMC_IDLE_ON 0x01 +#define PMC_IDLE_ON 0x01 static u8 __iomem *regs; #define pmc_readb(offs) (sbus_readb(regs+offs)) -#define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) +#define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) -/* +/* * CPU idle callback function * See .../arch/sparc/kernel/process.c */ -void pmc_swift_idle(void) +static void pmc_swift_idle(void) { #ifdef PMC_DEBUG_LED - set_auxio(0x00, AUXIO_LED); + set_auxio(0x00, AUXIO_LED); #endif pmc_writeb(pmc_readb(PMC_IDLE_REG) | PMC_IDLE_ON, PMC_IDLE_REG); #ifdef PMC_DEBUG_LED - set_auxio(AUXIO_LED, 0x00); + set_auxio(AUXIO_LED, 0x00); #endif -} +} static int __devinit pmc_probe(struct of_device *op, const struct of_device_id *match) @@ -63,7 +63,7 @@ static int __devinit pmc_probe(struct of_device *op, #ifndef PMC_NO_IDLE /* Assign power management IDLE handler */ - pm_idle = pmc_swift_idle; + pm_idle = pmc_swift_idle; #endif printk(KERN_INFO "%s: power management initialized\n", PMC_DEVNAME); diff --git a/arch/sparc64/kernel/power.c b/arch/sparc/kernel/power.c index 076cad7f9757..076cad7f9757 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc/kernel/power.c diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process_32.c index e8c43ffe317e..69d9315f4a93 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process_32.c @@ -168,11 +168,9 @@ void machine_restart(char * cmd) void machine_power_off(void) { -#ifdef CONFIG_SUN_AUXIO if (auxio_power_register && (strcmp(of_console_device->type, "serial") || scons_pwroff)) *auxio_power_register |= AUXIO_POWER_OFF; -#endif machine_halt(); } diff --git a/arch/sparc64/kernel/process.c b/arch/sparc/kernel/process_64.c index d5e2acef9877..d5e2acef9877 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc/kernel/process_64.c diff --git a/arch/sparc/kernel/prom.h b/arch/sparc/kernel/prom.h new file mode 100644 index 000000000000..bb0f0fda6cab --- /dev/null +++ b/arch/sparc/kernel/prom.h @@ -0,0 +1,29 @@ +#ifndef __PROM_H +#define __PROM_H + +#include <linux/spinlock.h> +#include <asm/prom.h> + +extern struct device_node *allnodes; /* temporary while merging */ +extern rwlock_t devtree_lock; /* temporary while merging */ + +extern void * prom_early_alloc(unsigned long size); +extern void irq_trans_init(struct device_node *dp); + +extern unsigned int prom_unique_id; + +static inline int is_root_node(const struct device_node *dp) +{ + if (!dp) + return 0; + + return (dp->parent == NULL); +} + +extern char *build_path_component(struct device_node *dp); +extern void of_console_init(void); +extern void of_fill_in_cpu_data(void); + +extern unsigned int prom_early_allocated; + +#endif /* __PROM_H */ diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom_32.c index eee5efcfe50e..fe43e80772db 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom_32.c @@ -25,107 +25,9 @@ #include <asm/prom.h> #include <asm/oplib.h> -extern struct device_node *allnodes; /* temporary while merging */ +#include "prom.h" -extern rwlock_t devtree_lock; /* temporary while merging */ - -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->node == handle) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - -int of_getintprop_default(struct device_node *np, const char *name, int def) -{ - struct property *prop; - int len; - - prop = of_find_property(np, name, &len); - if (!prop || len != 4) - return def; - - return *(int *) prop->value; -} -EXPORT_SYMBOL(of_getintprop_default); - -DEFINE_MUTEX(of_set_property_mutex); -EXPORT_SYMBOL(of_set_property_mutex); - -int of_set_property(struct device_node *dp, const char *name, void *val, int len) -{ - struct property **prevp; - void *new_val; - int err; - - new_val = kmalloc(len, GFP_KERNEL); - if (!new_val) - return -ENOMEM; - - memcpy(new_val, val, len); - - err = -ENODEV; - - write_lock(&devtree_lock); - prevp = &dp->properties; - while (*prevp) { - struct property *prop = *prevp; - - if (!strcasecmp(prop->name, name)) { - void *old_val = prop->value; - int ret; - - mutex_lock(&of_set_property_mutex); - ret = prom_setprop(dp->node, (char *) name, val, len); - mutex_unlock(&of_set_property_mutex); - - err = -EINVAL; - if (ret >= 0) { - prop->value = new_val; - prop->length = len; - - if (OF_IS_DYNAMIC(prop)) - kfree(old_val); - - OF_MARK_DYNAMIC(prop); - - err = 0; - } - break; - } - prevp = &(*prevp)->next; - } - write_unlock(&devtree_lock); - - /* XXX Upate procfs if necessary... */ - - return err; -} -EXPORT_SYMBOL(of_set_property); - -int of_find_in_proplist(const char *list, const char *match, int len) -{ - while (len > 0) { - int l; - - if (!strcmp(list, match)) - return 1; - l = strlen(list) + 1; - list += l; - len -= l; - } - return 0; -} -EXPORT_SYMBOL(of_find_in_proplist); - -static unsigned int prom_early_allocated; - -static void * __init prom_early_alloc(unsigned long size) +void * __init prom_early_alloc(unsigned long size) { void *ret; @@ -138,14 +40,6 @@ static void * __init prom_early_alloc(unsigned long size) return ret; } -static int is_root_node(const struct device_node *dp) -{ - if (!dp) - return 0; - - return (dp->parent == NULL); -} - /* The following routines deal with the black magic of fully naming a * node. * @@ -257,7 +151,7 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf) return sparc32_path_component(dp, tmp_buf); } -static char * __init build_path_component(struct device_node *dp) +char * __init build_path_component(struct device_node *dp) { char tmp_buf[64], *n; @@ -272,164 +166,9 @@ static char * __init build_path_component(struct device_node *dp) return n; } -static char * __init build_full_name(struct device_node *dp) -{ - int len, ourlen, plen; - char *n; - - plen = strlen(dp->parent->full_name); - ourlen = strlen(dp->path_component_name); - len = ourlen + plen + 2; - - n = prom_early_alloc(len); - strcpy(n, dp->parent->full_name); - if (!is_root_node(dp->parent)) { - strcpy(n + plen, "/"); - plen++; - } - strcpy(n + plen, dp->path_component_name); - - return n; -} - -static unsigned int unique_id; - -static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) -{ - static struct property *tmp = NULL; - struct property *p; - int len; - const char *name; - - if (tmp) { - p = tmp; - memset(p, 0, sizeof(*p) + 32); - tmp = NULL; - } else { - p = prom_early_alloc(sizeof(struct property) + 32); - p->unique_id = unique_id++; - } - - p->name = (char *) (p + 1); - if (special_name) { - strcpy(p->name, special_name); - p->length = special_len; - p->value = prom_early_alloc(special_len); - memcpy(p->value, special_val, special_len); - } else { - if (prev == NULL) { - name = prom_firstprop(node, NULL); - } else { - name = prom_nextprop(node, prev, NULL); - } - if (strlen(name) == 0) { - tmp = p; - return NULL; - } - strcpy(p->name, name); - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; - } else { - p->value = prom_early_alloc(p->length + 1); - len = prom_getproperty(node, p->name, p->value, - p->length); - if (len <= 0) - p->length = 0; - ((unsigned char *)p->value)[p->length] = '\0'; - } - } - return p; -} - -static struct property * __init build_prop_list(phandle node) -{ - struct property *head, *tail; - - head = tail = build_one_prop(node, NULL, - ".node", &node, sizeof(node)); - - tail->next = build_one_prop(node, NULL, NULL, NULL, 0); - tail = tail->next; - while(tail) { - tail->next = build_one_prop(node, tail->name, - NULL, NULL, 0); - tail = tail->next; - } - - return head; -} - -static char * __init get_one_property(phandle node, char *name) -{ - char *buf = "<NULL>"; - int len; - - len = prom_getproplen(node, name); - if (len > 0) { - buf = prom_early_alloc(len); - len = prom_getproperty(node, name, buf, len); - } - - return buf; -} - -static struct device_node * __init create_node(phandle node) -{ - struct device_node *dp; - - if (!node) - return NULL; - - dp = prom_early_alloc(sizeof(*dp)); - dp->unique_id = unique_id++; - - kref_init(&dp->kref); - - dp->name = get_one_property(node, "name"); - dp->type = get_one_property(node, "device_type"); - dp->node = node; - - /* Build interrupts later... */ - - dp->properties = build_prop_list(node); - - return dp; -} - -static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) -{ - struct device_node *dp; - - dp = create_node(node); - if (dp) { - *(*nextp) = dp; - *nextp = &dp->allnext; - - dp->parent = parent; - dp->path_component_name = build_path_component(dp); - dp->full_name = build_full_name(dp); - - dp->child = build_tree(dp, prom_getchild(node), nextp); - - dp->sibling = build_tree(parent, prom_getsibling(node), nextp); - } - - return dp; -} - -struct device_node *of_console_device; -EXPORT_SYMBOL(of_console_device); - -char *of_console_path; -EXPORT_SYMBOL(of_console_path); - -char *of_console_options; -EXPORT_SYMBOL(of_console_options); - extern void restore_current(void); -static void __init of_console_init(void) +void __init of_console_init(void) { char *msg = "OF stdout device is: %s\n"; struct device_node *dp; @@ -547,20 +286,10 @@ static void __init of_console_init(void) printk(msg, of_console_path); } -void __init prom_build_devicetree(void) +void __init of_fill_in_cpu_data(void) { - struct device_node **nextp; - - allnodes = create_node(prom_root_node); - allnodes->path_component_name = ""; - allnodes->full_name = "/"; - - nextp = &allnodes->allnext; - allnodes->child = build_tree(allnodes, - prom_getchild(allnodes->node), - &nextp); - of_console_init(); +} - printk("PROM: Built device tree with %u bytes of memory.\n", - prom_early_allocated); +void __init irq_trans_init(struct device_node *dp) +{ } diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c new file mode 100644 index 000000000000..edecca7b8116 --- /dev/null +++ b/arch/sparc/kernel/prom_64.c @@ -0,0 +1,571 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc64 by David S. Miller davem@davemloft.net + * + * 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 <linux/kernel.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/lmb.h> +#include <linux/of_device.h> + +#include <asm/prom.h> +#include <asm/oplib.h> +#include <asm/irq.h> +#include <asm/asi.h> +#include <asm/upa.h> +#include <asm/smp.h> + +#include "prom.h" + +void * __init prom_early_alloc(unsigned long size) +{ + unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES); + void *ret; + + if (!paddr) { + prom_printf("prom_early_alloc(%lu) failed\n"); + prom_halt(); + } + + ret = __va(paddr); + memset(ret, 0, size); + prom_early_allocated += size; + + return ret; +} + +/* The following routines deal with the black magic of fully naming a + * node. + * + * Certain well known named nodes are just the simple name string. + * + * Actual devices have an address specifier appended to the base name + * string, like this "foo@addr". The "addr" can be in any number of + * formats, and the platform plus the type of the node determine the + * format and how it is constructed. + * + * For children of the ROOT node, the naming convention is fixed and + * determined by whether this is a sun4u or sun4v system. + * + * For children of other nodes, it is bus type specific. So + * we walk up the tree until we discover a "device_type" property + * we recognize and we go from there. + * + * As an example, the boot device on my workstation has a full path: + * + * /pci@1e,600000/ide@d/disk@0,0:c + */ +static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *rprop; + u32 high_bits, low_bits, type; + + rprop = of_find_property(dp, "reg", NULL); + if (!rprop) + return; + + regs = rprop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + type = regs->phys_addr >> 60UL; + high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL; + low_bits = (regs->phys_addr & 0xffffffffUL); + + if (type == 0 || type == 8) { + const char *prefix = (type == 0) ? "m" : "i"; + + if (low_bits) + sprintf(tmp_buf, "%s@%s%x,%x", + dp->name, prefix, + high_bits, low_bits); + else + sprintf(tmp_buf, "%s@%s%x", + dp->name, + prefix, + high_bits); + } else if (type == 12) { + sprintf(tmp_buf, "%s@%x", + dp->name, high_bits); + } +} + +static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + prop = of_find_property(dp, "portid", NULL); + if (prop) { + unsigned long mask = 0xffffffffUL; + + if (tlb_type >= cheetah) + mask = 0x7fffff; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *)prop->value, + (unsigned int) (regs->phys_addr & mask)); + } +} + +/* "name@slot,offset" */ +static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, + regs->phys_addr); +} + +/* "name@devnum[,func]" */ +static void __init pci_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_pci_registers *regs; + struct property *prop; + unsigned int devfn; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + devfn = (regs->phys_hi >> 8) & 0xff; + if (devfn & 0x07) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + devfn >> 3, + devfn & 0x07); + } else { + sprintf(tmp_buf, "%s@%x", + dp->name, + devfn >> 3); + } +} + +/* "name@UPA_PORTID,offset" */ +static void __init upa_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + return; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *) prop->value, + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@reg" */ +static void __init vdev_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x", dp->name, *regs); +} + +/* "name@addrhi,addrlo" */ +static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@bus,addr" */ +static void __init i2c_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + /* This actually isn't right... should look at the #address-cells + * property of the i2c bus node etc. etc. + */ + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); +} + +/* "name@reg0[,reg1]" */ +static void __init usb_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (prop->length == sizeof(u32) || regs[1] == 1) { + sprintf(tmp_buf, "%s@%x", + dp->name, regs[0]); + } else { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); + } +} + +/* "name@reg0reg1[,reg2reg3]" */ +static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (regs[2] || regs[3]) { + sprintf(tmp_buf, "%s@%08x%08x,%04x%08x", + dp->name, regs[0], regs[1], regs[2], regs[3]); + } else { + sprintf(tmp_buf, "%s@%08x%08x", + dp->name, regs[0], regs[1]); + } +} + +static void __init __build_path_component(struct device_node *dp, char *tmp_buf) +{ + struct device_node *parent = dp->parent; + + if (parent != NULL) { + if (!strcmp(parent->type, "pci") || + !strcmp(parent->type, "pciex")) { + pci_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "sbus")) { + sbus_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "upa")) { + upa_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "ebus")) { + ebus_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->name, "usb") || + !strcmp(parent->name, "hub")) { + usb_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "i2c")) { + i2c_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "firewire")) { + ieee1394_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "virtual-devices")) { + vdev_path_component(dp, tmp_buf); + return; + } + /* "isa" is handled with platform naming */ + } + + /* Use platform naming convention. */ + if (tlb_type == hypervisor) { + sun4v_path_component(dp, tmp_buf); + return; + } else { + sun4u_path_component(dp, tmp_buf); + } +} + +char * __init build_path_component(struct device_node *dp) +{ + char tmp_buf[64], *n; + + tmp_buf[0] = '\0'; + __build_path_component(dp, tmp_buf); + if (tmp_buf[0] == '\0') + strcpy(tmp_buf, dp->name); + + n = prom_early_alloc(strlen(tmp_buf) + 1); + strcpy(n, tmp_buf); + + return n; +} + +static const char *get_mid_prop(void) +{ + return (tlb_type == spitfire ? "upa-portid" : "portid"); +} + +struct device_node *of_find_node_by_cpuid(int cpuid) +{ + struct device_node *dp; + const char *mid_prop = get_mid_prop(); + + for_each_node_by_type(dp, "cpu") { + int id = of_getintprop_default(dp, mid_prop, -1); + const char *this_mid_prop = mid_prop; + + if (id < 0) { + this_mid_prop = "cpuid"; + id = of_getintprop_default(dp, this_mid_prop, -1); + } + + if (id < 0) { + prom_printf("OF: Serious problem, cpu lacks " + "%s property", this_mid_prop); + prom_halt(); + } + if (cpuid == id) + return dp; + } + return NULL; +} + +void __init of_fill_in_cpu_data(void) +{ + struct device_node *dp; + const char *mid_prop; + + if (tlb_type == hypervisor) + return; + + mid_prop = get_mid_prop(); + ncpus_probed = 0; + for_each_node_by_type(dp, "cpu") { + int cpuid = of_getintprop_default(dp, mid_prop, -1); + const char *this_mid_prop = mid_prop; + struct device_node *portid_parent; + int portid = -1; + + portid_parent = NULL; + if (cpuid < 0) { + this_mid_prop = "cpuid"; + cpuid = of_getintprop_default(dp, this_mid_prop, -1); + if (cpuid >= 0) { + int limit = 2; + + portid_parent = dp; + while (limit--) { + portid_parent = portid_parent->parent; + if (!portid_parent) + break; + portid = of_getintprop_default(portid_parent, + "portid", -1); + if (portid >= 0) + break; + } + } + } + + if (cpuid < 0) { + prom_printf("OF: Serious problem, cpu lacks " + "%s property", this_mid_prop); + prom_halt(); + } + + ncpus_probed++; + +#ifdef CONFIG_SMP + if (cpuid >= NR_CPUS) { + printk(KERN_WARNING "Ignoring CPU %d which is " + ">= NR_CPUS (%d)\n", + cpuid, NR_CPUS); + continue; + } +#else + /* On uniprocessor we only want the values for the + * real physical cpu the kernel booted onto, however + * cpu_data() only has one entry at index 0. + */ + if (cpuid != real_hard_smp_processor_id()) + continue; + cpuid = 0; +#endif + + cpu_data(cpuid).clock_tick = + of_getintprop_default(dp, "clock-frequency", 0); + + if (portid_parent) { + cpu_data(cpuid).dcache_size = + of_getintprop_default(dp, "l1-dcache-size", + 16 * 1024); + cpu_data(cpuid).dcache_line_size = + of_getintprop_default(dp, "l1-dcache-line-size", + 32); + cpu_data(cpuid).icache_size = + of_getintprop_default(dp, "l1-icache-size", + 8 * 1024); + cpu_data(cpuid).icache_line_size = + of_getintprop_default(dp, "l1-icache-line-size", + 32); + cpu_data(cpuid).ecache_size = + of_getintprop_default(dp, "l2-cache-size", 0); + cpu_data(cpuid).ecache_line_size = + of_getintprop_default(dp, "l2-cache-line-size", 0); + if (!cpu_data(cpuid).ecache_size || + !cpu_data(cpuid).ecache_line_size) { + cpu_data(cpuid).ecache_size = + of_getintprop_default(portid_parent, + "l2-cache-size", + (4 * 1024 * 1024)); + cpu_data(cpuid).ecache_line_size = + of_getintprop_default(portid_parent, + "l2-cache-line-size", 64); + } + + cpu_data(cpuid).core_id = portid + 1; + cpu_data(cpuid).proc_id = portid; +#ifdef CONFIG_SMP + sparc64_multi_core = 1; +#endif + } else { + cpu_data(cpuid).dcache_size = + of_getintprop_default(dp, "dcache-size", 16 * 1024); + cpu_data(cpuid).dcache_line_size = + of_getintprop_default(dp, "dcache-line-size", 32); + + cpu_data(cpuid).icache_size = + of_getintprop_default(dp, "icache-size", 16 * 1024); + cpu_data(cpuid).icache_line_size = + of_getintprop_default(dp, "icache-line-size", 32); + + cpu_data(cpuid).ecache_size = + of_getintprop_default(dp, "ecache-size", + (4 * 1024 * 1024)); + cpu_data(cpuid).ecache_line_size = + of_getintprop_default(dp, "ecache-line-size", 64); + + cpu_data(cpuid).core_id = 0; + cpu_data(cpuid).proc_id = -1; + } + +#ifdef CONFIG_SMP + cpu_set(cpuid, cpu_present_map); + cpu_set(cpuid, cpu_possible_map); +#endif + } + + smp_fill_in_sib_core_maps(); +} + +void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + const char *type; + phandle node; + + of_console_path = prom_early_alloc(256); + if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) { + prom_printf("Cannot obtain path of stdout.\n"); + prom_halt(); + } + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + node = prom_inst2pkg(prom_stdout); + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", prom_stdout); + prom_halt(); + } + + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + if (!type) { + prom_printf("Console stdout lacks device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + printk(msg, of_console_path); +} diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c new file mode 100644 index 000000000000..4e9af593db49 --- /dev/null +++ b/arch/sparc/kernel/prom_common.c @@ -0,0 +1,326 @@ +/* prom_common.c: OF device tree support common code. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc by David S. Miller davem@davemloft.net + * + * 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 <linux/kernel.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <asm/prom.h> +#include <asm/oplib.h> + +#include "prom.h" + +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +int of_getintprop_default(struct device_node *np, const char *name, int def) +{ + struct property *prop; + int len; + + prop = of_find_property(np, name, &len); + if (!prop || len != 4) + return def; + + return *(int *) prop->value; +} +EXPORT_SYMBOL(of_getintprop_default); + +DEFINE_MUTEX(of_set_property_mutex); +EXPORT_SYMBOL(of_set_property_mutex); + +int of_set_property(struct device_node *dp, const char *name, void *val, int len) +{ + struct property **prevp; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcasecmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + mutex_lock(&of_set_property_mutex); + ret = prom_setprop(dp->node, name, val, len); + mutex_unlock(&of_set_property_mutex); + + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + +int of_find_in_proplist(const char *list, const char *match, int len) +{ + while (len > 0) { + int l; + + if (!strcmp(list, match)) + return 1; + l = strlen(list) + 1; + list += l; + len -= l; + } + return 0; +} +EXPORT_SYMBOL(of_find_in_proplist); + +unsigned int prom_unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, + char *special_name, + void *special_val, + int special_len) +{ + static struct property *tmp = NULL; + struct property *p; + const char *name; + + if (tmp) { + p = tmp; + memset(p, 0, sizeof(*p) + 32); + tmp = NULL; + } else { + p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = prom_unique_id++; + } + + p->name = (char *) (p + 1); + if (special_name) { + strcpy(p->name, special_name); + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); + } else { +#ifdef CONFIG_SPARC32 + if (prev == NULL) { + name = prom_firstprop(node, NULL); + } else { + name = prom_nextprop(node, prev, NULL); + } +#else + if (prev == NULL) { + prom_firstprop(node, p->name); + } else { + prom_nextprop(node, prev, p->name); + } + name = p->name; +#endif + if (strlen(name) == 0) { + tmp = p; + return NULL; + } +#ifdef CONFIG_SPARC32 + strcpy(p->name, name); +#endif + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + int len; + + p->value = prom_early_alloc(p->length + 1); + len = prom_getproperty(node, p->name, p->value, + p->length); + if (len <= 0) + p->length = 0; + ((unsigned char *)p->value)[p->length] = '\0'; + } + } + return p; +} + +static struct property * __init build_prop_list(phandle node) +{ + struct property *head, *tail; + + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; + while(tail) { + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); + tail = tail->next; + } + + return head; +} + +static char * __init get_one_property(phandle node, const char *name) +{ + char *buf = "<NULL>"; + int len; + + len = prom_getproplen(node, name); + if (len > 0) { + buf = prom_early_alloc(len); + len = prom_getproperty(node, name, buf, len); + } + + return buf; +} + +static struct device_node * __init prom_create_node(phandle node, + struct device_node *parent) +{ + struct device_node *dp; + + if (!node) + return NULL; + + dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = prom_unique_id++; + dp->parent = parent; + + kref_init(&dp->kref); + + dp->name = get_one_property(node, "name"); + dp->type = get_one_property(node, "device_type"); + dp->node = node; + + dp->properties = build_prop_list(node); + + irq_trans_init(dp); + + return dp; +} + +static char * __init build_full_name(struct device_node *dp) +{ + int len, ourlen, plen; + char *n; + + plen = strlen(dp->parent->full_name); + ourlen = strlen(dp->path_component_name); + len = ourlen + plen + 2; + + n = prom_early_alloc(len); + strcpy(n, dp->parent->full_name); + if (!is_root_node(dp->parent)) { + strcpy(n + plen, "/"); + plen++; + } + strcpy(n + plen, dp->path_component_name); + + return n; +} + +static struct device_node * __init prom_build_tree(struct device_node *parent, + phandle node, + struct device_node ***nextp) +{ + struct device_node *ret = NULL, *prev_sibling = NULL; + struct device_node *dp; + + while (1) { + dp = prom_create_node(node, parent); + if (!dp) + break; + + if (prev_sibling) + prev_sibling->sibling = dp; + + if (!ret) + ret = dp; + prev_sibling = dp; + + *(*nextp) = dp; + *nextp = &dp->allnext; + + dp->path_component_name = build_path_component(dp); + dp->full_name = build_full_name(dp); + + dp->child = prom_build_tree(dp, prom_getchild(node), nextp); + + node = prom_getsibling(node); + } + + return ret; +} + +unsigned int prom_early_allocated __initdata; + +void __init prom_build_devicetree(void) +{ + struct device_node **nextp; + + allnodes = prom_create_node(prom_root_node, NULL); + allnodes->path_component_name = ""; + allnodes->full_name = "/"; + + nextp = &allnodes->allnext; + allnodes->child = prom_build_tree(allnodes, + prom_getchild(allnodes->node), + &nextp); + of_console_init(); + + printk("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); + + of_fill_in_cpu_data(); +} diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc/kernel/prom_irqtrans.c index dbba82f9b142..96958c4dce8e 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc/kernel/prom_irqtrans.c @@ -1,151 +1,15 @@ -/* - * Procedures for creating, accessing and interpreting the device tree. - * - * Paul Mackerras August 1996. - * Copyright (C) 1996-2005 Paul Mackerras. - * - * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. - * {engebret|bergner}@us.ibm.com - * - * Adapted for sparc64 by David S. Miller davem@davemloft.net - * - * 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 <linux/kernel.h> -#include <linux/types.h> #include <linux/string.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/lmb.h> -#include <linux/of_device.h> +#include <linux/init.h> +#include <linux/of.h> +#include <linux/of_platform.h> -#include <asm/prom.h> #include <asm/oplib.h> +#include <asm/prom.h> #include <asm/irq.h> -#include <asm/asi.h> #include <asm/upa.h> -#include <asm/smp.h> - -extern struct device_node *allnodes; /* temporary while merging */ - -extern rwlock_t devtree_lock; /* temporary while merging */ - -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - for (np = allnodes; np; np = np->allnext) - if (np->node == handle) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - -int of_getintprop_default(struct device_node *np, const char *name, int def) -{ - struct property *prop; - int len; - - prop = of_find_property(np, name, &len); - if (!prop || len != 4) - return def; - - return *(int *) prop->value; -} -EXPORT_SYMBOL(of_getintprop_default); - -DEFINE_MUTEX(of_set_property_mutex); -EXPORT_SYMBOL(of_set_property_mutex); - -int of_set_property(struct device_node *dp, const char *name, void *val, int len) -{ - struct property **prevp; - void *new_val; - int err; - - new_val = kmalloc(len, GFP_KERNEL); - if (!new_val) - return -ENOMEM; - - memcpy(new_val, val, len); - - err = -ENODEV; - - write_lock(&devtree_lock); - prevp = &dp->properties; - while (*prevp) { - struct property *prop = *prevp; - - if (!strcasecmp(prop->name, name)) { - void *old_val = prop->value; - int ret; - - mutex_lock(&of_set_property_mutex); - ret = prom_setprop(dp->node, name, val, len); - mutex_unlock(&of_set_property_mutex); - - err = -EINVAL; - if (ret >= 0) { - prop->value = new_val; - prop->length = len; - - if (OF_IS_DYNAMIC(prop)) - kfree(old_val); - - OF_MARK_DYNAMIC(prop); - - err = 0; - } - break; - } - prevp = &(*prevp)->next; - } - write_unlock(&devtree_lock); - - /* XXX Upate procfs if necessary... */ - return err; -} -EXPORT_SYMBOL(of_set_property); - -int of_find_in_proplist(const char *list, const char *match, int len) -{ - while (len > 0) { - int l; - - if (!strcmp(list, match)) - return 1; - l = strlen(list) + 1; - list += l; - len -= l; - } - return 0; -} -EXPORT_SYMBOL(of_find_in_proplist); - -static unsigned int prom_early_allocated __initdata; - -static void * __init prom_early_alloc(unsigned long size) -{ - unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES); - void *ret; - - if (!paddr) { - prom_printf("prom_early_alloc(%lu) failed\n"); - prom_halt(); - } - - ret = __va(paddr); - memset(ret, 0, size); - prom_early_allocated += size; - - return ret; -} +#include "prom.h" #ifdef CONFIG_PCI /* PSYCHO interrupt mapping support. */ @@ -936,7 +800,7 @@ static void __init sun4v_vdev_irq_trans_init(struct device_node *dp) ((regs->phys_addr >> 32UL) & 0x0fffffff); } -static void __init irq_trans_init(struct device_node *dp) +void __init irq_trans_init(struct device_node *dp) { #ifdef CONFIG_PCI const char *model; @@ -976,709 +840,3 @@ static void __init irq_trans_init(struct device_node *dp) return; } } - -static int is_root_node(const struct device_node *dp) -{ - if (!dp) - return 0; - - return (dp->parent == NULL); -} - -/* The following routines deal with the black magic of fully naming a - * node. - * - * Certain well known named nodes are just the simple name string. - * - * Actual devices have an address specifier appended to the base name - * string, like this "foo@addr". The "addr" can be in any number of - * formats, and the platform plus the type of the node determine the - * format and how it is constructed. - * - * For children of the ROOT node, the naming convention is fixed and - * determined by whether this is a sun4u or sun4v system. - * - * For children of other nodes, it is bus type specific. So - * we walk up the tree until we discover a "device_type" property - * we recognize and we go from there. - * - * As an example, the boot device on my workstation has a full path: - * - * /pci@1e,600000/ide@d/disk@0,0:c - */ -static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *rprop; - u32 high_bits, low_bits, type; - - rprop = of_find_property(dp, "reg", NULL); - if (!rprop) - return; - - regs = rprop->value; - if (!is_root_node(dp->parent)) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); - return; - } - - type = regs->phys_addr >> 60UL; - high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL; - low_bits = (regs->phys_addr & 0xffffffffUL); - - if (type == 0 || type == 8) { - const char *prefix = (type == 0) ? "m" : "i"; - - if (low_bits) - sprintf(tmp_buf, "%s@%s%x,%x", - dp->name, prefix, - high_bits, low_bits); - else - sprintf(tmp_buf, "%s@%s%x", - dp->name, - prefix, - high_bits); - } else if (type == 12) { - sprintf(tmp_buf, "%s@%x", - dp->name, high_bits); - } -} - -static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - if (!is_root_node(dp->parent)) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); - return; - } - - prop = of_find_property(dp, "upa-portid", NULL); - if (!prop) - prop = of_find_property(dp, "portid", NULL); - if (prop) { - unsigned long mask = 0xffffffffUL; - - if (tlb_type >= cheetah) - mask = 0x7fffff; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - *(u32 *)prop->value, - (unsigned int) (regs->phys_addr & mask)); - } -} - -/* "name@slot,offset" */ -static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - regs->which_io, - regs->phys_addr); -} - -/* "name@devnum[,func]" */ -static void __init pci_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom_pci_registers *regs; - struct property *prop; - unsigned int devfn; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - devfn = (regs->phys_hi >> 8) & 0xff; - if (devfn & 0x07) { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - devfn >> 3, - devfn & 0x07); - } else { - sprintf(tmp_buf, "%s@%x", - dp->name, - devfn >> 3); - } -} - -/* "name@UPA_PORTID,offset" */ -static void __init upa_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - prop = of_find_property(dp, "upa-portid", NULL); - if (!prop) - return; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - *(u32 *) prop->value, - (unsigned int) (regs->phys_addr & 0xffffffffUL)); -} - -/* "name@reg" */ -static void __init vdev_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - sprintf(tmp_buf, "%s@%x", dp->name, *regs); -} - -/* "name@addrhi,addrlo" */ -static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) -{ - struct linux_prom64_registers *regs; - struct property *prop; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - sprintf(tmp_buf, "%s@%x,%x", - dp->name, - (unsigned int) (regs->phys_addr >> 32UL), - (unsigned int) (regs->phys_addr & 0xffffffffUL)); -} - -/* "name@bus,addr" */ -static void __init i2c_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - /* This actually isn't right... should look at the #address-cells - * property of the i2c bus node etc. etc. - */ - sprintf(tmp_buf, "%s@%x,%x", - dp->name, regs[0], regs[1]); -} - -/* "name@reg0[,reg1]" */ -static void __init usb_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - if (prop->length == sizeof(u32) || regs[1] == 1) { - sprintf(tmp_buf, "%s@%x", - dp->name, regs[0]); - } else { - sprintf(tmp_buf, "%s@%x,%x", - dp->name, regs[0], regs[1]); - } -} - -/* "name@reg0reg1[,reg2reg3]" */ -static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf) -{ - struct property *prop; - u32 *regs; - - prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - - regs = prop->value; - - if (regs[2] || regs[3]) { - sprintf(tmp_buf, "%s@%08x%08x,%04x%08x", - dp->name, regs[0], regs[1], regs[2], regs[3]); - } else { - sprintf(tmp_buf, "%s@%08x%08x", - dp->name, regs[0], regs[1]); - } -} - -static void __init __build_path_component(struct device_node *dp, char *tmp_buf) -{ - struct device_node *parent = dp->parent; - - if (parent != NULL) { - if (!strcmp(parent->type, "pci") || - !strcmp(parent->type, "pciex")) { - pci_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "sbus")) { - sbus_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "upa")) { - upa_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "ebus")) { - ebus_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->name, "usb") || - !strcmp(parent->name, "hub")) { - usb_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "i2c")) { - i2c_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "firewire")) { - ieee1394_path_component(dp, tmp_buf); - return; - } - if (!strcmp(parent->type, "virtual-devices")) { - vdev_path_component(dp, tmp_buf); - return; - } - /* "isa" is handled with platform naming */ - } - - /* Use platform naming convention. */ - if (tlb_type == hypervisor) { - sun4v_path_component(dp, tmp_buf); - return; - } else { - sun4u_path_component(dp, tmp_buf); - } -} - -static char * __init build_path_component(struct device_node *dp) -{ - char tmp_buf[64], *n; - - tmp_buf[0] = '\0'; - __build_path_component(dp, tmp_buf); - if (tmp_buf[0] == '\0') - strcpy(tmp_buf, dp->name); - - n = prom_early_alloc(strlen(tmp_buf) + 1); - strcpy(n, tmp_buf); - - return n; -} - -static char * __init build_full_name(struct device_node *dp) -{ - int len, ourlen, plen; - char *n; - - plen = strlen(dp->parent->full_name); - ourlen = strlen(dp->path_component_name); - len = ourlen + plen + 2; - - n = prom_early_alloc(len); - strcpy(n, dp->parent->full_name); - if (!is_root_node(dp->parent)) { - strcpy(n + plen, "/"); - plen++; - } - strcpy(n + plen, dp->path_component_name); - - return n; -} - -static unsigned int unique_id; - -static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) -{ - static struct property *tmp = NULL; - struct property *p; - - if (tmp) { - p = tmp; - memset(p, 0, sizeof(*p) + 32); - tmp = NULL; - } else { - p = prom_early_alloc(sizeof(struct property) + 32); - p->unique_id = unique_id++; - } - - p->name = (char *) (p + 1); - if (special_name) { - strcpy(p->name, special_name); - p->length = special_len; - p->value = prom_early_alloc(special_len); - memcpy(p->value, special_val, special_len); - } else { - if (prev == NULL) { - prom_firstprop(node, p->name); - } else { - prom_nextprop(node, prev, p->name); - } - if (strlen(p->name) == 0) { - tmp = p; - return NULL; - } - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; - } else { - p->value = prom_early_alloc(p->length + 1); - prom_getproperty(node, p->name, p->value, p->length); - ((unsigned char *)p->value)[p->length] = '\0'; - } - } - return p; -} - -static struct property * __init build_prop_list(phandle node) -{ - struct property *head, *tail; - - head = tail = build_one_prop(node, NULL, - ".node", &node, sizeof(node)); - - tail->next = build_one_prop(node, NULL, NULL, NULL, 0); - tail = tail->next; - while(tail) { - tail->next = build_one_prop(node, tail->name, - NULL, NULL, 0); - tail = tail->next; - } - - return head; -} - -static char * __init get_one_property(phandle node, const char *name) -{ - char *buf = "<NULL>"; - int len; - - len = prom_getproplen(node, name); - if (len > 0) { - buf = prom_early_alloc(len); - prom_getproperty(node, name, buf, len); - } - - return buf; -} - -static struct device_node * __init create_node(phandle node, struct device_node *parent) -{ - struct device_node *dp; - - if (!node) - return NULL; - - dp = prom_early_alloc(sizeof(*dp)); - dp->unique_id = unique_id++; - dp->parent = parent; - - kref_init(&dp->kref); - - dp->name = get_one_property(node, "name"); - dp->type = get_one_property(node, "device_type"); - dp->node = node; - - dp->properties = build_prop_list(node); - - irq_trans_init(dp); - - return dp; -} - -static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) -{ - struct device_node *ret = NULL, *prev_sibling = NULL; - struct device_node *dp; - - while (1) { - dp = create_node(node, parent); - if (!dp) - break; - - if (prev_sibling) - prev_sibling->sibling = dp; - - if (!ret) - ret = dp; - prev_sibling = dp; - - *(*nextp) = dp; - *nextp = &dp->allnext; - - dp->path_component_name = build_path_component(dp); - dp->full_name = build_full_name(dp); - - dp->child = build_tree(dp, prom_getchild(node), nextp); - - node = prom_getsibling(node); - } - - return ret; -} - -static const char *get_mid_prop(void) -{ - return (tlb_type == spitfire ? "upa-portid" : "portid"); -} - -struct device_node *of_find_node_by_cpuid(int cpuid) -{ - struct device_node *dp; - const char *mid_prop = get_mid_prop(); - - for_each_node_by_type(dp, "cpu") { - int id = of_getintprop_default(dp, mid_prop, -1); - const char *this_mid_prop = mid_prop; - - if (id < 0) { - this_mid_prop = "cpuid"; - id = of_getintprop_default(dp, this_mid_prop, -1); - } - - if (id < 0) { - prom_printf("OF: Serious problem, cpu lacks " - "%s property", this_mid_prop); - prom_halt(); - } - if (cpuid == id) - return dp; - } - return NULL; -} - -static void __init of_fill_in_cpu_data(void) -{ - struct device_node *dp; - const char *mid_prop = get_mid_prop(); - - ncpus_probed = 0; - for_each_node_by_type(dp, "cpu") { - int cpuid = of_getintprop_default(dp, mid_prop, -1); - const char *this_mid_prop = mid_prop; - struct device_node *portid_parent; - int portid = -1; - - portid_parent = NULL; - if (cpuid < 0) { - this_mid_prop = "cpuid"; - cpuid = of_getintprop_default(dp, this_mid_prop, -1); - if (cpuid >= 0) { - int limit = 2; - - portid_parent = dp; - while (limit--) { - portid_parent = portid_parent->parent; - if (!portid_parent) - break; - portid = of_getintprop_default(portid_parent, - "portid", -1); - if (portid >= 0) - break; - } - } - } - - if (cpuid < 0) { - prom_printf("OF: Serious problem, cpu lacks " - "%s property", this_mid_prop); - prom_halt(); - } - - ncpus_probed++; - -#ifdef CONFIG_SMP - if (cpuid >= NR_CPUS) { - printk(KERN_WARNING "Ignoring CPU %d which is " - ">= NR_CPUS (%d)\n", - cpuid, NR_CPUS); - continue; - } -#else - /* On uniprocessor we only want the values for the - * real physical cpu the kernel booted onto, however - * cpu_data() only has one entry at index 0. - */ - if (cpuid != real_hard_smp_processor_id()) - continue; - cpuid = 0; -#endif - - cpu_data(cpuid).clock_tick = - of_getintprop_default(dp, "clock-frequency", 0); - - if (portid_parent) { - cpu_data(cpuid).dcache_size = - of_getintprop_default(dp, "l1-dcache-size", - 16 * 1024); - cpu_data(cpuid).dcache_line_size = - of_getintprop_default(dp, "l1-dcache-line-size", - 32); - cpu_data(cpuid).icache_size = - of_getintprop_default(dp, "l1-icache-size", - 8 * 1024); - cpu_data(cpuid).icache_line_size = - of_getintprop_default(dp, "l1-icache-line-size", - 32); - cpu_data(cpuid).ecache_size = - of_getintprop_default(dp, "l2-cache-size", 0); - cpu_data(cpuid).ecache_line_size = - of_getintprop_default(dp, "l2-cache-line-size", 0); - if (!cpu_data(cpuid).ecache_size || - !cpu_data(cpuid).ecache_line_size) { - cpu_data(cpuid).ecache_size = - of_getintprop_default(portid_parent, - "l2-cache-size", - (4 * 1024 * 1024)); - cpu_data(cpuid).ecache_line_size = - of_getintprop_default(portid_parent, - "l2-cache-line-size", 64); - } - - cpu_data(cpuid).core_id = portid + 1; - cpu_data(cpuid).proc_id = portid; -#ifdef CONFIG_SMP - sparc64_multi_core = 1; -#endif - } else { - cpu_data(cpuid).dcache_size = - of_getintprop_default(dp, "dcache-size", 16 * 1024); - cpu_data(cpuid).dcache_line_size = - of_getintprop_default(dp, "dcache-line-size", 32); - - cpu_data(cpuid).icache_size = - of_getintprop_default(dp, "icache-size", 16 * 1024); - cpu_data(cpuid).icache_line_size = - of_getintprop_default(dp, "icache-line-size", 32); - - cpu_data(cpuid).ecache_size = - of_getintprop_default(dp, "ecache-size", - (4 * 1024 * 1024)); - cpu_data(cpuid).ecache_line_size = - of_getintprop_default(dp, "ecache-line-size", 64); - - cpu_data(cpuid).core_id = 0; - cpu_data(cpuid).proc_id = -1; - } - -#ifdef CONFIG_SMP - cpu_set(cpuid, cpu_present_map); - cpu_set(cpuid, cpu_possible_map); -#endif - } - - smp_fill_in_sib_core_maps(); -} - -struct device_node *of_console_device; -EXPORT_SYMBOL(of_console_device); - -char *of_console_path; -EXPORT_SYMBOL(of_console_path); - -char *of_console_options; -EXPORT_SYMBOL(of_console_options); - -static void __init of_console_init(void) -{ - char *msg = "OF stdout device is: %s\n"; - struct device_node *dp; - const char *type; - phandle node; - - of_console_path = prom_early_alloc(256); - if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) { - prom_printf("Cannot obtain path of stdout.\n"); - prom_halt(); - } - of_console_options = strrchr(of_console_path, ':'); - if (of_console_options) { - of_console_options++; - if (*of_console_options == '\0') - of_console_options = NULL; - } - - node = prom_inst2pkg(prom_stdout); - if (!node) { - prom_printf("Cannot resolve stdout node from " - "instance %08x.\n", prom_stdout); - prom_halt(); - } - - dp = of_find_node_by_phandle(node); - type = of_get_property(dp, "device_type", NULL); - if (!type) { - prom_printf("Console stdout lacks device_type property.\n"); - prom_halt(); - } - - if (strcmp(type, "display") && strcmp(type, "serial")) { - prom_printf("Console device_type is neither display " - "nor serial.\n"); - prom_halt(); - } - - of_console_device = dp; - - printk(msg, of_console_path); -} - -void __init prom_build_devicetree(void) -{ - struct device_node **nextp; - - allnodes = create_node(prom_root_node, NULL); - allnodes->path_component_name = ""; - allnodes->full_name = "/"; - - nextp = &allnodes->allnext; - allnodes->child = build_tree(allnodes, - prom_getchild(allnodes->node), - &nextp); - of_console_init(); - - printk("PROM: Built device tree with %u bytes of memory.\n", - prom_early_allocated); - - if (tlb_type != hypervisor) - of_fill_in_cpu_data(); -} diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc/kernel/psycho_common.c index 790996428c14..790996428c14 100644 --- a/arch/sparc64/kernel/psycho_common.c +++ b/arch/sparc/kernel/psycho_common.c diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc/kernel/psycho_common.h index 092c278ef28d..092c278ef28d 100644 --- a/arch/sparc64/kernel/psycho_common.h +++ b/arch/sparc/kernel/psycho_common.h diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace_32.c index 8ce6285a06d5..8ce6285a06d5 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace_32.c diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc/kernel/ptrace_64.c index a941c610e7ce..a941c610e7ce 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace_64.c diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc/kernel/reboot.c index ef89d3d69748..ef89d3d69748 100644 --- a/arch/sparc64/kernel/reboot.c +++ b/arch/sparc/kernel/reboot.c diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap_32.S index 4da2e1f66290..4da2e1f66290 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap_32.S diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc/kernel/rtrap_64.S index 97a993c1f7f3..fd3cee4d117c 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -14,9 +14,9 @@ #include <asm/visasm.h> #include <asm/processor.h> -#define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) -#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) -#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) +#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) +#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) +#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) .text .align 32 @@ -132,6 +132,18 @@ __handle_signal: ba,pt %xcc, __handle_signal_continue andn %l1, %l4, %l1 + /* When returning from a NMI (%pil==15) interrupt we want to + * avoid running softirqs, doing IRQ tracing, preempting, etc. + */ + .globl rtrap_nmi +rtrap_nmi: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + and %l1, %l4, %l4 + andn %l1, %l4, %l1 + srl %l4, 20, %l4 + ba,pt %xcc, rtrap_no_irq_enable + wrpr %l4, %pil + .align 64 .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall rtrap_irq: @@ -161,8 +173,8 @@ rtrap_xcall: call trace_hardirqs_on nop wrpr %l4, %pil -rtrap_no_irq_enable: #endif +rtrap_no_irq_enable: andcc %l1, TSTATE_PRIV, %l3 bne,pn %icc, to_kernel nop diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc/kernel/sbus.c index 2ead310066d1..2ead310066d1 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc/kernel/sbus.c diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup_32.c index 24fe3078bd4b..c96c65d1b58b 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup_32.c @@ -46,6 +46,8 @@ #include <asm/cpudata.h> #include <asm/setup.h> +#include "kernel.h" + struct screen_info screen_info = { 0, 0, /* orig-x, orig-y */ 0, /* unused */ @@ -308,9 +310,6 @@ void __init setup_arch(char **cmdline_p) smp_setup_cpu_possible_map(); } -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; - static int ncpus_probed; static int show_cpuinfo(struct seq_file *m, void *__unused) @@ -328,8 +327,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) "CPU0ClkTck\t: %ld\n" #endif , - sparc_cpu_type ? sparc_cpu_type : "undetermined", - sparc_fpu_type ? sparc_fpu_type : "undetermined", + sparc_cpu_type, + sparc_fpu_type , romvec->pv_romvers, prom_rev, romvec->pv_printrev >> 16, diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc/kernel/setup_64.c index c8b03a4f68bf..555db7452ebe 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc/kernel/setup_64.c @@ -52,6 +52,7 @@ #endif #include "entry.h" +#include "kernel.h" /* Used to synchronize accesses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ba5b09ad6666..ba5b09ad6666 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal_32.c index c94f91c8b6e0..c94f91c8b6e0 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal_32.c diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc/kernel/signal_64.c index ec82d76dc6f2..ec82d76dc6f2 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc/kernel/signal_64.c diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp_32.c index e396c1f17a92..e396c1f17a92 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp_32.c diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc/kernel/smp_64.c index f500b0618bb0..bfe99d82d458 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc/kernel/smp_64.c @@ -163,7 +163,7 @@ static inline long get_delta (long *rt, long *master) for (i = 0; i < NUM_ITERS; i++) { t0 = tick_ops->get_tick(); go[MASTER] = 1; - membar_storeload(); + membar_safe("#StoreLoad"); while (!(tm = go[SLAVE])) rmb(); go[SLAVE] = 0; @@ -257,7 +257,7 @@ static void smp_synchronize_one_tick(int cpu) /* now let the client proceed into his loop */ go[MASTER] = 0; - membar_storeload(); + membar_safe("#StoreLoad"); spin_lock_irqsave(&itc_sync_lock, flags); { @@ -267,7 +267,7 @@ static void smp_synchronize_one_tick(int cpu) go[MASTER] = 0; wmb(); go[SLAVE] = tick_ops->get_tick(); - membar_storeload(); + membar_safe("#StoreLoad"); } } spin_unlock_irqrestore(&itc_sync_lock, flags); @@ -773,7 +773,7 @@ static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask /* Setup the initial cpu list. */ cnt = 0; - for_each_cpu_mask_nr(i, *mask) { + for_each_cpu(i, mask) { if (i == this_cpu || !cpu_online(i)) continue; cpu_list[cnt++] = i; @@ -1122,7 +1122,6 @@ void smp_capture(void) smp_processor_id()); #endif penguins_are_doing_time = 1; - membar_storestore_loadstore(); atomic_inc(&smp_capture_registry); smp_cross_call(&xcall_capture, 0, 0, 0); while (atomic_read(&smp_capture_registry) != ncpus) @@ -1142,13 +1141,13 @@ void smp_release(void) smp_processor_id()); #endif penguins_are_doing_time = 0; - membar_storeload_storestore(); + membar_safe("#StoreLoad"); atomic_dec(&smp_capture_registry); } } -/* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they - * can service tlb flush xcalls... +/* Imprisoned penguins run with %pil == PIL_NORMAL_MAX, but PSTATE_IE + * set, so they can service tlb flush xcalls... */ extern void prom_world(int); @@ -1161,7 +1160,7 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) __asm__ __volatile__("flushw"); prom_world(1); atomic_inc(&smp_capture_registry); - membar_storeload_storestore(); + membar_safe("#StoreLoad"); while (penguins_are_doing_time) rmb(); atomic_dec(&smp_capture_registry); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms_32.c index b0dfff848653..a4d45fc29b21 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms_32.c @@ -61,7 +61,6 @@ extern void (*bzero_1page)(void *); extern void *__bzero(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); -extern int __memcmp(const void *, const void *, __kernel_size_t); extern int __strncmp(const char *, const char *, __kernel_size_t); extern int __ashrdi3(int, int); @@ -122,10 +121,8 @@ EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(rtc_lock); -#ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); -#endif EXPORT_SYMBOL(io_remap_pfn_range); #ifndef CONFIG_SMP @@ -213,7 +210,6 @@ EXPORT_SYMBOL(bzero_1page); EXPORT_SYMBOL(__bzero); EXPORT_SYMBOL(__memscan_zero); EXPORT_SYMBOL(__memscan_generic); -EXPORT_SYMBOL(__memcmp); EXPORT_SYMBOL(__strncmp); EXPORT_SYMBOL(__memmove); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc/kernel/sparc_ksyms_64.c index 30bba8b0a3b0..0133211ab634 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms_64.c @@ -49,6 +49,7 @@ #include <asm/timer.h> #include <asm/cpudata.h> #include <asm/ftrace.h> +#include <asm/hypervisor.h> struct poll { int fd; @@ -61,7 +62,6 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern void *__bzero(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); -extern int __memcmp(const void *, const void *, __kernel_size_t); extern __kernel_size_t strlen(const char *); extern void sys_sigsuspend(void); extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); @@ -148,10 +148,13 @@ EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(__flush_dcache_range); #endif -#ifdef CONFIG_SUN_AUXIO +EXPORT_SYMBOL(sun4v_niagara_getperf); +EXPORT_SYMBOL(sun4v_niagara_setperf); +EXPORT_SYMBOL(sun4v_niagara2_getperf); +EXPORT_SYMBOL(sun4v_niagara2_setperf); + EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); -#endif #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_set_sbus64); #endif @@ -177,7 +180,6 @@ EXPORT_SYMBOL(pci_dma_supported); EXPORT_SYMBOL(io_remap_pfn_range); EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(put_fs_struct); /* math-emu wants this */ EXPORT_SYMBOL(die_if_kernel); @@ -219,7 +221,6 @@ EXPORT_SYMBOL(copy_user_page); EXPORT_SYMBOL(__bzero); EXPORT_SYMBOL(__memscan_zero); EXPORT_SYMBOL(__memscan_generic); -EXPORT_SYMBOL(__memcmp); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(csum_partial); diff --git a/arch/sparc64/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S index ef902c6f8e3c..c357e40ffd01 100644 --- a/arch/sparc64/kernel/spiterrs.S +++ b/arch/sparc/kernel/spiterrs.S @@ -80,7 +80,7 @@ __spitfire_cee_trap_continue: cmp %g2, 1 rdpr %pil, %g2 bleu,pt %xcc, 1f - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etraptl1 rd %pc, %g7 diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc/kernel/sstate.c index 8cdbe5946b43..8cdbe5946b43 100644 --- a/arch/sparc64/kernel/sstate.c +++ b/arch/sparc/kernel/sstate.c diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c index 4e21d4a57d3b..acb12f673757 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc/kernel/stacktrace.c @@ -7,17 +7,18 @@ #include "kstack.h" -void save_stack_trace(struct stack_trace *trace) +static void __save_stack_trace(struct thread_info *tp, + struct stack_trace *trace, + bool skip_sched) { - struct thread_info *tp = task_thread_info(current); unsigned long ksp, fp; - stack_trace_flush(); - - __asm__ __volatile__( - "mov %%fp, %0" - : "=r" (ksp) - ); + if (tp == current_thread_info()) { + stack_trace_flush(); + __asm__ __volatile__("mov %%fp, %0" : "=r" (ksp)); + } else { + ksp = tp->ksp; + } fp = ksp + STACK_BIAS; do { @@ -43,8 +44,21 @@ void save_stack_trace(struct stack_trace *trace) if (trace->skip > 0) trace->skip--; - else + else if (!skip_sched || !in_sched_functions(pc)) trace->entries[trace->nr_entries++] = pc; } while (trace->nr_entries < trace->max_entries); } + +void save_stack_trace(struct stack_trace *trace) +{ + __save_stack_trace(current_thread_info(), trace, false); +} EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + struct thread_info *tp = task_thread_info(tsk); + + __save_stack_trace(tp, trace, true); +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc/kernel/starfire.c index 060d0f3a6151..060d0f3a6151 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc/kernel/starfire.c diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 5dc8a5769489..bc3adbf79c6a 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -160,6 +160,7 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) sun4c_timers = (void __iomem *) (unsigned long) addr[0]; irq = of_get_property(dp, "intr", NULL); + of_node_put(dp); if (!irq) { prom_printf("sun4c_init_timers: No intr property\n"); prom_halt(); @@ -200,6 +201,7 @@ void __init sun4c_init_IRQ(void) } addr = of_get_property(dp, "address", NULL); + of_node_put(dp); if (!addr) { prom_printf("sun4c_init_IRQ: No address property\n"); prom_halt(); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index d3cb76ce418b..3369fef5b4b3 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -40,6 +40,7 @@ #include <asm/cacheflush.h> #include <asm/irq_regs.h> +#include "kernel.h" #include "irq.h" /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ @@ -58,7 +59,6 @@ static struct sun4d_timer_regs __iomem *sun4d_timers; #define TIMER_IRQ 10 #define MAX_STATIC_ALLOC 4 -extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; extern int static_irq_count; static unsigned char sbus_tid[32]; @@ -508,6 +508,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) * bootbus. */ reg = of_get_property(dp, "reg", NULL); + of_node_put(dp); if (!reg) { prom_printf("sun4d_init_timers: No reg property\n"); prom_halt(); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index f10317179ee6..301892e2d718 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -374,6 +374,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) } addr = of_get_property(dp, "address", &len); + of_node_put(dp); if (!addr) { printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n"); return; @@ -437,6 +438,7 @@ void __init sun4m_init_IRQ(void) } addr = of_get_property(dp, "address", &len); + of_node_put(dp); if (!addr) { printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); return; diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc/kernel/sun4v_ivec.S index e2f8e1b4882a..559bc5e9c199 100644 --- a/arch/sparc64/kernel/sun4v_ivec.S +++ b/arch/sparc/kernel/sun4v_ivec.S @@ -186,7 +186,7 @@ sun4v_res_mondo: * when it's done. */ rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil mov %g1, %g4 ba,pt %xcc, etrap_irq rd %pc, %g7 @@ -216,7 +216,7 @@ sun4v_res_mondo_queue_full: membar #Sync rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS @@ -297,7 +297,7 @@ sun4v_nonres_mondo: * when it's done. */ rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil mov %g1, %g4 ba,pt %xcc, etrap_irq rd %pc, %g7 @@ -327,7 +327,7 @@ sun4v_nonres_mondo_queue_full: membar #Sync rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc/kernel/sun4v_tlb_miss.S index e1fbf8c75787..e1fbf8c75787 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc/kernel/sun4v_tlb_miss.S diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc/kernel/sys32.S index f061c4dda9ef..f061c4dda9ef 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc/kernel/sys32.S diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index e800503879e4..e800503879e4 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc_32.c index 03035c852a43..03035c852a43 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc_32.c diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc_64.c index 39749e32dc7e..39749e32dc7e 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc_64.c diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 7a6786a71363..7a6786a71363 100644 --- a/arch/sparc64/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index 84e5ce146713..d28f496f4669 100644 --- a/arch/sparc64/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -8,6 +8,7 @@ #include <linux/percpu.h> #include <linux/init.h> +#include <asm/cpudata.h> #include <asm/hypervisor.h> #include <asm/spitfire.h> diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc/kernel/systbls.h index bc9f5dac4069..bc9f5dac4069 100644 --- a/arch/sparc64/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls_32.S index 7d0807586442..7d0807586442 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls_32.S diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc/kernel/systbls_64.S index 9fc78cf354bd..9fc78cf354bd 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc/kernel/systbls_64.S diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time_32.c index 00f7383c7657..00f7383c7657 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time_32.c diff --git a/arch/sparc64/kernel/time.c b/arch/sparc/kernel/time_64.c index 141da3759091..141da3759091 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc/kernel/time_64.c diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline_32.S index 5e235c52d667..5e235c52d667 100644 --- a/arch/sparc/kernel/trampoline.S +++ b/arch/sparc/kernel/trampoline_32.S diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc/kernel/trampoline_64.S index 83abd5ae88a4..da1b781b5e65 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc/kernel/trampoline_64.S @@ -109,7 +109,6 @@ startup_continue: */ sethi %hi(prom_entry_lock), %g2 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 - membar #StoreLoad | #StoreStore brnz,pn %g1, 1b nop @@ -214,7 +213,6 @@ startup_continue: sethi %hi(prom_entry_lock), %g2 stb %g0, [%g2 + %lo(prom_entry_lock)] - membar #StoreStore | #StoreLoad ba,pt %xcc, after_lock_tlb nop @@ -330,7 +328,6 @@ after_lock_tlb: sethi %hi(prom_entry_lock), %g2 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 - membar #StoreLoad | #StoreStore brnz,pn %g1, 1b nop @@ -394,7 +391,6 @@ after_lock_tlb: 3: sethi %hi(prom_entry_lock), %g2 stb %g0, [%g2 + %lo(prom_entry_lock)] - membar #StoreStore | #StoreLoad ldx [%l0], %g6 ldx [%g6 + TI_TASK], %g4 diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps_32.c index 2b7d50659036..716f3946c494 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps_32.c @@ -25,31 +25,10 @@ #include <asm/unistd.h> #include <asm/traps.h> -/* #define TRAP_DEBUG */ - -struct trap_trace_entry { - unsigned long pc; - unsigned long type; -}; - -void syscall_trace_entry(struct pt_regs *regs) -{ - printk("%s[%d]: ", current->comm, task_pid_nr(current)); - printk("scall<%d> (could be %d)\n", (int) regs->u_regs[UREG_G1], - (int) regs->u_regs[UREG_I0]); -} - -void syscall_trace_exit(struct pt_regs *regs) -{ -} +#include "entry.h" +#include "kernel.h" -void sun4d_nmi(struct pt_regs *regs) -{ - printk("Aieee: sun4d NMI received!\n"); - printk("you lose buddy boy...\n"); - show_regs(regs); - prom_halt(); -} +/* #define TRAP_DEBUG */ static void instruction_dump(unsigned long *pc) { @@ -134,7 +113,6 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type) void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { - extern int do_user_muldiv (struct pt_regs *, unsigned long); siginfo_t info; if(psr & PSR_PS) @@ -195,10 +173,6 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon send_sig_info(SIGBUS, &info, current); } -extern void fpsave(unsigned long *fpregs, unsigned long *fsr, - void *fpqueue, unsigned long *fpqdepth); -extern void fpload(unsigned long *fpregs, unsigned long *fsr); - static unsigned long init_fsr = 0x0UL; static unsigned long init_fregs[32] __attribute__ ((aligned (8))) = { ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, @@ -456,8 +430,6 @@ void do_BUG(const char *file, int line) * up here so that timer interrupts work during initialization. */ -extern void sparc_cpu_startup(void); - void trap_init(void) { extern void thread_info_offsets_are_bolixed_pete(void); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc/kernel/traps_64.c index 81ccd22e78d4..4638af2f55a0 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc/kernel/traps_64.c @@ -1371,7 +1371,6 @@ static int cheetah_fix_ce(unsigned long physaddr) __asm__ __volatile__("ldxa [%0] %3, %%g0\n\t" "ldxa [%1] %3, %%g0\n\t" "casxa [%2] %3, %%g0, %%g0\n\t" - "membar #StoreLoad | #StoreStore\n\t" "ldxa [%0] %3, %%g0\n\t" "ldxa [%1] %3, %%g0\n\t" "membar #Sync" @@ -1833,7 +1832,7 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, } } -/* We run with %pil set to 15 and PSTATE_IE enabled in %pstate. +/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate. * Log the event and clear the first word of the entry. */ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) @@ -1881,7 +1880,7 @@ void sun4v_resum_overflow(struct pt_regs *regs) atomic_inc(&sun4v_resum_oflow_cnt); } -/* We run with %pil set to 15 and PSTATE_IE enabled in %pstate. +/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate. * Log the event, clear the first word of the entry, and die. */ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset) diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc/kernel/tsb.S index c499214b501d..8c91d9b29a2f 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc/kernel/tsb.S @@ -317,7 +317,7 @@ tsb_flush: srlx %g1, 32, %o3 andcc %o3, %g2, %g0 bne,pn %icc, 1b - membar #LoadLoad + nop cmp %g1, %o1 mov 1, %o3 bne,pt %xcc, 2f @@ -327,7 +327,7 @@ tsb_flush: bne,pn %xcc, 1b nop 2: retl - TSB_MEMBAR + nop .size tsb_flush, .-tsb_flush /* Reload MMU related context switch state at @@ -478,7 +478,7 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size nop retl - TSB_MEMBAR + nop .size copy_tsb, .-copy_tsb /* Set the invalid bit in all TSB entries. */ diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc/kernel/ttable.S index 1ade3d6fb7fc..ea925503b42e 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc/kernel/ttable.S @@ -66,7 +66,7 @@ tl0_irq6: BTRAP(0x46) tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) tl0_irq14: TRAP_IRQ(timer_interrupt, 14) -tl0_irq15: TRAP_IRQ(handler_irq, 15) +tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) diff --git a/arch/sparc/kernel/una_asm.S b/arch/sparc/kernel/una_asm_32.S index 8cc03458eb7e..8cc03458eb7e 100644 --- a/arch/sparc/kernel/una_asm.S +++ b/arch/sparc/kernel/una_asm_32.S diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc/kernel/una_asm_64.S index be183fe41443..be183fe41443 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc/kernel/una_asm_64.S diff --git a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned_32.c index c2a28c5ad650..c2a28c5ad650 100644 --- a/arch/sparc/kernel/unaligned.c +++ b/arch/sparc/kernel/unaligned_32.c diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc/kernel/unaligned_64.c index 203ddfad9f27..203ddfad9f27 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc/kernel/unaligned_64.c diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c index 791c15138f3a..791c15138f3a 100644 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ b/arch/sparc/kernel/us2e_cpufreq.c diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c index 365b6464e2ce..365b6464e2ce 100644 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ b/arch/sparc/kernel/us3_cpufreq.c diff --git a/arch/sparc64/kernel/utrap.S b/arch/sparc/kernel/utrap.S index b7f0f3f3a909..b7f0f3f3a909 100644 --- a/arch/sparc64/kernel/utrap.S +++ b/arch/sparc/kernel/utrap.S diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc/kernel/vio.c index 92b1f8ec01de..92b1f8ec01de 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc/kernel/vio.c diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc/kernel/viohs.c index 708fa1705fbe..708fa1705fbe 100644 --- a/arch/sparc64/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc/kernel/visemul.c index b956fd71c131..b956fd71c131 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 5b7e69a8c32f..76267085b13b 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -1,27 +1,56 @@ -/* ld script to make SparcLinux kernel */ +/* ld script for sparc32/sparc64 kernel */ #include <asm-generic/vmlinux.lds.h> + #include <asm/page.h> +#include <asm/thread_info.h> + +#ifdef CONFIG_SPARC32 +#define INITIAL_ADDRESS 0x10000 + SIZEOF_HEADERS +#define TEXTSTART 0xf0004000 + +#define SMP_CACHE_BYTES_SHIFT 5 + +#else +#define SMP_CACHE_BYTES_SHIFT 6 +#define INITIAL_ADDRESS 0x4000 +#define TEXTSTART 0x0000000000404000 + +#endif + +#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT) +#ifdef CONFIG_SPARC32 OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") OUTPUT_ARCH(sparc) ENTRY(_start) jiffies = jiffies_64 + 4; +#else +/* sparc64 */ +OUTPUT_FORMAT("elf64-sparc", "elf64-sparc", "elf64-sparc") +OUTPUT_ARCH(sparc:v9a) +ENTRY(_start) +jiffies = jiffies_64; +#endif + SECTIONS { - . = 0x10000 + SIZEOF_HEADERS; - .text 0xf0004000 : + /* swapper_low_pmd_dir is sparc64 only */ + swapper_low_pmd_dir = 0x0000000000402000; + . = INITIAL_ADDRESS; + .text TEXTSTART : { _text = .; *(.text.head) TEXT_TEXT SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.gnu.warning) } = 0 _etext = .; - PROVIDE (etext = .); - RODATA + + RO_DATA(PAGE_SIZE) .data : { DATA_DATA CONSTRUCTORS @@ -29,25 +58,38 @@ SECTIONS .data1 : { *(.data1) } + . = ALIGN(SMP_CACHE_BYTES); + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } + . = ALIGN(SMP_CACHE_BYTES); + .data.read_mostly : { + *(.data.read_mostly) + } + /* End of data section */ _edata = .; - PROVIDE (edata = .); + /* init_task */ + . = ALIGN(THREAD_SIZE); + .data.init_task : { + *(.data.init_task) + } .fixup : { __start___fixup = .; *(.fixup) __stop___fixup = .; } + . = ALIGN(16); __ex_table : { __start___ex_table = .; *(__ex_table) __stop___ex_table = .; } - NOTES . = ALIGN(PAGE_SIZE); - __init_begin = .; .init.text : { + __init_begin = .; _sinittext = .; INIT_TEXT _einittext = .; @@ -65,7 +107,7 @@ SECTIONS .initcall.init : { __initcall_start = .; INITCALLS - __initcall_end = .; + __initcall_end = .; } .con_initcall.init : { __con_initcall_start = .; @@ -74,38 +116,61 @@ SECTIONS } SECURITY_INIT + . = ALIGN(4); + .tsb_ldquad_phys_patch : { + __tsb_ldquad_phys_patch = .; + *(.tsb_ldquad_phys_patch) + __tsb_ldquad_phys_patch_end = .; + } + + .tsb_phys_patch : { + __tsb_phys_patch = .; + *(.tsb_phys_patch) + __tsb_phys_patch_end = .; + } + + .cpuid_patch : { + __cpuid_patch = .; + *(.cpuid_patch) + __cpuid_patch_end = .; + } + + .sun4v_1insn_patch : { + __sun4v_1insn_patch = .; + *(.sun4v_1insn_patch) + __sun4v_1insn_patch_end = .; + } + .sun4v_2insn_patch : { + __sun4v_2insn_patch = .; + *(.sun4v_2insn_patch) + __sun4v_2insn_patch_end = .; + } + #ifdef CONFIG_BLK_DEV_INITRD . = ALIGN(PAGE_SIZE); .init.ramfs : { - __initramfs_start = .; + __initramfs_start = .; *(.init.ramfs) - __initramfs_end = .; + __initramfs_end = .; } #endif PERCPU(PAGE_SIZE) + . = ALIGN(PAGE_SIZE); __init_end = .; - . = ALIGN(32); - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - . = ALIGN(32); - .data.read_mostly : { - *(.data.read_mostly) - } - __bss_start = .; .sbss : { *(.sbss) - *(.scommon) } + *(.scommon) + } .bss : { *(.dynbss) *(.bss) *(COMMON) } _end = . ; - PROVIDE (end = .); + /DISCARD/ : { EXIT_TEXT EXIT_DATA diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S index a6b0863c27df..a6b0863c27df 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc/kernel/winfixup.S diff --git a/arch/sparc64/lib/GENbzero.S b/arch/sparc/lib/GENbzero.S index 6a4f956a2f7a..6a4f956a2f7a 100644 --- a/arch/sparc64/lib/GENbzero.S +++ b/arch/sparc/lib/GENbzero.S diff --git a/arch/sparc64/lib/GENcopy_from_user.S b/arch/sparc/lib/GENcopy_from_user.S index 2b9df99e87f9..2b9df99e87f9 100644 --- a/arch/sparc64/lib/GENcopy_from_user.S +++ b/arch/sparc/lib/GENcopy_from_user.S diff --git a/arch/sparc64/lib/GENcopy_to_user.S b/arch/sparc/lib/GENcopy_to_user.S index bb3f7084daf9..bb3f7084daf9 100644 --- a/arch/sparc64/lib/GENcopy_to_user.S +++ b/arch/sparc/lib/GENcopy_to_user.S diff --git a/arch/sparc64/lib/GENmemcpy.S b/arch/sparc/lib/GENmemcpy.S index 89358ee94851..89358ee94851 100644 --- a/arch/sparc64/lib/GENmemcpy.S +++ b/arch/sparc/lib/GENmemcpy.S diff --git a/arch/sparc64/lib/GENpage.S b/arch/sparc/lib/GENpage.S index 2ef9d05f21bc..2ef9d05f21bc 100644 --- a/arch/sparc64/lib/GENpage.S +++ b/arch/sparc/lib/GENpage.S diff --git a/arch/sparc64/lib/GENpatch.S b/arch/sparc/lib/GENpatch.S index fab9e89f16bd..fab9e89f16bd 100644 --- a/arch/sparc64/lib/GENpatch.S +++ b/arch/sparc/lib/GENpatch.S diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 6e303e10c3b9..375016e19144 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -1,13 +1,44 @@ # Makefile for Sparc library files.. # -EXTRA_AFLAGS := -ansi -DST_DIV0=0x02 +asflags-y := -ansi -DST_DIV0=0x02 +ccflags-y := -Werror -lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ - strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ - strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ - copy_user.o locks.o atomic.o \ - lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o \ - cmpdi2.o +lib-$(CONFIG_SPARC32) += mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o +lib-$(CONFIG_SPARC32) += memcpy.o memset.o +lib-y += strlen.o +lib-y += checksum_$(BITS).o +lib-$(CONFIG_SPARC32) += blockops.o +lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o +lib-y += strncpy_from_user_$(BITS).o strlen_user_$(BITS).o +lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o +lib-$(CONFIG_SPARC32) += copy_user.o locks.o +lib-y += atomic_$(BITS).o +lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o +lib-y += rwsem_$(BITS).o +lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o -obj-y += iomap.o atomic32.o +lib-$(CONFIG_SPARC64) += PeeCeeI.o copy_page.o clear_page.o bzero.o +lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o +lib-$(CONFIG_SPARC64) += VISsave.o +lib-$(CONFIG_SPARC64) += bitops.o + +lib-$(CONFIG_SPARC64) += U1memcpy.o U1copy_from_user.o U1copy_to_user.o + +lib-$(CONFIG_SPARC64) += U3memcpy.o U3copy_from_user.o U3copy_to_user.o +lib-$(CONFIG_SPARC64) += U3patch.o + +lib-$(CONFIG_SPARC64) += NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o +lib-$(CONFIG_SPARC64) += NGpatch.o NGpage.o NGbzero.o + +lib-$(CONFIG_SPARC64) += NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o +lib-$(CONFIG_SPARC64) += NG2patch.o NG2page.o + +lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o +lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o + +lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o +lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o + +obj-y += iomap.o +obj-$(CONFIG_SPARC32) += atomic32.o diff --git a/arch/sparc64/lib/NG2copy_from_user.S b/arch/sparc/lib/NG2copy_from_user.S index c77ef5f22102..c77ef5f22102 100644 --- a/arch/sparc64/lib/NG2copy_from_user.S +++ b/arch/sparc/lib/NG2copy_from_user.S diff --git a/arch/sparc64/lib/NG2copy_to_user.S b/arch/sparc/lib/NG2copy_to_user.S index 4bd4093acbbd..4bd4093acbbd 100644 --- a/arch/sparc64/lib/NG2copy_to_user.S +++ b/arch/sparc/lib/NG2copy_to_user.S diff --git a/arch/sparc64/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S index 0aed75653b50..0aed75653b50 100644 --- a/arch/sparc64/lib/NG2memcpy.S +++ b/arch/sparc/lib/NG2memcpy.S diff --git a/arch/sparc64/lib/NG2page.S b/arch/sparc/lib/NG2page.S index 73b6b7c72cbf..73b6b7c72cbf 100644 --- a/arch/sparc64/lib/NG2page.S +++ b/arch/sparc/lib/NG2page.S diff --git a/arch/sparc64/lib/NG2patch.S b/arch/sparc/lib/NG2patch.S index 28c36f06a6d1..28c36f06a6d1 100644 --- a/arch/sparc64/lib/NG2patch.S +++ b/arch/sparc/lib/NG2patch.S diff --git a/arch/sparc64/lib/NGbzero.S b/arch/sparc/lib/NGbzero.S index 814d5f7a45e1..814d5f7a45e1 100644 --- a/arch/sparc64/lib/NGbzero.S +++ b/arch/sparc/lib/NGbzero.S diff --git a/arch/sparc64/lib/NGcopy_from_user.S b/arch/sparc/lib/NGcopy_from_user.S index e7f433f71b42..e7f433f71b42 100644 --- a/arch/sparc64/lib/NGcopy_from_user.S +++ b/arch/sparc/lib/NGcopy_from_user.S diff --git a/arch/sparc64/lib/NGcopy_to_user.S b/arch/sparc/lib/NGcopy_to_user.S index 6ea01c5532a0..6ea01c5532a0 100644 --- a/arch/sparc64/lib/NGcopy_to_user.S +++ b/arch/sparc/lib/NGcopy_to_user.S diff --git a/arch/sparc64/lib/NGmemcpy.S b/arch/sparc/lib/NGmemcpy.S index 96a14caf6966..96a14caf6966 100644 --- a/arch/sparc64/lib/NGmemcpy.S +++ b/arch/sparc/lib/NGmemcpy.S diff --git a/arch/sparc64/lib/NGpage.S b/arch/sparc/lib/NGpage.S index 428920de05ba..428920de05ba 100644 --- a/arch/sparc64/lib/NGpage.S +++ b/arch/sparc/lib/NGpage.S diff --git a/arch/sparc64/lib/NGpatch.S b/arch/sparc/lib/NGpatch.S index 3b0674fc3366..3b0674fc3366 100644 --- a/arch/sparc64/lib/NGpatch.S +++ b/arch/sparc/lib/NGpatch.S diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc/lib/PeeCeeI.c index 46053e6ddd7b..46053e6ddd7b 100644 --- a/arch/sparc64/lib/PeeCeeI.c +++ b/arch/sparc/lib/PeeCeeI.c diff --git a/arch/sparc64/lib/U1copy_from_user.S b/arch/sparc/lib/U1copy_from_user.S index 3192b0bf4fab..3192b0bf4fab 100644 --- a/arch/sparc64/lib/U1copy_from_user.S +++ b/arch/sparc/lib/U1copy_from_user.S diff --git a/arch/sparc64/lib/U1copy_to_user.S b/arch/sparc/lib/U1copy_to_user.S index d1210ffb0b82..d1210ffb0b82 100644 --- a/arch/sparc64/lib/U1copy_to_user.S +++ b/arch/sparc/lib/U1copy_to_user.S diff --git a/arch/sparc64/lib/U1memcpy.S b/arch/sparc/lib/U1memcpy.S index bafd2fc07acb..bafd2fc07acb 100644 --- a/arch/sparc64/lib/U1memcpy.S +++ b/arch/sparc/lib/U1memcpy.S diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc/lib/U3copy_from_user.S index f5bfc8d9d216..f5bfc8d9d216 100644 --- a/arch/sparc64/lib/U3copy_from_user.S +++ b/arch/sparc/lib/U3copy_from_user.S diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc/lib/U3copy_to_user.S index 2334f111bb0c..2334f111bb0c 100644 --- a/arch/sparc64/lib/U3copy_to_user.S +++ b/arch/sparc/lib/U3copy_to_user.S diff --git a/arch/sparc64/lib/U3memcpy.S b/arch/sparc/lib/U3memcpy.S index 7cae9cc6a204..7cae9cc6a204 100644 --- a/arch/sparc64/lib/U3memcpy.S +++ b/arch/sparc/lib/U3memcpy.S diff --git a/arch/sparc64/lib/U3patch.S b/arch/sparc/lib/U3patch.S index ecc302619a6e..ecc302619a6e 100644 --- a/arch/sparc64/lib/U3patch.S +++ b/arch/sparc/lib/U3patch.S diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc/lib/VISsave.S index b320ae9e2e2e..b320ae9e2e2e 100644 --- a/arch/sparc64/lib/VISsave.S +++ b/arch/sparc/lib/VISsave.S diff --git a/arch/sparc/lib/atomic.S b/arch/sparc/lib/atomic_32.S index 178cbb8ae1b9..178cbb8ae1b9 100644 --- a/arch/sparc/lib/atomic.S +++ b/arch/sparc/lib/atomic_32.S diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc/lib/atomic_64.S index 70ac4186f62b..0268210ca168 100644 --- a/arch/sparc64/lib/atomic.S +++ b/arch/sparc/lib/atomic_64.S @@ -43,29 +43,10 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_sub, .-atomic_sub - /* On SMP we need to use memory barriers to ensure - * correct memory operation ordering, nop these out - * for uniprocessor. - */ -#ifdef CONFIG_SMP - -#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad; -#define ATOMIC_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop -#else -#define ATOMIC_PRE_BARRIER -#define ATOMIC_POST_BARRIER -#endif - .globl atomic_add_ret .type atomic_add_ret,#function atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) - ATOMIC_PRE_BARRIER 1: lduw [%o1], %g1 add %g1, %o0, %g7 cas [%o1], %g1, %g7 @@ -73,7 +54,6 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ bne,pn %icc, 2f add %g7, %o0, %g7 sra %g7, 0, %o0 - ATOMIC_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o2, %o3, 1b) @@ -83,7 +63,6 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ .type atomic_sub_ret,#function atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) - ATOMIC_PRE_BARRIER 1: lduw [%o1], %g1 sub %g1, %o0, %g7 cas [%o1], %g1, %g7 @@ -91,7 +70,6 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ bne,pn %icc, 2f sub %g7, %o0, %g7 sra %g7, 0, %o0 - ATOMIC_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o2, %o3, 1b) @@ -131,7 +109,6 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */ .type atomic64_add_ret,#function atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) - ATOMIC_PRE_BARRIER 1: ldx [%o1], %g1 add %g1, %o0, %g7 casx [%o1], %g1, %g7 @@ -139,7 +116,6 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ bne,pn %xcc, 2f add %g7, %o0, %g7 mov %g7, %o0 - ATOMIC_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o2, %o3, 1b) @@ -149,7 +125,6 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ .type atomic64_sub_ret,#function atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) - ATOMIC_PRE_BARRIER 1: ldx [%o1], %g1 sub %g1, %o0, %g7 casx [%o1], %g1, %g7 @@ -157,7 +132,6 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ bne,pn %xcc, 2f sub %g7, %o0, %g7 mov %g7, %o0 - ATOMIC_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o2, %o3, 1b) diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc/lib/bitops.S index 6b015a6eefb5..2b7228cb8c22 100644 --- a/arch/sparc64/lib/bitops.S +++ b/arch/sparc/lib/bitops.S @@ -8,29 +8,10 @@ .text - /* On SMP we need to use memory barriers to ensure - * correct memory operation ordering, nop these out - * for uniprocessor. - */ - -#ifdef CONFIG_SMP -#define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad -#define BITOP_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop -#else -#define BITOP_PRE_BARRIER -#define BITOP_POST_BARRIER -#endif - .globl test_and_set_bit .type test_and_set_bit,#function test_and_set_bit: /* %o0=nr, %o1=addr */ BACKOFF_SETUP(%o3) - BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -45,7 +26,6 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 - BITOP_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o3, %o4, 1b) @@ -55,7 +35,6 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ .type test_and_clear_bit,#function test_and_clear_bit: /* %o0=nr, %o1=addr */ BACKOFF_SETUP(%o3) - BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -70,7 +49,6 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 - BITOP_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o3, %o4, 1b) @@ -80,7 +58,6 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ .type test_and_change_bit,#function test_and_change_bit: /* %o0=nr, %o1=addr */ BACKOFF_SETUP(%o3) - BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -95,7 +72,6 @@ test_and_change_bit: /* %o0=nr, %o1=addr */ and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 - BITOP_POST_BARRIER retl nop 2: BACKOFF_SPIN(%o3, %o4, 1b) diff --git a/arch/sparc64/lib/bzero.S b/arch/sparc/lib/bzero.S index c7bbae8c590f..c7bbae8c590f 100644 --- a/arch/sparc64/lib/bzero.S +++ b/arch/sparc/lib/bzero.S diff --git a/arch/sparc/lib/checksum.S b/arch/sparc/lib/checksum_32.S index 77f228533d47..77f228533d47 100644 --- a/arch/sparc/lib/checksum.S +++ b/arch/sparc/lib/checksum_32.S diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc/lib/checksum_64.S index 1d230f693dc4..1d230f693dc4 100644 --- a/arch/sparc64/lib/checksum.S +++ b/arch/sparc/lib/checksum_64.S diff --git a/arch/sparc64/lib/clear_page.S b/arch/sparc/lib/clear_page.S index 77e531f6c2a7..77e531f6c2a7 100644 --- a/arch/sparc64/lib/clear_page.S +++ b/arch/sparc/lib/clear_page.S diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S index 650af3f21f78..650af3f21f78 100644 --- a/arch/sparc64/lib/copy_in_user.S +++ b/arch/sparc/lib/copy_in_user.S diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc/lib/copy_page.S index b243d3b606ba..b243d3b606ba 100644 --- a/arch/sparc64/lib/copy_page.S +++ b/arch/sparc/lib/copy_page.S diff --git a/arch/sparc64/lib/csum_copy.S b/arch/sparc/lib/csum_copy.S index e566c770a0f6..e566c770a0f6 100644 --- a/arch/sparc64/lib/csum_copy.S +++ b/arch/sparc/lib/csum_copy.S diff --git a/arch/sparc64/lib/csum_copy_from_user.S b/arch/sparc/lib/csum_copy_from_user.S index a22eddbe5dba..a22eddbe5dba 100644 --- a/arch/sparc64/lib/csum_copy_from_user.S +++ b/arch/sparc/lib/csum_copy_from_user.S diff --git a/arch/sparc64/lib/csum_copy_to_user.S b/arch/sparc/lib/csum_copy_to_user.S index d5b12f441f02..d5b12f441f02 100644 --- a/arch/sparc64/lib/csum_copy_to_user.S +++ b/arch/sparc/lib/csum_copy_to_user.S diff --git a/arch/sparc64/lib/ipcsum.S b/arch/sparc/lib/ipcsum.S index 58ca5b9a8778..58ca5b9a8778 100644 --- a/arch/sparc64/lib/ipcsum.S +++ b/arch/sparc/lib/ipcsum.S diff --git a/arch/sparc64/lib/mcount.S b/arch/sparc/lib/mcount.S index 7ce9c65f3592..7ce9c65f3592 100644 --- a/arch/sparc64/lib/mcount.S +++ b/arch/sparc/lib/mcount.S diff --git a/arch/sparc/lib/memcmp.S b/arch/sparc/lib/memcmp.S index cb4bdb0cc2af..efa106c41ed0 100644 --- a/arch/sparc/lib/memcmp.S +++ b/arch/sparc/lib/memcmp.S @@ -1,312 +1,27 @@ - .text - .align 4 - .global __memcmp, memcmp -__memcmp: -memcmp: -#if 1 - cmp %o2, 0 - ble L3 - mov 0, %g3 -L5: - ldub [%o0], %g2 - ldub [%o1], %g3 - sub %g2, %g3, %g2 - mov %g2, %g3 - sll %g2, 24, %g2 - - cmp %g2, 0 - bne L3 - add %o0, 1, %o0 +/* Sparc optimized memcmp code. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 2000, 2008 David S. Miller (davem@davemloft.net) + */ - add %o2, -1, %o2 +#include <linux/linkage.h> +#include <asm/asm.h> + .text +ENTRY(memcmp) cmp %o2, 0 - bg L5 - add %o1, 1, %o1 -L3: - sll %g3, 24, %o0 - sra %o0, 24, %o0 - - retl +1: BRANCH32(be, pn, 2f) nop -#else - save %sp, -104, %sp - mov %i2, %o4 - mov %i0, %o0 - - cmp %o4, 15 - ble L72 - mov %i1, %i2 - - andcc %i2, 3, %g0 - be L161 - andcc %o0, 3, %g2 -L75: - ldub [%o0], %g3 - ldub [%i2], %g2 - add %o0,1, %o0 - - subcc %g3, %g2, %i0 - bne L156 - add %i2, 1, %i2 - - andcc %i2, 3, %g0 - bne L75 - add %o4, -1, %o4 - - andcc %o0, 3, %g2 -L161: - bne,a L78 - mov %i2, %i1 - - mov %o0, %i5 - mov %i2, %i3 - srl %o4, 2, %i4 - - cmp %i4, 0 - bge L93 - mov %i4, %g2 - - add %i4, 3, %g2 -L93: - sra %g2, 2, %g2 - sll %g2, 2, %g2 - sub %i4, %g2, %g2 - - cmp %g2, 1 - be,a L88 - add %o0, 4, %i5 - - bg L94 - cmp %g2, 2 - - cmp %g2, 0 - be,a L86 - ld [%o0], %g3 - - b L162 - ld [%i5], %g3 -L94: - be L81 - cmp %g2, 3 - - be,a L83 - add %o0, -4, %i5 - - b L162 - ld [%i5], %g3 -L81: - add %o0, -8, %i5 - ld [%o0], %g3 - add %i2, -8, %i3 - ld [%i2], %g2 - - b L82 - add %i4, 2, %i4 -L83: - ld [%o0], %g4 - add %i2, -4, %i3 - ld [%i2], %g1 - - b L84 - add %i4, 1, %i4 -L86: - b L87 - ld [%i2], %g2 -L88: - add %i2, 4, %i3 - ld [%o0], %g4 - add %i4, -1, %i4 - ld [%i2], %g1 -L95: - ld [%i5], %g3 -L162: - cmp %g4, %g1 - be L87 - ld [%i3], %g2 - - cmp %g4, %g1 -L163: - bleu L114 - mov -1, %i0 - - b L114 - mov 1, %i0 -L87: - ld [%i5 + 4], %g4 - cmp %g3, %g2 - bne L163 - ld [%i3 + 4], %g1 -L84: - ld [%i5 + 8], %g3 - - cmp %g4, %g1 - bne L163 - ld [%i3 + 8], %g2 -L82: - ld [%i5 + 12], %g4 - cmp %g3, %g2 - bne L163 - ld [%i3 + 12], %g1 - - add %i5, 16, %i5 - - addcc %i4, -4, %i4 - bne L95 - add %i3, 16, %i3 - - cmp %g4, %g1 - bne L163 - nop - - b L114 - mov 0, %i0 -L78: - srl %o4, 2, %i0 - and %o0, -4, %i3 - orcc %i0, %g0, %g3 - sll %g2, 3, %o7 - mov 32, %g2 - - bge L129 - sub %g2, %o7, %o1 - - add %i0, 3, %g3 -L129: - sra %g3, 2, %g2 - sll %g2, 2, %g2 - sub %i0, %g2, %g2 - - cmp %g2, 1 - be,a L124 - ld [%i3], %o3 - - bg L130 - cmp %g2, 2 - - cmp %g2, 0 - be,a L122 - ld [%i3], %o2 - - b L164 - sll %o3, %o7, %g3 -L130: - be L117 - cmp %g2, 3 - - be,a L119 - ld [%i3], %g1 - - b L164 - sll %o3, %o7, %g3 -L117: - ld [%i3], %g4 - add %i2, -8, %i1 - ld [%i3 + 4], %o3 - add %i0, 2, %i0 - ld [%i2], %i4 - - b L118 - add %i3, -4, %i3 -L119: - ld [%i3 + 4], %g4 - add %i2, -4, %i1 - ld [%i2], %i5 - - b L120 - add %i0, 1, %i0 -L122: - ld [%i3 + 4], %g1 - ld [%i2], %i4 - - b L123 - add %i3, 4, %i3 -L124: - add %i2, 4, %i1 - ld [%i3 + 4], %o2 - add %i0, -1, %i0 - ld [%i2], %i5 - add %i3, 8, %i3 -L131: - sll %o3, %o7, %g3 -L164: - srl %o2, %o1, %g2 - ld [%i3], %g1 - or %g3, %g2, %g3 - - cmp %g3, %i5 - bne L163 - ld [%i1], %i4 -L123: - sll %o2, %o7, %g3 - srl %g1, %o1, %g2 - ld [%i3 + 4], %g4 - or %g3, %g2, %g3 - - cmp %g3, %i4 - bne L163 - ld [%i1 + 4], %i5 -L120: - sll %g1, %o7, %g3 - srl %g4, %o1, %g2 - ld [%i3 + 8], %o3 - or %g3, %g2, %g3 - - cmp %g3, %i5 - bne L163 - ld [%i1 + 8], %i4 -L118: - sll %g4, %o7, %g3 - srl %o3, %o1, %g2 - ld [%i3 + 12], %o2 - or %g3, %g2, %g3 - - cmp %g3, %i4 - bne L163 - ld [%i1 + 12], %i5 - - add %i3, 16, %i3 - addcc %i0, -4, %i0 - bne L131 - add %i1, 16, %i1 - - sll %o3, %o7, %g3 - srl %o2, %o1, %g2 - or %g3, %g2, %g3 - - cmp %g3, %i5 - be,a L114 - mov 0, %i0 - - b,a L163 -L114: - cmp %i0, 0 - bne L156 - and %o4, -4, %g2 - - add %o0, %g2, %o0 - add %i2, %g2, %i2 - and %o4, 3, %o4 -L72: - cmp %o4, 0 - be L156 - mov 0, %i0 - - ldub [%o0], %g3 -L165: - ldub [%i2], %g2 + ldub [%o0], %g7 + ldub [%o1], %g3 + sub %o2, 1, %o2 add %o0, 1, %o0 - - subcc %g3, %g2, %i0 - bne L156 - add %i2, 1, %i2 - - addcc %o4, -1, %o4 - bne,a L165 - ldub [%o0], %g3 - - mov 0, %i0 -L156: - ret - restore -#endif + add %o1, 1, %o1 + subcc %g7, %g3, %g3 + BRANCH32(be, pt, 1b) + cmp %o2, 0 + retl + mov %g3, %o0 +2: retl + mov 0, %o0 +ENDPROC(memcmp) diff --git a/arch/sparc64/lib/memmove.S b/arch/sparc/lib/memmove.S index 97395802c23c..97395802c23c 100644 --- a/arch/sparc64/lib/memmove.S +++ b/arch/sparc/lib/memmove.S diff --git a/arch/sparc/lib/memscan.S b/arch/sparc/lib/memscan_32.S index 4ff1657dfc24..4ff1657dfc24 100644 --- a/arch/sparc/lib/memscan.S +++ b/arch/sparc/lib/memscan_32.S diff --git a/arch/sparc64/lib/memscan.S b/arch/sparc/lib/memscan_64.S index 5686dfa5dc15..5686dfa5dc15 100644 --- a/arch/sparc64/lib/memscan.S +++ b/arch/sparc/lib/memscan_64.S diff --git a/arch/sparc/lib/rwsem.S b/arch/sparc/lib/rwsem_32.S index 9675268e7fde..9675268e7fde 100644 --- a/arch/sparc/lib/rwsem.S +++ b/arch/sparc/lib/rwsem_32.S diff --git a/arch/sparc64/lib/rwsem.S b/arch/sparc/lib/rwsem_64.S index 1a4cc5654de4..91a7d29a79d5 100644 --- a/arch/sparc64/lib/rwsem.S +++ b/arch/sparc/lib/rwsem_64.S @@ -17,7 +17,6 @@ __down_read: bne,pn %icc, 1b add %g7, 1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f nop 2: @@ -42,7 +41,6 @@ __down_read_trylock: cmp %g1, %g7 bne,pn %icc, 1b mov 1, %o1 - membar #StoreLoad | #StoreStore 2: retl mov %o1, %o0 .size __down_read_trylock, .-__down_read_trylock @@ -58,7 +56,6 @@ __down_write: cmp %g3, %g7 bne,pn %icc, 1b cmp %g7, 0 - membar #StoreLoad | #StoreStore bne,pn %icc, 3f nop 2: retl @@ -85,7 +82,6 @@ __down_write_trylock: cmp %g3, %g7 bne,pn %icc, 1b mov 1, %o1 - membar #StoreLoad | #StoreStore 2: retl mov %o1, %o0 .size __down_write_trylock, .-__down_write_trylock @@ -99,7 +95,6 @@ __up_read: cmp %g1, %g7 bne,pn %icc, 1b cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f nop 2: retl @@ -129,7 +124,6 @@ __up_write: bne,pn %icc, 1b sub %g7, %g1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f nop 2: @@ -155,7 +149,6 @@ __downgrade_write: bne,pn %icc, 1b sub %g7, %g1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f nop 2: diff --git a/arch/sparc/lib/strlen.S b/arch/sparc/lib/strlen.S index ed9a763368cd..536f83507fbf 100644 --- a/arch/sparc/lib/strlen.S +++ b/arch/sparc/lib/strlen.S @@ -1,51 +1,40 @@ /* strlen.S: Sparc optimized strlen code * Hand optimized from GNU libc's strlen * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996,2008 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include <linux/linkage.h> +#include <asm/asm.h> + #define LO_MAGIC 0x01010101 #define HI_MAGIC 0x80808080 -0: + .text +ENTRY(strlen) + mov %o0, %o1 + andcc %o0, 3, %g0 + BRANCH32(be, pt, 9f) + sethi %hi(HI_MAGIC), %o4 ldub [%o0], %o5 - cmp %o5, 0 - be 1f + BRANCH_REG_ZERO(pn, %o5, 11f) add %o0, 1, %o0 andcc %o0, 3, %g0 - be 4f + BRANCH32(be, pn, 4f) or %o4, %lo(HI_MAGIC), %o3 ldub [%o0], %o5 - cmp %o5, 0 - be 2f + BRANCH_REG_ZERO(pn, %o5, 12f) add %o0, 1, %o0 andcc %o0, 3, %g0 - be 5f + BRANCH32(be, pt, 5f) sethi %hi(LO_MAGIC), %o4 ldub [%o0], %o5 - cmp %o5, 0 - be 3f + BRANCH_REG_ZERO(pn, %o5, 13f) add %o0, 1, %o0 - b 8f + BRANCH32(ba, pt, 8f) or %o4, %lo(LO_MAGIC), %o2 -1: - retl - mov 0, %o0 -2: - retl - mov 1, %o0 -3: - retl - mov 2, %o0 - - .align 4 - .global strlen -strlen: - mov %o0, %o1 - andcc %o0, 3, %g0 - bne 0b - sethi %hi(HI_MAGIC), %o4 +9: or %o4, %lo(HI_MAGIC), %o3 4: sethi %hi(LO_MAGIC), %o4 @@ -56,26 +45,36 @@ strlen: 2: sub %o5, %o2, %o4 andcc %o4, %o3, %g0 - be 8b + BRANCH32(be, pt, 8b) add %o0, 4, %o0 /* Check every byte. */ - srl %o5, 24, %g5 - andcc %g5, 0xff, %g0 - be 1f + srl %o5, 24, %g7 + andcc %g7, 0xff, %g0 + BRANCH32(be, pn, 1f) add %o0, -4, %o4 - srl %o5, 16, %g5 - andcc %g5, 0xff, %g0 - be 1f + srl %o5, 16, %g7 + andcc %g7, 0xff, %g0 + BRANCH32(be, pn, 1f) add %o4, 1, %o4 - srl %o5, 8, %g5 - andcc %g5, 0xff, %g0 - be 1f + srl %o5, 8, %g7 + andcc %g7, 0xff, %g0 + BRANCH32(be, pn, 1f) add %o4, 1, %o4 andcc %o5, 0xff, %g0 - bne,a 2b + BRANCH32_ANNUL(bne, pt, 2b) ld [%o0], %o5 add %o4, 1, %o4 1: retl sub %o4, %o1, %o0 +11: + retl + mov 0, %o0 +12: + retl + mov 1, %o0 +13: + retl + mov 2, %o0 +ENDPROC(strlen) diff --git a/arch/sparc/lib/strlen_user.S b/arch/sparc/lib/strlen_user_32.S index 8c8a371df3c9..8c8a371df3c9 100644 --- a/arch/sparc/lib/strlen_user.S +++ b/arch/sparc/lib/strlen_user_32.S diff --git a/arch/sparc64/lib/strlen_user.S b/arch/sparc/lib/strlen_user_64.S index 114ed111e251..114ed111e251 100644 --- a/arch/sparc64/lib/strlen_user.S +++ b/arch/sparc/lib/strlen_user_64.S diff --git a/arch/sparc/lib/strncmp.S b/arch/sparc/lib/strncmp_32.S index 494ec664537a..494ec664537a 100644 --- a/arch/sparc/lib/strncmp.S +++ b/arch/sparc/lib/strncmp_32.S diff --git a/arch/sparc64/lib/strncmp.S b/arch/sparc/lib/strncmp_64.S index 980e83751556..980e83751556 100644 --- a/arch/sparc64/lib/strncmp.S +++ b/arch/sparc/lib/strncmp_64.S diff --git a/arch/sparc/lib/strncpy_from_user.S b/arch/sparc/lib/strncpy_from_user_32.S index d77198976a66..d77198976a66 100644 --- a/arch/sparc/lib/strncpy_from_user.S +++ b/arch/sparc/lib/strncpy_from_user_32.S diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc/lib/strncpy_from_user_64.S index 511c8f136f95..511c8f136f95 100644 --- a/arch/sparc64/lib/strncpy_from_user.S +++ b/arch/sparc/lib/strncpy_from_user_64.S diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc/lib/user_fixup.c index 05a361b0a1a4..05a361b0a1a4 100644 --- a/arch/sparc64/lib/user_fixup.c +++ b/arch/sparc/lib/user_fixup.c diff --git a/arch/sparc64/lib/xor.S b/arch/sparc/lib/xor.S index f44f58f40234..f44f58f40234 100644 --- a/arch/sparc64/lib/xor.S +++ b/arch/sparc/lib/xor.S diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile index 8136987977f4..b9085ecbb27b 100644 --- a/arch/sparc/math-emu/Makefile +++ b/arch/sparc/math-emu/Makefile @@ -2,7 +2,7 @@ # Makefile for the FPU instruction emulation. # -obj-y := math.o +# supress all warnings - as math.c produces a lot! +ccflags-y := -w -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS = -I. -Iinclude/math-emu -w +obj-y := math_$(BITS).o diff --git a/arch/sparc/math-emu/ashldi3.S b/arch/sparc/math-emu/ashldi3.S deleted file mode 100644 index 7230ff5c7aa1..000000000000 --- a/arch/sparc/math-emu/ashldi3.S +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ashldi3.S: Math-emu code creates all kinds of references to - * this little routine on the sparc with gcc. - * - * Copyright (C) 1998 Jakub Jelinek(jj@ultra.linux.cz) - */ - -#include <asm/cprefix.h> - - .globl C_LABEL(__ashldi3) -C_LABEL(__ashldi3): - tst %o2 - be 3f - mov 32, %g2 - - sub %g2, %o2, %g2 - - tst %g2 - bg 1f - srl %o1, %g2, %g3 - - clr %o5 - neg %g2 - ba 2f - sll %o1, %g2, %o4 - -1: - sll %o1, %o2, %o5 - srl %o0, %o2, %g2 - or %g2, %g3, %o4 -2: - mov %o4, %o0 - mov %o5, %o1 -3: - jmpl %o7 + 8, %g0 - nop diff --git a/arch/sparc/math-emu/math.c b/arch/sparc/math-emu/math_32.c index 8613b3eb877c..e13f65da17df 100644 --- a/arch/sparc/math-emu/math.c +++ b/arch/sparc/math-emu/math_32.c @@ -69,7 +69,7 @@ #include <linux/mm.h> #include <asm/uaccess.h> -#include "sfp-util.h" +#include "sfp-util_32.h" #include <math-emu/soft-fp.h> #include <math-emu/single.h> #include <math-emu/double.h> diff --git a/arch/sparc64/math-emu/math.c b/arch/sparc/math-emu/math_64.c index add053e0f3b3..6863c9bde25c 100644 --- a/arch/sparc64/math-emu/math.c +++ b/arch/sparc/math-emu/math_64.c @@ -16,7 +16,7 @@ #include <asm/ptrace.h> #include <asm/uaccess.h> -#include "sfp-util.h" +#include "sfp-util_64.h" #include <math-emu/soft-fp.h> #include <math-emu/single.h> #include <math-emu/double.h> diff --git a/arch/sparc/math-emu/sfp-util.h b/arch/sparc/math-emu/sfp-util_32.h index d1b2aff3c259..d1b2aff3c259 100644 --- a/arch/sparc/math-emu/sfp-util.h +++ b/arch/sparc/math-emu/sfp-util_32.h diff --git a/arch/sparc64/math-emu/sfp-util.h b/arch/sparc/math-emu/sfp-util_64.h index 425d3cf01af4..425d3cf01af4 100644 --- a/arch/sparc64/math-emu/sfp-util.h +++ b/arch/sparc/math-emu/sfp-util_64.h diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index ea88955d97ff..681abe0a4594 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -1,17 +1,25 @@ # Makefile for the linux Sparc-specific parts of the memory manager. # -EXTRA_AFLAGS := -ansi +asflags-y := -ansi +ccflags-y := -Werror -obj-y := fault.o init.o loadmmu.o generic.o extable.o btfixup.o \ - srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o +obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o +obj-y += fault_$(BITS).o +obj-y += init_$(BITS).o +obj-$(CONFIG_SPARC32) += loadmmu.o +obj-y += generic_$(BITS).o +obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o +obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o -ifdef CONFIG_HIGHMEM -obj-y += highmem.o -endif +# Only used by sparc64 +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o + +# Only used by sparc32 +obj-$(CONFIG_HIGHMEM) += highmem.o ifdef CONFIG_SMP -obj-y += nosun4c.o +obj-$(CONFIG_SPARC32) += nosun4c.o else -obj-y += sun4c.o +obj-$(CONFIG_SPARC32) += sun4c.o endif diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault_32.c index a507e1174662..a507e1174662 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault_32.c diff --git a/arch/sparc64/mm/fault.c b/arch/sparc/mm/fault_64.c index a9e474bf6385..a9e474bf6385 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc/mm/fault_64.c diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic_32.c index a289261da9fd..a289261da9fd 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic_32.c diff --git a/arch/sparc64/mm/generic.c b/arch/sparc/mm/generic_64.c index f362c2037013..f362c2037013 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc/mm/generic_64.c diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index f27d10369e0c..f27d10369e0c 100644 --- a/arch/sparc64/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init_32.c index 677c1e187a23..fec926021f49 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init_32.c @@ -25,6 +25,7 @@ #include <linux/pagemap.h> #include <linux/poison.h> +#include <asm/sections.h> #include <asm/system.h> #include <asm/vac-ops.h> #include <asm/page.h> @@ -48,9 +49,6 @@ unsigned long sparc_unmapped_base; struct pgtable_cache_struct pgt_quicklists; -/* References to section boundaries */ -extern char __init_begin, __init_end, _start, _end, etext , edata; - /* Initial ramdisk setup */ extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; @@ -450,9 +448,9 @@ void __init mem_init(void) totalram_pages += totalhigh_pages; - codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); + codepages = (((unsigned long) &_etext) - ((unsigned long)&_start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; - datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); + datapages = (((unsigned long) &_edata) - ((unsigned long)&_etext)); datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT; initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; @@ -476,8 +474,10 @@ void __init mem_init(void) void free_initmem (void) { unsigned long addr; + unsigned long freed; addr = (unsigned long)(&__init_begin); + freed = (unsigned long)(&__init_end) - addr; for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { struct page *p; @@ -490,8 +490,8 @@ void free_initmem (void) totalram_pages++; num_physpages++; } - printk(KERN_INFO "Freeing unused kernel memory: %dk freed\n", - (&__init_end - &__init_begin) >> 10); + printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", + freed >> 10); } #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/sparc64/mm/init.c b/arch/sparc/mm/init_64.c index 185f34679110..6ea73da29312 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc/mm/init_64.c @@ -50,7 +50,7 @@ #include <asm/cpudata.h> #include <asm/irq.h> -#include "init.h" +#include "init_64.h" unsigned long kern_linear_pte_xor[2] __read_mostly; @@ -214,7 +214,6 @@ static inline void set_dcache_dirty(struct page *page, int this_cpu) "or %%g1, %0, %%g1\n\t" "casx [%2], %%g7, %%g1\n\t" "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" "bne,pn %%xcc, 1b\n\t" " nop" : /* no outputs */ @@ -236,7 +235,6 @@ static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu) " andn %%g7, %1, %%g1\n\t" "casx [%2], %%g7, %%g1\n\t" "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" "bne,pn %%xcc, 1b\n\t" " nop\n" "2:" @@ -956,7 +954,7 @@ int of_node_to_nid(struct device_node *dp) return nid; } -static void __init add_node_ranges(void) +static void add_node_ranges(void) { int i; diff --git a/arch/sparc64/mm/init.h b/arch/sparc/mm/init_64.h index 16063870a489..16063870a489 100644 --- a/arch/sparc64/mm/init.h +++ b/arch/sparc/mm/init_64.h diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index daadf5f88050..005e758a4db7 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -156,8 +156,8 @@ static void iounit_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { --sz; - sg->dvma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length); - sg->dvma_length = sg->length; + sg->dma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length); + sg->dma_length = sg->length; sg = sg_next(sg); } spin_unlock_irqrestore(&iounit->lock, flags); @@ -186,8 +186,8 @@ static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { --sz; - len = ((sg->dvma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT; - vaddr = (sg->dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; + len = ((sg->dma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT; + vaddr = (sg->dma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); for (len += vaddr; vaddr < len; vaddr++) clear_bit(vaddr, iounit->bmap); diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index e7a499e3aa3c..b2e6e73888b5 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -245,8 +245,8 @@ static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *s while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; - sg->dvma_length = (__u32) sg->length; + sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; + sg->dma_length = sg->length; sg = sg_next(sg); } } @@ -259,8 +259,8 @@ static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; - sg->dvma_length = (__u32) sg->length; + sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; + sg->dma_length = sg->length; sg = sg_next(sg); } } @@ -290,8 +290,8 @@ static void iommu_get_scsi_sgl_pflush(struct device *dev, struct scatterlist *sg } } - sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; - sg->dvma_length = (__u32) sg->length; + sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; + sg->dma_length = sg->length; sg = sg_next(sg); } } @@ -330,8 +330,8 @@ static void iommu_release_scsi_sgl(struct device *dev, struct scatterlist *sg, i --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - iommu_release_one(dev, sg->dvma_address & PAGE_MASK, n); - sg->dvma_address = 0x21212121; + iommu_release_one(dev, sg->dma_address & PAGE_MASK, n); + sg->dma_address = 0x21212121; sg = sg_next(sg); } } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index dd8aa36f366c..fe7ed08390bb 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1312,10 +1312,8 @@ void __init srmmu_paging_init(void) #endif poke_srmmu(); -#ifdef CONFIG_SUN_IO srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); -#endif srmmu_allocate_ptable_skeleton( __fix_to_virt(__end_of_fixed_addresses - 1), FIXADDR_TOP); @@ -1916,18 +1914,6 @@ static void __cpuinit poke_viking(void) mreg |= VIKING_SBENABLE; mreg &= ~(VIKING_ACENABLE); srmmu_set_mmureg(mreg); - -#ifdef CONFIG_SMP - /* Avoid unnecessary cross calls. */ - BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all); - BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm); - BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range); - BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page); - BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram); - BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns); - BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma); - btfixup(); -#endif } static void __init init_viking(void) @@ -2272,6 +2258,17 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM); + + if (poke_srmmu == poke_viking) { + /* Avoid unnecessary cross calls. */ + BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all); + BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm); + BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range); + BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page); + BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram); + BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns); + BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma); + } #endif if (sparc_cpu_model == sun4d) diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index fe65aeeb3947..2ffacd67c424 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -18,6 +18,7 @@ #include <linux/seq_file.h> #include <linux/scatterlist.h> +#include <asm/sections.h> #include <asm/page.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> @@ -240,9 +241,7 @@ void sun4c_complete_all_stores(void) _unused = sun4c_get_context(); sun4c_set_context(_unused); -#ifdef CONFIG_SUN_AUXIO _unused = get_auxio(); -#endif } /* Bootup utility functions. */ @@ -1124,8 +1123,8 @@ static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int s { while (sz != 0) { --sz; - sg->dvma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length); - sg->dvma_length = sg->length; + sg->dma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length); + sg->dma_length = sg->length; sg = sg_next(sg); } } @@ -1141,7 +1140,7 @@ static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, i { while (sz != 0) { --sz; - sun4c_unlockarea((char *)sg->dvma_address, sg->length); + sun4c_unlockarea((char *)sg->dma_address, sg->length); sg = sg_next(sg); } } @@ -1953,7 +1952,6 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p } extern void sparc_context_init(int); -extern unsigned long end; extern unsigned long bootmem_init(unsigned long *pages_avail); extern unsigned long last_valid_pfn; @@ -1964,7 +1962,7 @@ void __init sun4c_paging_init(void) extern struct resource sparc_iomap; unsigned long end_pfn, pages_avail; - kernel_end = (unsigned long) &end; + kernel_end = (unsigned long) &_end; kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end); pages_avail = 0; diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc/mm/tlb.c index d8f21e24a82f..d8f21e24a82f 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc/mm/tlb.c diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc/mm/tsb.c index 587f8efb2e05..36a0813f9517 100644 --- a/arch/sparc64/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -41,10 +41,8 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) KERNEL_TSB_NENTRIES); struct tsb *ent = &swapper_tsb[hash]; - if (tag_compare(ent->tag, v)) { + if (tag_compare(ent->tag, v)) ent->tag = (1UL << TSB_TAG_INVALID_BIT); - membar_storeload_storestore(); - } } } @@ -267,6 +265,18 @@ void __init pgtable_cache_init(void) } } +int sysctl_tsb_ratio = -2; + +static unsigned long tsb_size_to_rss_limit(unsigned long new_size) +{ + unsigned long num_ents = (new_size / sizeof(struct tsb)); + + if (sysctl_tsb_ratio < 0) + return num_ents - (num_ents >> -sysctl_tsb_ratio); + else + return num_ents + (num_ents >> sysctl_tsb_ratio); +} + /* When the RSS of an address space exceeds tsb_rss_limit for a TSB, * do_sparc64_fault() invokes this routine to try and grow it. * @@ -297,19 +307,14 @@ void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long rss) new_cache_index = 0; for (new_size = 8192; new_size < max_tsb_size; new_size <<= 1UL) { - unsigned long n_entries = new_size / sizeof(struct tsb); - - n_entries = (n_entries * 3) / 4; - if (n_entries > rss) + new_rss_limit = tsb_size_to_rss_limit(new_size); + if (new_rss_limit > rss) break; - new_cache_index++; } if (new_size == max_tsb_size) new_rss_limit = ~0UL; - else - new_rss_limit = ((new_size / sizeof(struct tsb)) * 3) / 4; retry_tsb_alloc: gfp_flags = GFP_KERNEL; diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc/mm/ultra.S index 86773e89dc1b..80c788ec7c32 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -125,7 +125,6 @@ __spitfire_flush_tlb_mm_slow: .align 32 .globl __flush_icache_page __flush_icache_page: /* %o0 = phys_page */ - membar #StoreStore srlx %o0, PAGE_SHIFT, %o0 sethi %uhi(PAGE_OFFSET), %g1 sllx %o0, PAGE_SHIFT, %o0 @@ -467,7 +466,7 @@ xcall_sync_tick: .previous rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil sethi %hi(109f), %g7 b,pt %xcc, etrap_irq 109: or %g7, %lo(109b), %g7 @@ -507,7 +506,6 @@ xcall_fetch_glob_regs: sllx %g2, TRAP_BLOCK_SZ_SHIFT, %g2 add %g7, %g2, %g7 ldx [%g7 + TRAP_PER_CPU_THREAD], %g3 - membar #StoreStore stx %g3, [%g1 + GR_SNAP_THREAD] retry @@ -690,7 +688,7 @@ xcall_kgdb_capture: .previous rdpr %pil, %g2 - wrpr %g0, 15, %pil + wrpr %g0, PIL_NORMAL_MAX, %pil sethi %hi(109f), %g7 ba,pt %xcc, etrap_irq 109: or %g7, %lo(109b), %g7 diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c index 17bb6035069b..d6e170c074fc 100644 --- a/arch/sparc/oprofile/init.c +++ b/arch/sparc/oprofile/init.c @@ -12,12 +12,239 @@ #include <linux/errno.h> #include <linux/init.h> +#ifdef CONFIG_SPARC64 +#include <asm/hypervisor.h> +#include <asm/spitfire.h> +#include <asm/cpudata.h> +#include <asm/irq.h> + +static int nmi_enabled; + +struct pcr_ops { + u64 (*read)(void); + void (*write)(u64); +}; +static const struct pcr_ops *pcr_ops; + +static u64 direct_pcr_read(void) +{ + u64 val; + + read_pcr(val); + return val; +} + +static void direct_pcr_write(u64 val) +{ + write_pcr(val); +} + +static const struct pcr_ops direct_pcr_ops = { + .read = direct_pcr_read, + .write = direct_pcr_write, +}; + +static void n2_pcr_write(u64 val) +{ + unsigned long ret; + + ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); + if (val != HV_EOK) + write_pcr(val); +} + +static const struct pcr_ops n2_pcr_ops = { + .read = direct_pcr_read, + .write = n2_pcr_write, +}; + +/* In order to commonize as much of the implementation as + * possible, we use PICH as our counter. Mostly this is + * to accomodate Niagara-1 which can only count insn cycles + * in PICH. + */ +static u64 picl_value(void) +{ + u32 delta = local_cpu_data().clock_tick / HZ; + + return ((u64)((0 - delta) & 0xffffffff)) << 32; +} + +#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ +#define PCR_STRACE 0x00000002 /* Trace supervisor events */ +#define PCR_UTRACE 0x00000004 /* Trace user events */ +#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ +#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ +#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ +#define PCR_N2_MASK0 0x00003fc0 +#define PCR_N2_MASK0_SHIFT 6 +#define PCR_N2_SL0 0x0003c000 +#define PCR_N2_SL0_SHIFT 14 +#define PCR_N2_OV0 0x00040000 +#define PCR_N2_MASK1 0x07f80000 +#define PCR_N2_MASK1_SHIFT 19 +#define PCR_N2_SL1 0x78000000 +#define PCR_N2_SL1_SHIFT 27 +#define PCR_N2_OV1 0x80000000 + +#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) +#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ + PCR_N2_TOE_OV1 | \ + (2 << PCR_N2_SL1_SHIFT) | \ + (0xff << PCR_N2_MASK1_SHIFT)) + +static u64 pcr_enable = PCR_SUN4U_ENABLE; + +static void nmi_handler(struct pt_regs *regs) +{ + pcr_ops->write(PCR_PIC_PRIV); + + if (nmi_enabled) { + oprofile_add_sample(regs, 0); + + write_pic(picl_value()); + pcr_ops->write(pcr_enable); + } +} + +/* We count "clock cycle" events in the lower 32-bit PIC. + * Then configure it such that it overflows every HZ, and thus + * generates a level 15 interrupt at that frequency. + */ +static void cpu_nmi_start(void *_unused) +{ + pcr_ops->write(PCR_PIC_PRIV); + write_pic(picl_value()); + + pcr_ops->write(pcr_enable); +} + +static void cpu_nmi_stop(void *_unused) +{ + pcr_ops->write(PCR_PIC_PRIV); +} + +static int nmi_start(void) +{ + int err = register_perfctr_intr(nmi_handler); + + if (!err) { + nmi_enabled = 1; + wmb(); + err = on_each_cpu(cpu_nmi_start, NULL, 1); + if (err) { + nmi_enabled = 0; + wmb(); + on_each_cpu(cpu_nmi_stop, NULL, 1); + release_perfctr_intr(nmi_handler); + } + } + + return err; +} + +static void nmi_stop(void) +{ + nmi_enabled = 0; + wmb(); + + on_each_cpu(cpu_nmi_stop, NULL, 1); + release_perfctr_intr(nmi_handler); + synchronize_sched(); +} + +static unsigned long perf_hsvc_group; +static unsigned long perf_hsvc_major; +static unsigned long perf_hsvc_minor; + +static int __init register_perf_hsvc(void) +{ + if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + perf_hsvc_group = HV_GRP_NIAG_PERF; + break; + + case SUN4V_CHIP_NIAGARA2: + perf_hsvc_group = HV_GRP_N2_CPU; + break; + + default: + return -ENODEV; + } + + + perf_hsvc_major = 1; + perf_hsvc_minor = 0; + if (sun4v_hvapi_register(perf_hsvc_group, + perf_hsvc_major, + &perf_hsvc_minor)) { + printk("perfmon: Could not register N2 hvapi.\n"); + return -ENODEV; + } + } + return 0; +} + +static void unregister_perf_hsvc(void) +{ + if (tlb_type != hypervisor) + return; + sun4v_hvapi_unregister(perf_hsvc_group); +} + +static int oprofile_nmi_init(struct oprofile_operations *ops) +{ + int err = register_perf_hsvc(); + + if (err) + return err; + + switch (tlb_type) { + case hypervisor: + pcr_ops = &n2_pcr_ops; + pcr_enable = PCR_N2_ENABLE; + break; + + case cheetah: + case cheetah_plus: + pcr_ops = &direct_pcr_ops; + break; + + default: + return -ENODEV; + } + + ops->create_files = NULL; + ops->setup = NULL; + ops->shutdown = NULL; + ops->start = nmi_start; + ops->stop = nmi_stop; + ops->cpu_type = "timer"; + + printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n"); + + return 0; +} +#endif + int __init oprofile_arch_init(struct oprofile_operations *ops) { - return -ENODEV; + int ret = -ENODEV; + +#ifdef CONFIG_SPARC64 + ret = oprofile_nmi_init(ops); + if (!ret) + return ret; +#endif + + return ret; } void oprofile_arch_exit(void) { +#ifdef CONFIG_SPARC64 + unregister_perf_hsvc(); +#endif } diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 8f7e18546c97..1b8c073adb44 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -1,6 +1,21 @@ # Makefile for the Sun Boot PROM interface library under # Linux. # +asflags := -ansi +ccflags := -Werror -lib-y := bootstr.o devmap.o devops.o init.o memory.o misc.o mp.o \ - palloc.o ranges.o segment.o console.o printf.o tree.o +lib-y := bootstr_$(BITS).o +lib-$(CONFIG_SPARC32) += devmap.o +lib-y += devops_$(BITS).o +lib-y += init_$(BITS).o +lib-$(CONFIG_SPARC32) += memory.o +lib-y += misc_$(BITS).o +lib-$(CONFIG_SPARC32) += mp.o +lib-$(CONFIG_SPARC32) += palloc.o +lib-$(CONFIG_SPARC32) += ranges.o +lib-$(CONFIG_SPARC32) += segment.o +lib-y += console_$(BITS).o +lib-y += printf.o +lib-y += tree_$(BITS).o +lib-$(CONFIG_SPARC64) += p1275.o +lib-$(CONFIG_SPARC64) += cif.o diff --git a/arch/sparc/prom/bootstr.c b/arch/sparc/prom/bootstr_32.c index 916831da7e67..916831da7e67 100644 --- a/arch/sparc/prom/bootstr.c +++ b/arch/sparc/prom/bootstr_32.c diff --git a/arch/sparc64/prom/bootstr.c b/arch/sparc/prom/bootstr_64.c index ab9ccc63b388..ab9ccc63b388 100644 --- a/arch/sparc64/prom/bootstr.c +++ b/arch/sparc/prom/bootstr_64.c diff --git a/arch/sparc64/prom/cif.S b/arch/sparc/prom/cif.S index 5f27ad779c0c..5f27ad779c0c 100644 --- a/arch/sparc64/prom/cif.S +++ b/arch/sparc/prom/cif.S diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console_32.c index b3075d73fc19..b3075d73fc19 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console_32.c diff --git a/arch/sparc64/prom/console.c b/arch/sparc/prom/console_64.c index e1c3fc87484d..e1c3fc87484d 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc/prom/console_64.c diff --git a/arch/sparc/prom/devops.c b/arch/sparc/prom/devops_32.c index 9f1a95c91ad1..9f1a95c91ad1 100644 --- a/arch/sparc/prom/devops.c +++ b/arch/sparc/prom/devops_32.c diff --git a/arch/sparc64/prom/devops.c b/arch/sparc/prom/devops_64.c index 9dbd803e46e1..9dbd803e46e1 100644 --- a/arch/sparc64/prom/devops.c +++ b/arch/sparc/prom/devops_64.c diff --git a/arch/sparc/prom/init.c b/arch/sparc/prom/init_32.c index 873217c6d823..873217c6d823 100644 --- a/arch/sparc/prom/init.c +++ b/arch/sparc/prom/init_32.c diff --git a/arch/sparc64/prom/init.c b/arch/sparc/prom/init_64.c index 7b00f89490a4..7b00f89490a4 100644 --- a/arch/sparc64/prom/init.c +++ b/arch/sparc/prom/init_64.c diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc_32.c index 49b5057b9601..cf6c3f6d36c3 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc_32.c @@ -61,9 +61,7 @@ prom_cmdline(void) restore_current(); install_linux_ticker(); spin_unlock_irqrestore(&prom_lock, flags); -#ifdef CONFIG_SUN_AUXIO set_auxio(AUXIO_LED, 0); -#endif } /* Drop into the prom, but completely terminate the program. diff --git a/arch/sparc64/prom/misc.c b/arch/sparc/prom/misc_64.c index 9b0c0760901e..9b0c0760901e 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc/prom/misc_64.c diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc/prom/p1275.c index 4b7c937bba61..4b7c937bba61 100644 --- a/arch/sparc64/prom/p1275.c +++ b/arch/sparc/prom/p1275.c diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c index a36ab9c5ee08..660943ee4c2a 100644 --- a/arch/sparc/prom/printf.c +++ b/arch/sparc/prom/printf.c @@ -2,6 +2,7 @@ * printf.c: Internal prom library printf facility. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com) * * We used to warn all over the code: DO NOT USE prom_printf(), @@ -13,7 +14,6 @@ */ #include <linux/kernel.h> -#include <linux/module.h> #include <asm/openprom.h> #include <asm/oplib.h> @@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n) } void -prom_printf(char *fmt, ...) +prom_printf(const char *fmt, ...) { va_list args; int i; @@ -45,4 +45,3 @@ prom_printf(char *fmt, ...) prom_write(ppbuf, i); } -EXPORT_SYMBOL(prom_printf); diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree_32.c index f228fe057b24..6d8187357331 100644 --- a/arch/sparc/prom/tree.c +++ b/arch/sparc/prom/tree_32.c @@ -85,7 +85,7 @@ int prom_getsibling(int node) /* Return the length in bytes of property 'prop' at node 'node'. * Return -1 on error. */ -int prom_getproplen(int node, char *prop) +int prom_getproplen(int node, const char *prop) { int ret; unsigned long flags; @@ -104,7 +104,7 @@ int prom_getproplen(int node, char *prop) * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ -int prom_getproperty(int node, char *prop, char *buffer, int bufsize) +int prom_getproperty(int node, const char *prop, char *buffer, int bufsize) { int plen, ret; unsigned long flags; @@ -303,7 +303,7 @@ int prom_node_has_property(int node, char *prop) /* Set property 'pname' at node 'node' to value 'value' which has a length * of 'size' bytes. Return the number of bytes the prom accepted. */ -int prom_setprop(int node, char *pname, char *value, int size) +int prom_setprop(int node, const char *pname, char *value, int size) { unsigned long flags; int ret; diff --git a/arch/sparc64/prom/tree.c b/arch/sparc/prom/tree_64.c index 281aea44790b..281aea44790b 100644 --- a/arch/sparc64/prom/tree.c +++ b/arch/sparc/prom/tree_64.c diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig deleted file mode 100644 index 3b96e70b4670..000000000000 --- a/arch/sparc64/Kconfig +++ /dev/null @@ -1,433 +0,0 @@ -# sparc64 configuration -mainmenu "Linux Kernel Configuration for 64-bit SPARC" - -config SPARC - bool - default y - select HAVE_OPROFILE - select HAVE_KPROBES - select HAVE_KRETPROBES - -config SPARC64 - bool - default y - select HAVE_FUNCTION_TRACER - select HAVE_IDE - select HAVE_LMB - select HAVE_ARCH_KGDB - select USE_GENERIC_SMP_HELPERS if SMP - select HAVE_ARCH_TRACEHOOK - select ARCH_WANT_OPTIONAL_GPIOLIB - select RTC_CLASS - select RTC_DRV_M48T59 - select RTC_DRV_CMOS - select RTC_DRV_BQ4802 - select RTC_DRV_SUN4V - select RTC_DRV_STARFIRE - -config GENERIC_TIME - bool - default y - -config GENERIC_CMOS_UPDATE - bool - default y - -config GENERIC_CLOCKEVENTS - bool - default y - -config GENERIC_GPIO - bool - help - Generic GPIO API support - -config 64BIT - def_bool y - -config MMU - bool - default y - -config IOMMU_HELPER - bool - default y - -config QUICKLIST - bool - default y - -config STACKTRACE_SUPPORT - bool - default y - -config LOCKDEP_SUPPORT - bool - default y - -config ARCH_MAY_HAVE_PC_FDC - bool - default y - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -config AUDIT_ARCH - bool - default y - -config HAVE_SETUP_PER_CPU_AREA - def_bool y - -config ARCH_NO_VIRT_TO_BUS - def_bool y - -config OF - def_bool y - -config GENERIC_HARDIRQS_NO__DO_IRQ - bool - def_bool y - -source "init/Kconfig" -source "kernel/Kconfig.freezer" - -menu "Processor type and features" - -choice - prompt "Kernel page size" - default SPARC64_PAGE_SIZE_8KB - -config SPARC64_PAGE_SIZE_8KB - bool "8KB" - help - This lets you select the page size of the kernel. - - 8KB and 64KB work quite well, since SPARC ELF sections - provide for up to 64KB alignment. - - If you don't know what to do, choose 8KB. - -config SPARC64_PAGE_SIZE_64KB - bool "64KB" - -endchoice - -config SECCOMP - bool "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS - default y - help - This kernel feature is useful for number crunching applications - that may need to compute untrusted bytecode during their - execution. By using pipes or other transports made available to - the process as file descriptors supporting the read/write - syscalls, it's possible to isolate those applications in - their own address space using seccomp. Once seccomp is - enabled via /proc/<pid>/seccomp, it cannot be disabled - and the task is only allowed to execute a few safe syscalls - defined by each seccomp mode. - - If unsure, say Y. Only embedded should say N here. - -source kernel/Kconfig.hz - -config HOTPLUG_CPU - bool "Support for hot-pluggable CPUs" - depends on SMP - select HOTPLUG - help - Say Y here to experiment with turning CPUs off and on. CPUs - can be controlled through /sys/devices/system/cpu/cpu#. - Say N if you want to disable CPU hotplug. - -config GENERIC_HARDIRQS - bool - default y - -source "kernel/time/Kconfig" - -config SMP - bool "Symmetric multi-processing support" - help - This enables support for systems with more than one CPU. If you have - a system with only one CPU, say N. If you have a system with more than - one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on single-processor machines. - On a single-processor machine, the kernel will run faster if you say - N here. - - If you don't know what to do here, say N. - -config NR_CPUS - int "Maximum number of CPUs (2-1024)" - range 2 1024 - depends on SMP - default "64" - -source "drivers/cpufreq/Kconfig" - -config US3_FREQ - tristate "UltraSPARC-III CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE - help - This adds the CPUFreq driver for UltraSPARC-III processors. - - For details, take a look at <file:Documentation/cpu-freq>. - - If in doubt, say N. - -config US2E_FREQ - tristate "UltraSPARC-IIe CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE - help - This adds the CPUFreq driver for UltraSPARC-IIe processors. - - For details, take a look at <file:Documentation/cpu-freq>. - - If in doubt, say N. - -config US3_MC - tristate "UltraSPARC-III Memory Controller driver" - default y - help - This adds a driver for the UltraSPARC-III memory controller. - Loading this driver allows exact mnemonic strings to be - printed in the event of a memory error, so that the faulty DIMM - on the motherboard can be matched to the error. - - If in doubt, say Y, as this information can be very useful. - -# Global things across all Sun machines. -config GENERIC_LOCKBREAK - bool - default y - depends on SMP && PREEMPT - -config RWSEM_GENERIC_SPINLOCK - bool - -config RWSEM_XCHGADD_ALGORITHM - bool - default y - -config GENERIC_FIND_NEXT_BIT - bool - default y - -config GENERIC_HWEIGHT - bool - default y if !ULTRA_HAS_POPULATION_COUNT - -config GENERIC_CALIBRATE_DELAY - bool - default y - -choice - prompt "SPARC64 Huge TLB Page Size" - depends on HUGETLB_PAGE - default HUGETLB_PAGE_SIZE_4MB - -config HUGETLB_PAGE_SIZE_4MB - bool "4MB" - -config HUGETLB_PAGE_SIZE_512K - bool "512K" - -config HUGETLB_PAGE_SIZE_64K - depends on !SPARC64_PAGE_SIZE_64KB - bool "64K" - -endchoice - -endmenu - -config NUMA - bool "NUMA support" - depends on SMP - -config NODES_SHIFT - int - default "4" - depends on NEED_MULTIPLE_NODES - -# Some NUMA nodes have memory ranges that span -# other nodes. Even though a pfn is valid and -# between a node's start and end pfns, it may not -# reside on that node. See memmap_init_zone() -# for details. -config NODES_SPAN_OTHER_NODES - def_bool y - depends on NEED_MULTIPLE_NODES - -config ARCH_POPULATES_NODE_MAP - def_bool y - -config ARCH_SELECT_MEMORY_MODEL - def_bool y - -config ARCH_SPARSEMEM_ENABLE - def_bool y - select SPARSEMEM_VMEMMAP_ENABLE - -config ARCH_SPARSEMEM_DEFAULT - def_bool y - -source "mm/Kconfig" - -config ISA - bool - -config ISAPNP - bool - -config EISA - bool - -config MCA - bool - -config PCMCIA - tristate - help - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> - for location). Please also read the PCMCIA-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. - -config SBUS - bool - default y - -config SBUSCHAR - bool - default y - -config SUN_AUXIO - bool - default y - -config SUN_IO - bool - default y - -config SUN_LDOMS - bool "Sun Logical Domains support" - help - Say Y here is you want to support virtual devices via - Logical Domains. - -config PCI - bool "PCI support" - select ARCH_SUPPORTS_MSI - help - Find out whether your system includes a PCI bus. PCI is the name of - a bus system, i.e. the way the CPU talks to the other stuff inside - your box. If you say Y here, the kernel will include drivers and - infrastructure code to support PCI bus devices. - -config PCI_DOMAINS - def_bool PCI - -config PCI_SYSCALL - def_bool PCI - -source "drivers/pci/Kconfig" - -config SUN_OPENPROMFS - tristate "Openprom tree appears in /proc/openprom" - help - If you say Y, the OpenPROM device tree will be available as a - virtual file system, which you can mount to /proc/openprom by "mount - -t openpromfs none /proc/openprom". - - To compile the /proc/openprom support as a module, choose M here: the - module will be called openpromfs. If unsure, choose M. - -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -config COMPAT - bool - default y - select COMPAT_BINFMT_ELF - -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - -endmenu - -config SCHED_SMT - bool "SMT (Hyperthreading) scheduler support" - depends on SMP - default y - help - SMT scheduler support improves the CPU scheduler's decision making - when dealing with SPARC cpus at a cost of slightly increased overhead - in some places. If unsure say N here. - -config SCHED_MC - bool "Multi-core scheduler support" - depends on SMP - default y - help - Multi-core scheduler support improves the CPU scheduler's decision - making when dealing with multi-core CPU chips at a cost of slightly - increased overhead in some places. If unsure say N here. - -source "kernel/Kconfig.preempt" - -config CMDLINE_BOOL - bool "Default bootloader kernel arguments" - -config CMDLINE - string "Initial kernel command string" - depends on CMDLINE_BOOL - default "console=ttyS0,9600 root=/dev/sda1" - help - Say Y here if you want to be able to pass default arguments to - the kernel. This will be overridden by the bootloader, if you - use one (such as SILO). This is most useful if you want to boot - a kernel from TFTP, and want default options to be available - with having them passed on the command line. - - NOTE: This option WILL override the PROM bootargs setting! - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "drivers/sbus/char/Kconfig" - -source "fs/Kconfig" - -source "arch/sparc64/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug deleted file mode 100644 index c40515c06690..000000000000 --- a/arch/sparc64/Kconfig.debug +++ /dev/null @@ -1,44 +0,0 @@ -menu "Kernel hacking" - -config TRACE_IRQFLAGS_SUPPORT - bool - default y - -source "lib/Kconfig.debug" - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_DCFLUSH - bool "D-cache flush debugging" - depends on DEBUG_KERNEL - -config STACK_DEBUG - depends on DEBUG_KERNEL - bool "Stack Overflow Detection Support" - -config DEBUG_PAGEALLOC - bool "Debug page memory allocations" - depends on DEBUG_KERNEL && !HIBERNATION - help - Unmap pages from the kernel linear mapping after free_pages(). - This results in a large slowdown, but helps to find certain types - of memory corruptions. - -config MCOUNT - bool - depends on STACK_DEBUG || FUNCTION_TRACER - default y - -config FRAME_POINTER - bool - depends on MCOUNT - default y - -endmenu diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile deleted file mode 100644 index c7214abc0d84..000000000000 --- a/arch/sparc64/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# sparc64/Makefile -# -# Makefile for the architecture dependent flags and dependencies on the -# 64-bit Sparc. -# -# Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) -# Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) -# - -CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 - -# Undefine sparc when processing vmlinux.lds - it is used -# And teach CPP we are doing 64 bit builds (for this case) -CPPFLAGS_vmlinux.lds += -m64 -Usparc - -LDFLAGS := -m elf64_sparc - -KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ - -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ - -Wa,--undeclared-regs -KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3) -KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs - -ifeq ($(CONFIG_MCOUNT),y) - KBUILD_CFLAGS += -pg -endif - -head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o - -core-y += arch/sparc64/kernel/ arch/sparc64/mm/ -core-y += arch/sparc64/math-emu/ -libs-y += arch/sparc64/prom/ arch/sparc64/lib/ -drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/ - -boot := arch/sparc64/boot - -image tftpboot.img vmlinux.aout: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -define archhelp - echo '* vmlinux - Standard sparc64 kernel' - echo ' vmlinux.aout - a.out kernel for sparc64' - echo ' tftpboot.img - Image prepared for tftp' -endef - diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile deleted file mode 100644 index 0458b5244f09..000000000000 --- a/arch/sparc64/boot/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Makefile for the Sparc64 boot stuff. -# -# Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) -# Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - -ROOT_IMG := /usr/src/root.img -ELFTOAOUT := elftoaout - -hostprogs-y := piggyback -targets := image tftpboot.img vmlinux.aout - -quiet_cmd_elftoaout = ELF2AOUT $@ - cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@ -quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback $@ System.map $(ROOT_IMG) -quiet_cmd_strip = STRIP $@ - cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ - - -# Actual linking -$(obj)/image: vmlinux FORCE - $(call if_changed,strip) - @echo ' kernel: $@ is ready' - -$(obj)/tftpboot.img: vmlinux $(obj)/piggyback System.map $(ROOT_IMG) FORCE - $(call if_changed,elftoaout) - $(call if_changed,piggy) - @echo ' kernel: $@ is ready' - -$(obj)/vmlinux.aout: vmlinux FORCE - $(call if_changed,elftoaout) - @echo ' kernel: $@ is ready' - diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile deleted file mode 100644 index b3e0b986bef8..000000000000 --- a/arch/sparc64/kernel/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile for the linux kernel. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -CFLAGS_REMOVE_ftrace.o = -pg - -extra-y := head.o init_task.o vmlinux.lds - -obj-y := process.o setup.o cpu.o idprom.o reboot.o \ - traps.o auxio.o una_asm.o sysfs.o iommu.o \ - irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o central.o starfire.o \ - power.o sbus.o sparc64_ksyms.o ebus.o \ - visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o - -obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o -obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \ - pci_psycho.o pci_sabre.o pci_schizo.o \ - pci_sun4v.o pci_sun4v_asm.o pci_fire.o -obj-$(CONFIG_PCI_MSI) += pci_msi.o -obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o -obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o -obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o -obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o -obj-$(CONFIG_US3_MC) += chmc.o -obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o -obj-$(CONFIG_AUDIT) += audit.o -obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o -obj-y += $(obj-yy) -obj-$(CONFIG_KGDB) += kgdb.o diff --git a/arch/sparc64/kernel/asm-offsets.c b/arch/sparc64/kernel/asm-offsets.c deleted file mode 100644 index 9e263112a6e2..000000000000 --- a/arch/sparc64/kernel/asm-offsets.c +++ /dev/null @@ -1 +0,0 @@ -/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c deleted file mode 100644 index 0c9ac83ed0a8..000000000000 --- a/arch/sparc64/kernel/cpu.c +++ /dev/null @@ -1,166 +0,0 @@ -/* cpu.c: Dinky routines to look for the kind of Sparc cpu - * we are on. - * - * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <asm/asi.h> -#include <asm/system.h> -#include <asm/fpumacro.h> -#include <asm/cpudata.h> -#include <asm/spitfire.h> -#include <asm/oplib.h> - -#include "entry.h" - -DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; - -struct cpu_chip_info { - unsigned short manuf; - unsigned short impl; - const char *cpu_name; - const char *fp_name; -}; - -static const struct cpu_chip_info cpu_chips[] = { - { - .manuf = 0x17, - .impl = 0x10, - .cpu_name = "TI UltraSparc I (SpitFire)", - .fp_name = "UltraSparc I integrated FPU", - }, - { - .manuf = 0x22, - .impl = 0x10, - .cpu_name = "TI UltraSparc I (SpitFire)", - .fp_name = "UltraSparc I integrated FPU", - }, - { - .manuf = 0x17, - .impl = 0x11, - .cpu_name = "TI UltraSparc II (BlackBird)", - .fp_name = "UltraSparc II integrated FPU", - }, - { - .manuf = 0x17, - .impl = 0x12, - .cpu_name = "TI UltraSparc IIi (Sabre)", - .fp_name = "UltraSparc IIi integrated FPU", - }, - { - .manuf = 0x17, - .impl = 0x13, - .cpu_name = "TI UltraSparc IIe (Hummingbird)", - .fp_name = "UltraSparc IIe integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x14, - .cpu_name = "TI UltraSparc III (Cheetah)", - .fp_name = "UltraSparc III integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x15, - .cpu_name = "TI UltraSparc III+ (Cheetah+)", - .fp_name = "UltraSparc III+ integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x16, - .cpu_name = "TI UltraSparc IIIi (Jalapeno)", - .fp_name = "UltraSparc IIIi integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x18, - .cpu_name = "TI UltraSparc IV (Jaguar)", - .fp_name = "UltraSparc IV integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x19, - .cpu_name = "TI UltraSparc IV+ (Panther)", - .fp_name = "UltraSparc IV+ integrated FPU", - }, - { - .manuf = 0x3e, - .impl = 0x22, - .cpu_name = "TI UltraSparc IIIi+ (Serrano)", - .fp_name = "UltraSparc IIIi+ integrated FPU", - }, -}; - -#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) - -const char *sparc_cpu_type; -const char *sparc_fpu_type; - -static void __init sun4v_cpu_probe(void) -{ - switch (sun4v_chip_type) { - case SUN4V_CHIP_NIAGARA1: - sparc_cpu_type = "UltraSparc T1 (Niagara)"; - sparc_fpu_type = "UltraSparc T1 integrated FPU"; - break; - - case SUN4V_CHIP_NIAGARA2: - sparc_cpu_type = "UltraSparc T2 (Niagara2)"; - sparc_fpu_type = "UltraSparc T2 integrated FPU"; - break; - - default: - printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", - prom_cpu_compatible); - sparc_cpu_type = "Unknown SUN4V CPU"; - sparc_fpu_type = "Unknown SUN4V FPU"; - break; - } -} - -static const struct cpu_chip_info * __init find_cpu_chip(unsigned short manuf, - unsigned short impl) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cpu_chips); i++) { - const struct cpu_chip_info *p = &cpu_chips[i]; - - if (p->manuf == manuf && p->impl == impl) - return p; - } - return NULL; -} - -static int __init cpu_type_probe(void) -{ - if (tlb_type == hypervisor) { - sun4v_cpu_probe(); - } else { - unsigned long ver, manuf, impl; - const struct cpu_chip_info *p; - - __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); - - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - p = find_cpu_chip(manuf, impl); - if (p) { - sparc_cpu_type = p->cpu_name; - sparc_fpu_type = p->fp_name; - } else { - printk(KERN_ERR "CPU: Unknown chip, manuf[%lx] impl[%lx]\n", - manuf, impl); - sparc_cpu_type = "Unknown CPU"; - sparc_fpu_type = "Unknown FPU"; - } - } - return 0; -} - -arch_initcall(cpu_type_probe); diff --git a/arch/sparc64/kernel/idprom.c b/arch/sparc64/kernel/idprom.c deleted file mode 100644 index a62ff83337cd..000000000000 --- a/arch/sparc64/kernel/idprom.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * idprom.c: Routines to load the idprom into kernel addresses and - * interpret the data contained within. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> - -#include <asm/oplib.h> -#include <asm/idprom.h> - -struct idprom *idprom; -static struct idprom idprom_buffer; - -/* Calculate the IDPROM checksum (xor of the data bytes). */ -static unsigned char __init calc_idprom_cksum(struct idprom *idprom) -{ - unsigned char cksum, i, *ptr = (unsigned char *)idprom; - - for (i = cksum = 0; i <= 0x0E; i++) - cksum ^= *ptr++; - - return cksum; -} - -/* Create a local IDPROM copy and verify integrity. */ -void __init idprom_init(void) -{ - prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer)); - - idprom = &idprom_buffer; - - if (idprom->id_format != 0x01) { - prom_printf("IDPROM: Warning, unknown format type!\n"); - } - - if (idprom->id_cksum != calc_idprom_cksum(idprom)) { - prom_printf("IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n", - idprom->id_cksum, calc_idprom_cksum(idprom)); - } - - printk("Ethernet address: %pM\n", idprom->id_ethaddr); -} diff --git a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c deleted file mode 100644 index d2b312381c19..000000000000 --- a/arch/sparc64/kernel/init_task.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/processor.h> - -static struct fs_struct init_fs = INIT_FS; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - -/* .text section in head.S is aligned at 2 page boundary and this gets linked - * right after that so that the init_thread_union is aligned properly as well. - * We really don't need this special alignment like the Intel does, but - * I do it anyways for completeness. - */ -__asm__ (".text"); -union thread_union init_thread_union = { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -EXPORT_SYMBOL(init_task); - -__asm__(".data"); -struct task_struct init_task = INIT_TASK(init_task); diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c deleted file mode 100644 index 158484bf5999..000000000000 --- a/arch/sparc64/kernel/module.c +++ /dev/null @@ -1,213 +0,0 @@ -/* Kernel module help for sparc64. - * - * Copyright (C) 2001 Rusty Russell. - * Copyright (C) 2002 David S. Miller. - */ - -#include <linux/moduleloader.h> -#include <linux/kernel.h> -#include <linux/elf.h> -#include <linux/vmalloc.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/mm.h> - -#include <asm/processor.h> -#include <asm/spitfire.h> - -static void *module_map(unsigned long size) -{ - struct vm_struct *area; - - size = PAGE_ALIGN(size); - if (!size || size > MODULES_LEN) - return NULL; - - area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); - if (!area) - return NULL; - - return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); -} - -void *module_alloc(unsigned long size) -{ - void *ret; - - /* We handle the zero case fine, unlike vmalloc */ - if (size == 0) - return NULL; - - ret = module_map(size); - if (!ret) - ret = ERR_PTR(-ENOMEM); - else - memset(ret, 0, size); - - return ret; -} - -/* Free memory returned from module_core_alloc/module_init_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* Make generic code ignore STT_REGISTER dummy undefined symbols. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - unsigned int symidx; - Elf64_Sym *sym; - const char *strtab; - int i; - - for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) { - if (symidx == hdr->e_shnum-1) { - printk("%s: no symtab found.\n", mod->name); - return -ENOEXEC; - } - } - sym = (Elf64_Sym *)sechdrs[symidx].sh_addr; - strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr; - - for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { - if (sym[i].st_shndx == SHN_UNDEF && - ELF64_ST_TYPE(sym[i].st_info) == STT_REGISTER) - sym[i].st_shndx = SHN_ABS; - } - return 0; -} - -int apply_relocate(Elf64_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; -} - -int apply_relocate_add(Elf64_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf64_Sym *sym; - u8 *location; - u32 *loc32; - - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - Elf64_Addr v; - - /* This is where to make the change */ - location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - loc32 = (u32 *) location; - - BUG_ON(((u64)location >> (u64)32) != (u64)0); - - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf64_Sym *)sechdrs[symindex].sh_addr - + ELF64_R_SYM(rel[i].r_info); - v = sym->st_value + rel[i].r_addend; - - switch (ELF64_R_TYPE(rel[i].r_info) & 0xff) { - case R_SPARC_64: - location[0] = v >> 56; - location[1] = v >> 48; - location[2] = v >> 40; - location[3] = v >> 32; - location[4] = v >> 24; - location[5] = v >> 16; - location[6] = v >> 8; - location[7] = v >> 0; - break; - - case R_SPARC_32: - location[0] = v >> 24; - location[1] = v >> 16; - location[2] = v >> 8; - location[3] = v >> 0; - break; - - case R_SPARC_DISP32: - v -= (Elf64_Addr) location; - *loc32 = v; - break; - - case R_SPARC_WDISP30: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x3fffffff) | - ((v >> 2) & 0x3fffffff); - break; - - case R_SPARC_WDISP22: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x3fffff) | - ((v >> 2) & 0x3fffff); - break; - - case R_SPARC_WDISP19: - v -= (Elf64_Addr) location; - *loc32 = (*loc32 & ~0x7ffff) | - ((v >> 2) & 0x7ffff); - break; - - case R_SPARC_LO10: - *loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff); - break; - - case R_SPARC_HI22: - *loc32 = (*loc32 & ~0x3fffff) | - ((v >> 10) & 0x3fffff); - break; - - case R_SPARC_OLO10: - *loc32 = (*loc32 & ~0x1fff) | - (((v & 0x3ff) + - (ELF64_R_TYPE(rel[i].r_info) >> 8)) - & 0x1fff); - break; - - default: - printk(KERN_ERR "module %s: Unknown relocation: %x\n", - me->name, - (int) (ELF64_R_TYPE(rel[i].r_info) & 0xff)); - return -ENOEXEC; - }; - } - return 0; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - /* Cheetah's I-cache is fully coherent. */ - if (tlb_type == spitfire) { - unsigned long va; - - flushw_all(); - for (va = 0; va < (PAGE_SIZE << 1); va += 32) - spitfire_put_icache_tag(va, 0x0); - __asm__ __volatile__("flush %g6"); - } - - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S deleted file mode 100644 index 01f809617e5e..000000000000 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ /dev/null @@ -1,147 +0,0 @@ -/* ld script to make UltraLinux kernel */ - -#include <asm/page.h> -#include <asm-generic/vmlinux.lds.h> - -OUTPUT_FORMAT("elf64-sparc", "elf64-sparc", "elf64-sparc") -OUTPUT_ARCH(sparc:v9a) -ENTRY(_start) - -jiffies = jiffies_64; -SECTIONS -{ - swapper_low_pmd_dir = 0x0000000000402000; - . = 0x4000; - .text 0x0000000000404000 : { - _text = .; - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.gnu.warning) - } = 0 - _etext = .; - PROVIDE (etext = .); - - RO_DATA(PAGE_SIZE) - .data : { - DATA_DATA - CONSTRUCTORS - } - .data1 : { - *(.data1) - } - . = ALIGN(64); - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - . = ALIGN(64); - .data.read_mostly : { - *(.data.read_mostly) - } - _edata = .; - PROVIDE (edata = .); - .fixup : { - *(.fixup) - } - . = ALIGN(16); - __ex_table : { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - NOTES - - . = ALIGN(PAGE_SIZE); - .init.text : { - __init_begin = .; - _sinittext = .; - INIT_TEXT - _einittext = .; - } - .init.data : { - INIT_DATA - } - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - .initcall.init : { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - SECURITY_INIT - - . = ALIGN(4); - .tsb_ldquad_phys_patch : { - __tsb_ldquad_phys_patch = .; - *(.tsb_ldquad_phys_patch) - __tsb_ldquad_phys_patch_end = .; - } - - .tsb_phys_patch : { - __tsb_phys_patch = .; - *(.tsb_phys_patch) - __tsb_phys_patch_end = .; - } - - .cpuid_patch : { - __cpuid_patch = .; - *(.cpuid_patch) - __cpuid_patch_end = .; - } - - .sun4v_1insn_patch : { - __sun4v_1insn_patch = .; - *(.sun4v_1insn_patch) - __sun4v_1insn_patch_end = .; - } - .sun4v_2insn_patch : { - __sun4v_2insn_patch = .; - *(.sun4v_2insn_patch) - __sun4v_2insn_patch_end = .; - } - -#ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } -#endif - - PERCPU(PAGE_SIZE) - - . = ALIGN(PAGE_SIZE); - __init_end = .; - __bss_start = .; - .sbss : { - *(.sbss) - *(.scommon) - } - .bss : { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - - /DISCARD/ : { - EXIT_TEXT - EXIT_DATA - *(.exitcall.exit) - } - - STABS_DEBUG - DWARF_DEBUG -} diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile deleted file mode 100644 index f095e13910bc..000000000000 --- a/arch/sparc64/lib/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# Makefile for Sparc64 library files.. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ - memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - bzero.o csum_copy.o csum_copy_from_user.o csum_copy_to_user.o \ - VISsave.o atomic.o bitops.o \ - U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ - U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ - NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \ - NGpage.o NGbzero.o \ - NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o NG2patch.o \ - NG2page.o \ - GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \ - GENpage.o GENbzero.o \ - copy_in_user.o user_fixup.o memmove.o \ - mcount.o ipcsum.o rwsem.o xor.o - -obj-y += iomap.o diff --git a/arch/sparc64/lib/iomap.c b/arch/sparc64/lib/iomap.c deleted file mode 100644 index 7120ebbd4d03..000000000000 --- a/arch/sparc64/lib/iomap.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Implement the sparc64 iomap interfaces - */ -#include <linux/pci.h> -#include <linux/module.h> -#include <asm/io.h> - -/* Create a virtual mapping cookie for an IO port range */ -void __iomem *ioport_map(unsigned long port, unsigned int nr) -{ - return (void __iomem *) (unsigned long) port; -} - -void ioport_unmap(void __iomem *addr) -{ - /* Nothing to do */ -} -EXPORT_SYMBOL(ioport_map); -EXPORT_SYMBOL(ioport_unmap); - -/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - resource_size_t start = pci_resource_start(dev, bar); - resource_size_t len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - if (maxlen && len > maxlen) - len = maxlen; - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) { - if (flags & IORESOURCE_CACHEABLE) - return ioremap(start, len); - return ioremap_nocache(start, len); - } - /* What? */ - return NULL; -} - -void pci_iounmap(struct pci_dev *dev, void __iomem * addr) -{ - /* nothing to do */ -} -EXPORT_SYMBOL(pci_iomap); -EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/sparc64/lib/memcmp.S b/arch/sparc64/lib/memcmp.S deleted file mode 100644 index d3fdaa898566..000000000000 --- a/arch/sparc64/lib/memcmp.S +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Sparc64 optimized memcmp code. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ - - .text - .align 32 - .globl __memcmp, memcmp -__memcmp: -memcmp: - cmp %o2, 0 ! IEU1 Group -loop: be,pn %icc, ret_0 ! CTI - nop ! IEU0 - ldub [%o0], %g7 ! LSU Group - ldub [%o1], %g3 ! LSU Group - sub %o2, 1, %o2 ! IEU0 - add %o0, 1, %o0 ! IEU1 - add %o1, 1, %o1 ! IEU0 Group - subcc %g7, %g3, %g3 ! IEU1 Group - be,pt %icc, loop ! CTI - cmp %o2, 0 ! IEU1 Group - -ret_n0: retl - mov %g3, %o0 -ret_0: retl - mov 0, %o0 diff --git a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S deleted file mode 100644 index e9ba1920d818..000000000000 --- a/arch/sparc64/lib/strlen.S +++ /dev/null @@ -1,80 +0,0 @@ -/* strlen.S: Sparc64 optimized strlen code - * Hand optimized from GNU libc's strlen - * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#define LO_MAGIC 0x01010101 -#define HI_MAGIC 0x80808080 - - .align 32 - .globl strlen - .type strlen,#function -strlen: - mov %o0, %o1 - andcc %o0, 3, %g0 - be,pt %icc, 9f - sethi %hi(HI_MAGIC), %o4 - ldub [%o0], %o5 - brz,pn %o5, 11f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pn %icc, 4f - or %o4, %lo(HI_MAGIC), %o3 - ldub [%o0], %o5 - brz,pn %o5, 12f - add %o0, 1, %o0 - andcc %o0, 3, %g0 - be,pt %icc, 5f - sethi %hi(LO_MAGIC), %o4 - ldub [%o0], %o5 - brz,pn %o5, 13f - add %o0, 1, %o0 - ba,pt %icc, 8f - or %o4, %lo(LO_MAGIC), %o2 -9: - or %o4, %lo(HI_MAGIC), %o3 -4: - sethi %hi(LO_MAGIC), %o4 -5: - or %o4, %lo(LO_MAGIC), %o2 -8: - ld [%o0], %o5 -2: - sub %o5, %o2, %o4 - andcc %o4, %o3, %g0 - be,pt %icc, 8b - add %o0, 4, %o0 - - /* Check every byte. */ - srl %o5, 24, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o0, -4, %o4 - srl %o5, 16, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - srl %o5, 8, %g7 - andcc %g7, 0xff, %g0 - be,pn %icc, 1f - add %o4, 1, %o4 - andcc %o5, 0xff, %g0 - bne,a,pt %icc, 2b - ld [%o0], %o5 - add %o4, 1, %o4 -1: - retl - sub %o4, %o1, %o0 -11: - retl - mov 0, %o0 -12: - retl - mov 1, %o0 -13: - retl - mov 2, %o0 - - .size strlen, .-strlen diff --git a/arch/sparc64/math-emu/Makefile b/arch/sparc64/math-emu/Makefile deleted file mode 100644 index cc5cb9baf6aa..000000000000 --- a/arch/sparc64/math-emu/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the FPU instruction emulation. -# - -obj-y := math.o - -EXTRA_CFLAGS = -Iinclude/math-emu -w diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile deleted file mode 100644 index 68d04c0370f4..000000000000 --- a/arch/sparc64/mm/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Makefile for the linux Sparc64-specific parts of the memory manager. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -obj-y := ultra.o tlb.o tsb.o fault.o init.o generic.o - -obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/sparc64/oprofile/Makefile b/arch/sparc64/oprofile/Makefile deleted file mode 100644 index e9feca1ca28b..000000000000 --- a/arch/sparc64/oprofile/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o ) - -oprofile-y := $(DRIVER_OBJS) init.o diff --git a/arch/sparc64/oprofile/init.c b/arch/sparc64/oprofile/init.c deleted file mode 100644 index 17bb6035069b..000000000000 --- a/arch/sparc64/oprofile/init.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file init.c - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon <levon@movementarian.org> - */ - -#include <linux/kernel.h> -#include <linux/oprofile.h> -#include <linux/errno.h> -#include <linux/init.h> - -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - return -ENODEV; -} - - -void oprofile_arch_exit(void) -{ -} diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile deleted file mode 100644 index 8c94483ca54d..000000000000 --- a/arch/sparc64/prom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Makefile for the Sun Boot PROM interface library under -# Linux. -# - -EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror - -lib-y := bootstr.o devops.o init.o misc.o \ - tree.o console.o printf.o p1275.o cif.o diff --git a/arch/sparc64/prom/printf.c b/arch/sparc64/prom/printf.c deleted file mode 100644 index 660943ee4c2a..000000000000 --- a/arch/sparc64/prom/printf.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * printf.c: Internal prom library printf facility. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com) - * - * We used to warn all over the code: DO NOT USE prom_printf(), - * and yet people do. Anton's banking code was outputting banks - * with prom_printf for most of the 2.4 lifetime. Since an effective - * stick is not available, we deployed a carrot: an early printk - * through PROM by means of -p boot option. This ought to fix it. - * USE printk; if you need, deploy -p. - */ - -#include <linux/kernel.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> - -static char ppbuf[1024]; - -void -prom_write(const char *buf, unsigned int n) -{ - char ch; - - while (n != 0) { - --n; - if ((ch = *buf++) == '\n') - prom_putchar('\r'); - prom_putchar(ch); - } -} - -void -prom_printf(const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); - va_end(args); - - prom_write(ppbuf, i); -} diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h index 753346e2cdfd..ae5f94d6317d 100644 --- a/arch/um/include/asm/system.h +++ b/arch/um/include/asm/system.h @@ -11,21 +11,21 @@ extern int get_signals(void); extern void block_signals(void); extern void unblock_signals(void); -#define local_save_flags(flags) do { typecheck(unsigned long, flags); \ +#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \ (flags) = get_signals(); } while(0) -#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \ +#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \ set_signals(flags); } while(0) -#define local_irq_save(flags) do { local_save_flags(flags); \ - local_irq_disable(); } while(0) +#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \ + raw_local_irq_disable(); } while(0) -#define local_irq_enable() unblock_signals() -#define local_irq_disable() block_signals() +#define raw_local_irq_enable() unblock_signals() +#define raw_local_irq_disable() block_signals() #define irqs_disabled() \ ({ \ unsigned long flags; \ - local_save_flags(flags); \ + raw_local_save_flags(flags); \ (flags == 0); \ }) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 98a0ed52b5c3..0f44add3e0b7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -247,6 +247,28 @@ config X86_HAS_BOOT_CPU_ID def_bool y depends on X86_VOYAGER +config SPARSE_IRQ + bool "Support sparse irq numbering" + depends on PCI_MSI || HT_IRQ + help + This enables support for sparse irqs. This is useful for distro + kernels that want to define a high CONFIG_NR_CPUS value but still + want to have low kernel memory footprint on smaller machines. + + ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread + out the irq_desc[] array in a more NUMA-friendly way. ) + + If you don't know what to do here, say N. + +config NUMA_MIGRATE_IRQ_DESC + bool "Move irq desc when changing irq smp_affinity" + depends on SPARSE_IRQ && NUMA + default n + help + This enables moving irq_desc to cpu/node that irq will use handled. + + If you don't know what to do here, say N. + config X86_FIND_SMP_CONFIG def_bool y depends on X86_MPPARSE || X86_VOYAGER @@ -479,7 +501,7 @@ config HPET_TIMER The HPET provides a stable time base on SMP systems, unlike the TSC, but it is more expensive to access, as it is off-chip. You can find the HPET spec at - <http://www.intel.com/hardwaredesign/hpetspec.htm>. + <http://www.intel.com/hardwaredesign/hpetspec_1.pdf>. You can safely choose Y here. However, HPET will only be activated if the platform and the BIOS support this feature. diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index dc22c0733282..4035357f5b9d 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -65,7 +65,7 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) return dma_ops; else return dev->archdata.dma_ops; -#endif /* _ASM_X86_DMA_MAPPING_H */ +#endif } /* Make sure we keep the same behaviour */ diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index e475e009ae5d..7a1f44ac1f17 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -198,17 +198,14 @@ extern void restore_IO_APIC_setup(void); extern void reinit_intr_remapped_IO_APIC(int); #endif -extern int probe_nr_irqs(void); +extern void probe_nr_irqs_gsi(void); #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 static const int timer_through_8259 = 0; -static inline void ioapic_init_mappings(void) { } +static inline void ioapic_init_mappings(void) { } -static inline int probe_nr_irqs(void) -{ - return NR_IRQS; -} +static inline void probe_nr_irqs_gsi(void) { } #endif #endif /* _ASM_X86_IO_APIC_H */ diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 295b13193f4d..a6ee9e6f530f 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -7,8 +7,6 @@ extern struct dma_mapping_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; -extern unsigned long iommu_nr_pages(unsigned long addr, unsigned long len); - /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 0005adb0f941..f7ff65032b9d 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -101,12 +101,23 @@ #define LAST_VM86_IRQ 15 #define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) +#define NR_IRQS_LEGACY 16 + #if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER) + +#ifndef CONFIG_SPARSE_IRQ # if NR_CPUS < MAX_IO_APICS # define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) # else # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) # endif +#else +# if (8 * NR_CPUS) > (32 * MAX_IO_APICS) +# define NR_IRQS (NR_VECTORS + (8 * NR_CPUS)) +# else +# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) +# endif +#endif #elif defined(CONFIG_X86_VOYAGER) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 647781298e7e..66834c41c049 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -84,6 +84,8 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, static inline void early_quirks(void) { } #endif +extern void pci_iommu_alloc(void); + #endif /* __KERNEL__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pci_64.h b/arch/x86/include/asm/pci_64.h index d02d936840a3..4da207982777 100644 --- a/arch/x86/include/asm/pci_64.h +++ b/arch/x86/include/asm/pci_64.h @@ -23,7 +23,6 @@ extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value); extern void dma32_reserve_bootmem(void); -extern void pci_iommu_alloc(void); /* The PCI address space does equal the physical memory * address space. The networking and block device layers use diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 580c3ee6c58c..4340055b7559 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -157,6 +157,7 @@ extern int __get_user_bad(void); int __ret_gu; \ unsigned long __val_gu; \ __chk_user_ptr(ptr); \ + might_fault(); \ switch (sizeof(*(ptr))) { \ case 1: \ __get_user_x(1, __ret_gu, __val_gu, ptr); \ @@ -241,6 +242,7 @@ extern void __put_user_8(void); int __ret_pu; \ __typeof__(*(ptr)) __pu_val; \ __chk_user_ptr(ptr); \ + might_fault(); \ __pu_val = x; \ switch (sizeof(*(ptr))) { \ case 1: \ diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index d095a3aeea1b..5e06259e90e5 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -82,8 +82,8 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) static __always_inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { - might_sleep(); - return __copy_to_user_inatomic(to, from, n); + might_fault(); + return __copy_to_user_inatomic(to, from, n); } static __always_inline unsigned long @@ -137,7 +137,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { - might_sleep(); + might_fault(); if (__builtin_constant_p(n)) { unsigned long ret; @@ -159,7 +159,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) static __always_inline unsigned long __copy_from_user_nocache(void *to, const void __user *from, unsigned long n) { - might_sleep(); + might_fault(); if (__builtin_constant_p(n)) { unsigned long ret; diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index f8cfd00db450..84210c479fca 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -29,6 +29,8 @@ static __always_inline __must_check int __copy_from_user(void *dst, const void __user *src, unsigned size) { int ret = 0; + + might_fault(); if (!__builtin_constant_p(size)) return copy_user_generic(dst, (__force void *)src, size); switch (size) { @@ -71,6 +73,8 @@ static __always_inline __must_check int __copy_to_user(void __user *dst, const void *src, unsigned size) { int ret = 0; + + might_fault(); if (!__builtin_constant_p(size)) return copy_user_generic((__force void *)dst, src, size); switch (size) { @@ -113,6 +117,8 @@ static __always_inline __must_check int __copy_in_user(void __user *dst, const void __user *src, unsigned size) { int ret = 0; + + might_fault(); if (!__builtin_constant_p(size)) return copy_user_generic((__force void *)dst, (__force void *)src, size); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 88dd768eab6d..d364df03c1d6 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -109,6 +109,8 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o +obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o # NB rename without _64 + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) @@ -122,7 +124,6 @@ ifeq ($(CONFIG_X86_64),y) obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu_init.o amd_iommu.o - obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o endif diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 3f0a3edf0a57..845ea097383e 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -813,7 +813,7 @@ int __init hpet_enable(void) out_nohpet: hpet_clear_mapping(); - boot_hpet_disable = 1; + hpet_address = 0; return 0; } @@ -836,10 +836,11 @@ static __init int hpet_late_init(void) hpet_address = force_hpet_address; hpet_enable(); - if (!hpet_virt_address) - return -ENODEV; } + if (!hpet_virt_address) + return -ENODEV; + hpet_reserve_platform_timers(hpet_readl(HPET_ID)); for_each_online_cpu(cpu) { diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 679e7bbbbcd6..f6ea94b74da1 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -108,93 +108,252 @@ static int __init parse_noapic(char *str) early_param("noapic", parse_noapic); struct irq_pin_list; + +/* + * This is performance-critical, we want to do it O(1) + * + * the indexing order of this array favors 1:1 mappings + * between pins and IRQs. + */ + +struct irq_pin_list { + int apic, pin; + struct irq_pin_list *next; +}; + +static struct irq_pin_list *get_one_free_irq_2_pin(int cpu) +{ + struct irq_pin_list *pin; + int node; + + node = cpu_to_node(cpu); + + pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node); + printk(KERN_DEBUG " alloc irq_2_pin on cpu %d node %d\n", cpu, node); + + return pin; +} + struct irq_cfg { - unsigned int irq; struct irq_pin_list *irq_2_pin; cpumask_t domain; cpumask_t old_domain; unsigned move_cleanup_count; u8 vector; u8 move_in_progress : 1; +#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC + u8 move_desc_pending : 1; +#endif }; /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ +#ifdef CONFIG_SPARSE_IRQ +static struct irq_cfg irq_cfgx[] = { +#else static struct irq_cfg irq_cfgx[NR_IRQS] = { - [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, - [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, - [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, - [3] = { .irq = 3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, }, - [4] = { .irq = 4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, }, - [5] = { .irq = 5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, }, - [6] = { .irq = 6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, }, - [7] = { .irq = 7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, }, - [8] = { .irq = 8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, }, - [9] = { .irq = 9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, }, - [10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, }, - [11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, }, - [12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, }, - [13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, }, - [14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, }, - [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, +#endif + [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, + [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, + [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, + [3] = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, }, + [4] = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, }, + [5] = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, }, + [6] = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, }, + [7] = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, }, + [8] = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, }, + [9] = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, }, + [10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, }, + [11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, }, + [12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, }, + [13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, }, + [14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, }, + [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, }; -#define for_each_irq_cfg(irq, cfg) \ - for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++) +void __init arch_early_irq_init(void) +{ + struct irq_cfg *cfg; + struct irq_desc *desc; + int count; + int i; + + cfg = irq_cfgx; + count = ARRAY_SIZE(irq_cfgx); + + for (i = 0; i < count; i++) { + desc = irq_to_desc(i); + desc->chip_data = &cfg[i]; + } +} +#ifdef CONFIG_SPARSE_IRQ static struct irq_cfg *irq_cfg(unsigned int irq) { - return irq < nr_irqs ? irq_cfgx + irq : NULL; + struct irq_cfg *cfg = NULL; + struct irq_desc *desc; + + desc = irq_to_desc(irq); + if (desc) + cfg = desc->chip_data; + + return cfg; } -static struct irq_cfg *irq_cfg_alloc(unsigned int irq) +static struct irq_cfg *get_one_free_irq_cfg(int cpu) { - return irq_cfg(irq); + struct irq_cfg *cfg; + int node; + + node = cpu_to_node(cpu); + + cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node); + printk(KERN_DEBUG " alloc irq_cfg on cpu %d node %d\n", cpu, node); + + return cfg; } -/* - * Rough estimation of how many shared IRQs there are, can be changed - * anytime. - */ -#define MAX_PLUS_SHARED_IRQS NR_IRQS -#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) +void arch_init_chip_data(struct irq_desc *desc, int cpu) +{ + struct irq_cfg *cfg; -/* - * This is performance-critical, we want to do it O(1) - * - * the indexing order of this array favors 1:1 mappings - * between pins and IRQs. - */ + cfg = desc->chip_data; + if (!cfg) { + desc->chip_data = get_one_free_irq_cfg(cpu); + if (!desc->chip_data) { + printk(KERN_ERR "can not alloc irq_cfg\n"); + BUG_ON(1); + } + } +} -struct irq_pin_list { - int apic, pin; - struct irq_pin_list *next; -}; +#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC + +static void +init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu) +{ + struct irq_pin_list *old_entry, *head, *tail, *entry; + + cfg->irq_2_pin = NULL; + old_entry = old_cfg->irq_2_pin; + if (!old_entry) + return; -static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE]; -static struct irq_pin_list *irq_2_pin_ptr; + entry = get_one_free_irq_2_pin(cpu); + if (!entry) + return; -static void __init irq_2_pin_init(void) + entry->apic = old_entry->apic; + entry->pin = old_entry->pin; + head = entry; + tail = entry; + old_entry = old_entry->next; + while (old_entry) { + entry = get_one_free_irq_2_pin(cpu); + if (!entry) { + entry = head; + while (entry) { + head = entry->next; + kfree(entry); + entry = head; + } + /* still use the old one */ + return; + } + entry->apic = old_entry->apic; + entry->pin = old_entry->pin; + tail->next = entry; + tail = entry; + old_entry = old_entry->next; + } + + tail->next = NULL; + cfg->irq_2_pin = head; +} + +static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg) { - struct irq_pin_list *pin = irq_2_pin_head; - int i; + struct irq_pin_list *entry, *next; - for (i = 1; i < PIN_MAP_SIZE; i++) - pin[i-1].next = &pin[i]; + if (old_cfg->irq_2_pin == cfg->irq_2_pin) + return; + + entry = old_cfg->irq_2_pin; - irq_2_pin_ptr = &pin[0]; + while (entry) { + next = entry->next; + kfree(entry); + entry = next; + } + old_cfg->irq_2_pin = NULL; } -static struct irq_pin_list *get_one_free_irq_2_pin(void) +void arch_init_copy_chip_data(struct irq_desc *old_desc, + struct irq_desc *desc, int cpu) { - struct irq_pin_list *pin = irq_2_pin_ptr; + struct irq_cfg *cfg; + struct irq_cfg *old_cfg; - if (!pin) - panic("can not get more irq_2_pin\n"); + cfg = get_one_free_irq_cfg(cpu); - irq_2_pin_ptr = pin->next; - pin->next = NULL; - return pin; + if (!cfg) + return; + + desc->chip_data = cfg; + + old_cfg = old_desc->chip_data; + + memcpy(cfg, old_cfg, sizeof(struct irq_cfg)); + + init_copy_irq_2_pin(old_cfg, cfg, cpu); +} + +static void free_irq_cfg(struct irq_cfg *old_cfg) +{ + kfree(old_cfg); +} + +void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc) +{ + struct irq_cfg *old_cfg, *cfg; + + old_cfg = old_desc->chip_data; + cfg = desc->chip_data; + + if (old_cfg == cfg) + return; + + if (old_cfg) { + free_irq_2_pin(old_cfg, cfg); + free_irq_cfg(old_cfg); + old_desc->chip_data = NULL; + } +} + +static void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask) +{ + struct irq_cfg *cfg = desc->chip_data; + + if (!cfg->move_in_progress) { + /* it means that domain is not changed */ + if (!cpus_intersects(desc->affinity, mask)) + cfg->move_desc_pending = 1; + } } +#endif + +#else +static struct irq_cfg *irq_cfg(unsigned int irq) +{ + return irq < nr_irqs ? irq_cfgx + irq : NULL; +} + +#endif + +#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC +static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask) +{ +} +#endif struct io_apic { unsigned int index; @@ -237,11 +396,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned writel(value, &io_apic->data); } -static bool io_apic_level_ack_pending(unsigned int irq) +static bool io_apic_level_ack_pending(struct irq_cfg *cfg) { struct irq_pin_list *entry; unsigned long flags; - struct irq_cfg *cfg = irq_cfg(irq); spin_lock_irqsave(&ioapic_lock, flags); entry = cfg->irq_2_pin; @@ -323,13 +481,12 @@ static void ioapic_mask_entry(int apic, int pin) } #ifdef CONFIG_SMP -static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) +static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) { int apic, pin; - struct irq_cfg *cfg; struct irq_pin_list *entry; + u8 vector = cfg->vector; - cfg = irq_cfg(irq); entry = cfg->irq_2_pin; for (;;) { unsigned int reg; @@ -359,24 +516,27 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) } } -static int assign_irq_vector(int irq, cpumask_t mask); +static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask); -static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +static void set_ioapic_affinity_irq_desc(struct irq_desc *desc, cpumask_t mask) { struct irq_cfg *cfg; unsigned long flags; unsigned int dest; cpumask_t tmp; - struct irq_desc *desc; + unsigned int irq; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) return; - cfg = irq_cfg(irq); - if (assign_irq_vector(irq, mask)) + irq = desc->irq; + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); /* @@ -384,12 +544,20 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) */ dest = SET_APIC_LOGICAL_ID(dest); - desc = irq_to_desc(irq); spin_lock_irqsave(&ioapic_lock, flags); - __target_IO_APIC_irq(irq, dest, cfg->vector); + __target_IO_APIC_irq(irq, dest, cfg); desc->affinity = mask; spin_unlock_irqrestore(&ioapic_lock, flags); } + +static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +{ + struct irq_desc *desc; + + desc = irq_to_desc(irq); + + set_ioapic_affinity_irq_desc(desc, mask); +} #endif /* CONFIG_SMP */ /* @@ -397,16 +565,18 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static void add_pin_to_irq(unsigned int irq, int apic, int pin) +static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin) { - struct irq_cfg *cfg; struct irq_pin_list *entry; - /* first time to refer irq_cfg, so with new */ - cfg = irq_cfg_alloc(irq); entry = cfg->irq_2_pin; if (!entry) { - entry = get_one_free_irq_2_pin(); + entry = get_one_free_irq_2_pin(cpu); + if (!entry) { + printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n", + apic, pin); + return; + } cfg->irq_2_pin = entry; entry->apic = apic; entry->pin = pin; @@ -421,7 +591,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) entry = entry->next; } - entry->next = get_one_free_irq_2_pin(); + entry->next = get_one_free_irq_2_pin(cpu); entry = entry->next; entry->apic = apic; entry->pin = pin; @@ -430,11 +600,10 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) /* * Reroute an IRQ to a different pin. */ -static void __init replace_pin_at_irq(unsigned int irq, +static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu, int oldapic, int oldpin, int newapic, int newpin) { - struct irq_cfg *cfg = irq_cfg(irq); struct irq_pin_list *entry = cfg->irq_2_pin; int replaced = 0; @@ -451,18 +620,16 @@ static void __init replace_pin_at_irq(unsigned int irq, /* why? call replace before add? */ if (!replaced) - add_pin_to_irq(irq, newapic, newpin); + add_pin_to_irq_cpu(cfg, cpu, newapic, newpin); } -static inline void io_apic_modify_irq(unsigned int irq, +static inline void io_apic_modify_irq(struct irq_cfg *cfg, int mask_and, int mask_or, void (*final)(struct irq_pin_list *entry)) { int pin; - struct irq_cfg *cfg; struct irq_pin_list *entry; - cfg = irq_cfg(irq); for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { unsigned int reg; pin = entry->pin; @@ -475,9 +642,9 @@ static inline void io_apic_modify_irq(unsigned int irq, } } -static void __unmask_IO_APIC_irq(unsigned int irq) +static void __unmask_IO_APIC_irq(struct irq_cfg *cfg) { - io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL); + io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL); } #ifdef CONFIG_X86_64 @@ -492,47 +659,64 @@ void io_apic_sync(struct irq_pin_list *entry) readl(&io_apic->data); } -static void __mask_IO_APIC_irq(unsigned int irq) +static void __mask_IO_APIC_irq(struct irq_cfg *cfg) { - io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); + io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); } #else /* CONFIG_X86_32 */ -static void __mask_IO_APIC_irq(unsigned int irq) +static void __mask_IO_APIC_irq(struct irq_cfg *cfg) { - io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL); + io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL); } -static void __mask_and_edge_IO_APIC_irq(unsigned int irq) +static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg) { - io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER, + io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER, IO_APIC_REDIR_MASKED, NULL); } -static void __unmask_and_level_IO_APIC_irq(unsigned int irq) +static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg) { - io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, + io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, IO_APIC_REDIR_LEVEL_TRIGGER, NULL); } #endif /* CONFIG_X86_32 */ -static void mask_IO_APIC_irq (unsigned int irq) +static void mask_IO_APIC_irq_desc(struct irq_desc *desc) { + struct irq_cfg *cfg = desc->chip_data; unsigned long flags; + BUG_ON(!cfg); + spin_lock_irqsave(&ioapic_lock, flags); - __mask_IO_APIC_irq(irq); + __mask_IO_APIC_irq(cfg); spin_unlock_irqrestore(&ioapic_lock, flags); } -static void unmask_IO_APIC_irq (unsigned int irq) +static void unmask_IO_APIC_irq_desc(struct irq_desc *desc) { + struct irq_cfg *cfg = desc->chip_data; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - __unmask_IO_APIC_irq(irq); + __unmask_IO_APIC_irq(cfg); spin_unlock_irqrestore(&ioapic_lock, flags); } +static void mask_IO_APIC_irq(unsigned int irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + + mask_IO_APIC_irq_desc(desc); +} +static void unmask_IO_APIC_irq(unsigned int irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + + unmask_IO_APIC_irq_desc(desc); +} + static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) { struct IO_APIC_route_entry entry; @@ -809,7 +993,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); */ static int EISA_ELCR(unsigned int irq) { - if (irq < 16) { + if (irq < NR_IRQS_LEGACY) { unsigned int port = 0x4d0 + (irq >> 3); return (inb(port) >> (irq & 7)) & 1; } @@ -1034,7 +1218,7 @@ void unlock_vector_lock(void) spin_unlock(&vector_lock); } -static int __assign_irq_vector(int irq, cpumask_t mask) +static int __assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask) { /* * NOTE! The local APIC isn't very good at handling @@ -1050,16 +1234,13 @@ static int __assign_irq_vector(int irq, cpumask_t mask) static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; unsigned int old_vector; int cpu; - struct irq_cfg *cfg; - cfg = irq_cfg(irq); + if ((cfg->move_in_progress) || cfg->move_cleanup_count) + return -EBUSY; /* Only try and allocate irqs on cpus that are present */ cpus_and(mask, mask, cpu_online_map); - if ((cfg->move_in_progress) || cfg->move_cleanup_count) - return -EBUSY; - old_vector = cfg->vector; if (old_vector) { cpumask_t tmp; @@ -1113,24 +1294,22 @@ next: return -ENOSPC; } -static int assign_irq_vector(int irq, cpumask_t mask) +static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask) { int err; unsigned long flags; spin_lock_irqsave(&vector_lock, flags); - err = __assign_irq_vector(irq, mask); + err = __assign_irq_vector(irq, cfg, mask); spin_unlock_irqrestore(&vector_lock, flags); return err; } -static void __clear_irq_vector(int irq) +static void __clear_irq_vector(int irq, struct irq_cfg *cfg) { - struct irq_cfg *cfg; cpumask_t mask; int cpu, vector; - cfg = irq_cfg(irq); BUG_ON(!cfg->vector); vector = cfg->vector; @@ -1162,9 +1341,13 @@ void __setup_vector_irq(int cpu) /* This function must be called with vector_lock held */ int irq, vector; struct irq_cfg *cfg; + struct irq_desc *desc; /* Mark the inuse vectors */ - for_each_irq_cfg(irq, cfg) { + for_each_irq_desc(irq, desc) { + if (!desc) + continue; + cfg = desc->chip_data; if (!cpu_isset(cpu, cfg->domain)) continue; vector = cfg->vector; @@ -1215,11 +1398,8 @@ static inline int IO_APIC_irq_trigger(int irq) } #endif -static void ioapic_register_intr(int irq, unsigned long trigger) +static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger) { - struct irq_desc *desc; - - desc = irq_to_desc(irq); if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || trigger == IOAPIC_LEVEL) @@ -1311,7 +1491,7 @@ static int setup_ioapic_entry(int apic, int irq, return 0; } -static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, +static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc, int trigger, int polarity) { struct irq_cfg *cfg; @@ -1321,10 +1501,10 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, if (!IO_APIC_IRQ(irq)) return; - cfg = irq_cfg(irq); + cfg = desc->chip_data; mask = TARGET_CPUS; - if (assign_irq_vector(irq, mask)) + if (assign_irq_vector(irq, cfg, mask)) return; cpus_and(mask, cfg->domain, mask); @@ -1341,12 +1521,12 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, cfg->vector)) { printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", mp_ioapics[apic].mp_apicid, pin); - __clear_irq_vector(irq); + __clear_irq_vector(irq, cfg); return; } - ioapic_register_intr(irq, trigger); - if (irq < 16) + ioapic_register_intr(irq, desc, trigger); + if (irq < NR_IRQS_LEGACY) disable_8259A_irq(irq); ioapic_write_entry(apic, pin, entry); @@ -1356,6 +1536,9 @@ static void __init setup_IO_APIC_irqs(void) { int apic, pin, idx, irq; int notcon = 0; + struct irq_desc *desc; + struct irq_cfg *cfg; + int cpu = boot_cpu_id; apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); @@ -1387,9 +1570,15 @@ static void __init setup_IO_APIC_irqs(void) if (multi_timer_check(apic, irq)) continue; #endif - add_pin_to_irq(irq, apic, pin); + desc = irq_to_desc_alloc_cpu(irq, cpu); + if (!desc) { + printk(KERN_INFO "can not get irq_desc for %d\n", irq); + continue; + } + cfg = desc->chip_data; + add_pin_to_irq_cpu(cfg, cpu, apic, pin); - setup_IO_APIC_irq(apic, pin, irq, + setup_IO_APIC_irq(apic, pin, irq, desc, irq_trigger(idx), irq_polarity(idx)); } } @@ -1448,6 +1637,7 @@ __apicdebuginit(void) print_IO_APIC(void) union IO_APIC_reg_03 reg_03; unsigned long flags; struct irq_cfg *cfg; + struct irq_desc *desc; unsigned int irq; if (apic_verbosity == APIC_QUIET) @@ -1537,8 +1727,13 @@ __apicdebuginit(void) print_IO_APIC(void) } } printk(KERN_DEBUG "IRQ to pin mappings:\n"); - for_each_irq_cfg(irq, cfg) { - struct irq_pin_list *entry = cfg->irq_2_pin; + for_each_irq_desc(irq, desc) { + struct irq_pin_list *entry; + + if (!desc) + continue; + cfg = desc->chip_data; + entry = cfg->irq_2_pin; if (!entry) continue; printk(KERN_DEBUG "IRQ%d ", irq); @@ -2022,14 +2217,16 @@ static unsigned int startup_ioapic_irq(unsigned int irq) { int was_pending = 0; unsigned long flags; + struct irq_cfg *cfg; spin_lock_irqsave(&ioapic_lock, flags); - if (irq < 16) { + if (irq < NR_IRQS_LEGACY) { disable_8259A_irq(irq); if (i8259A_irq_pending(irq)) was_pending = 1; } - __unmask_IO_APIC_irq(irq); + cfg = irq_cfg(irq); + __unmask_IO_APIC_irq(cfg); spin_unlock_irqrestore(&ioapic_lock, flags); return was_pending; @@ -2092,35 +2289,37 @@ static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration); * as simple as edge triggered migration and we can do the irq migration * with a simple atomic update to IO-APIC RTE. */ -static void migrate_ioapic_irq(int irq, cpumask_t mask) +static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask) { struct irq_cfg *cfg; - struct irq_desc *desc; cpumask_t tmp, cleanup_mask; struct irte irte; int modify_ioapic_rte; unsigned int dest; unsigned long flags; + unsigned int irq; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) return; + irq = desc->irq; if (get_irte(irq, &irte)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); - desc = irq_to_desc(irq); modify_ioapic_rte = desc->status & IRQ_LEVEL; if (modify_ioapic_rte) { spin_lock_irqsave(&ioapic_lock, flags); - __target_IO_APIC_irq(irq, dest, cfg->vector); + __target_IO_APIC_irq(irq, dest, cfg); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -2142,14 +2341,14 @@ static void migrate_ioapic_irq(int irq, cpumask_t mask) desc->affinity = mask; } -static int migrate_irq_remapped_level(int irq) +static int migrate_irq_remapped_level_desc(struct irq_desc *desc) { int ret = -1; - struct irq_desc *desc = irq_to_desc(irq); + struct irq_cfg *cfg = desc->chip_data; - mask_IO_APIC_irq(irq); + mask_IO_APIC_irq_desc(desc); - if (io_apic_level_ack_pending(irq)) { + if (io_apic_level_ack_pending(cfg)) { /* * Interrupt in progress. Migrating irq now will change the * vector information in the IO-APIC RTE and that will confuse @@ -2161,14 +2360,15 @@ static int migrate_irq_remapped_level(int irq) } /* everthing is clear. we have right of way */ - migrate_ioapic_irq(irq, desc->pending_mask); + migrate_ioapic_irq_desc(desc, desc->pending_mask); ret = 0; desc->status &= ~IRQ_MOVE_PENDING; cpus_clear(desc->pending_mask); unmask: - unmask_IO_APIC_irq(irq); + unmask_IO_APIC_irq_desc(desc); + return ret; } @@ -2178,6 +2378,9 @@ static void ir_irq_migration(struct work_struct *work) struct irq_desc *desc; for_each_irq_desc(irq, desc) { + if (!desc) + continue; + if (desc->status & IRQ_MOVE_PENDING) { unsigned long flags; @@ -2198,18 +2401,22 @@ static void ir_irq_migration(struct work_struct *work) /* * Migrates the IRQ destination in the process context. */ -static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, cpumask_t mask) { - struct irq_desc *desc = irq_to_desc(irq); - if (desc->status & IRQ_LEVEL) { desc->status |= IRQ_MOVE_PENDING; desc->pending_mask = mask; - migrate_irq_remapped_level(irq); + migrate_irq_remapped_level_desc(desc); return; } - migrate_ioapic_irq(irq, mask); + migrate_ioapic_irq_desc(desc, mask); +} +static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +{ + struct irq_desc *desc = irq_to_desc(irq); + + set_ir_ioapic_affinity_irq_desc(desc, mask); } #endif @@ -2228,6 +2435,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) struct irq_cfg *cfg; irq = __get_cpu_var(vector_irq)[vector]; + if (irq == -1) + continue; + desc = irq_to_desc(irq); if (!desc) continue; @@ -2249,19 +2459,40 @@ unlock: irq_exit(); } -static void irq_complete_move(unsigned int irq) +static void irq_complete_move(struct irq_desc **descp) { - struct irq_cfg *cfg = irq_cfg(irq); + struct irq_desc *desc = *descp; + struct irq_cfg *cfg = desc->chip_data; unsigned vector, me; - if (likely(!cfg->move_in_progress)) + if (likely(!cfg->move_in_progress)) { +#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC + if (likely(!cfg->move_desc_pending)) + return; + + /* domain has not changed, but affinity did */ + me = smp_processor_id(); + if (cpu_isset(me, desc->affinity)) { + *descp = desc = move_irq_desc(desc, me); + /* get the new one */ + cfg = desc->chip_data; + cfg->move_desc_pending = 0; + } +#endif return; + } vector = ~get_irq_regs()->orig_ax; me = smp_processor_id(); if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) { cpumask_t cleanup_mask; +#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC + *descp = desc = move_irq_desc(desc, me); + /* get the new one */ + cfg = desc->chip_data; +#endif + cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map); cfg->move_cleanup_count = cpus_weight(cleanup_mask); send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); @@ -2269,8 +2500,9 @@ static void irq_complete_move(unsigned int irq) } } #else -static inline void irq_complete_move(unsigned int irq) {} +static inline void irq_complete_move(struct irq_desc **descp) {} #endif + #ifdef CONFIG_INTR_REMAP static void ack_x2apic_level(unsigned int irq) { @@ -2281,11 +2513,14 @@ static void ack_x2apic_edge(unsigned int irq) { ack_x2APIC_irq(); } + #endif static void ack_apic_edge(unsigned int irq) { - irq_complete_move(irq); + struct irq_desc *desc = irq_to_desc(irq); + + irq_complete_move(&desc); move_native_irq(irq); ack_APIC_irq(); } @@ -2294,18 +2529,21 @@ atomic_t irq_mis_count; static void ack_apic_level(unsigned int irq) { + struct irq_desc *desc = irq_to_desc(irq); + #ifdef CONFIG_X86_32 unsigned long v; int i; #endif + struct irq_cfg *cfg; int do_unmask_irq = 0; - irq_complete_move(irq); + irq_complete_move(&desc); #ifdef CONFIG_GENERIC_PENDING_IRQ /* If we are moving the irq we need to mask it */ - if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { + if (unlikely(desc->status & IRQ_MOVE_PENDING)) { do_unmask_irq = 1; - mask_IO_APIC_irq(irq); + mask_IO_APIC_irq_desc(desc); } #endif @@ -2329,7 +2567,8 @@ static void ack_apic_level(unsigned int irq) * operation to prevent an edge-triggered interrupt escaping meanwhile. * The idea is from Manfred Spraul. --macro */ - i = irq_cfg(irq)->vector; + cfg = desc->chip_data; + i = cfg->vector; v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); #endif @@ -2368,17 +2607,18 @@ static void ack_apic_level(unsigned int irq) * accurate and is causing problems then it is a hardware bug * and you can go talk to the chipset vendor about it. */ - if (!io_apic_level_ack_pending(irq)) + cfg = desc->chip_data; + if (!io_apic_level_ack_pending(cfg)) move_masked_irq(irq); - unmask_IO_APIC_irq(irq); + unmask_IO_APIC_irq_desc(desc); } #ifdef CONFIG_X86_32 if (!(v & (1 << (i & 0x1f)))) { atomic_inc(&irq_mis_count); spin_lock(&ioapic_lock); - __mask_and_edge_IO_APIC_irq(irq); - __unmask_and_level_IO_APIC_irq(irq); + __mask_and_edge_IO_APIC_irq(cfg); + __unmask_and_level_IO_APIC_irq(cfg); spin_unlock(&ioapic_lock); } #endif @@ -2429,20 +2669,22 @@ static inline void init_IO_APIC_traps(void) * Also, we've got to be careful not to trash gate * 0x80, because int 0x80 is hm, kind of importantish. ;) */ - for_each_irq_cfg(irq, cfg) { - if (IO_APIC_IRQ(irq) && !cfg->vector) { + for_each_irq_desc(irq, desc) { + if (!desc) + continue; + + cfg = desc->chip_data; + if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { /* * Hmm.. We don't have an entry for this, * so default to an old-fashioned 8259 * interrupt if we can.. */ - if (irq < 16) + if (irq < NR_IRQS_LEGACY) make_8259A_irq(irq); - else { - desc = irq_to_desc(irq); + else /* Strange. Oh, well.. */ desc->chip = &no_irq_chip; - } } } } @@ -2467,7 +2709,7 @@ static void unmask_lapic_irq(unsigned int irq) apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); } -static void ack_lapic_irq (unsigned int irq) +static void ack_lapic_irq(unsigned int irq) { ack_APIC_irq(); } @@ -2479,11 +2721,8 @@ static struct irq_chip lapic_chip __read_mostly = { .ack = ack_lapic_irq, }; -static void lapic_register_intr(int irq) +static void lapic_register_intr(int irq, struct irq_desc *desc) { - struct irq_desc *desc; - - desc = irq_to_desc(irq); desc->status &= ~IRQ_LEVEL; set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, "edge"); @@ -2587,7 +2826,9 @@ int timer_through_8259 __initdata; */ static inline void __init check_timer(void) { - struct irq_cfg *cfg = irq_cfg(0); + struct irq_desc *desc = irq_to_desc(0); + struct irq_cfg *cfg = desc->chip_data; + int cpu = boot_cpu_id; int apic1, pin1, apic2, pin2; unsigned long flags; unsigned int ver; @@ -2602,7 +2843,7 @@ static inline void __init check_timer(void) * get/set the timer IRQ vector: */ disable_8259A_irq(0); - assign_irq_vector(0, TARGET_CPUS); + assign_irq_vector(0, cfg, TARGET_CPUS); /* * As IRQ0 is to be enabled in the 8259A, the virtual @@ -2653,10 +2894,10 @@ static inline void __init check_timer(void) * Ok, does IRQ0 through the IOAPIC work? */ if (no_pin1) { - add_pin_to_irq(0, apic1, pin1); + add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); } - unmask_IO_APIC_irq(0); + unmask_IO_APIC_irq_desc(desc); if (timer_irq_works()) { if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); @@ -2682,9 +2923,9 @@ static inline void __init check_timer(void) /* * legacy devices should be connected to IO APIC #0 */ - replace_pin_at_irq(0, apic1, pin1, apic2, pin2); + replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); - unmask_IO_APIC_irq(0); + unmask_IO_APIC_irq_desc(desc); enable_8259A_irq(0); if (timer_irq_works()) { apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); @@ -2716,7 +2957,7 @@ static inline void __init check_timer(void) apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...\n"); - lapic_register_intr(0); + lapic_register_intr(0, desc); apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ enable_8259A_irq(0); @@ -2901,22 +3142,26 @@ unsigned int create_irq_nr(unsigned int irq_want) unsigned int irq; unsigned int new; unsigned long flags; - struct irq_cfg *cfg_new; - - irq_want = nr_irqs - 1; + struct irq_cfg *cfg_new = NULL; + int cpu = boot_cpu_id; + struct irq_desc *desc_new = NULL; irq = 0; spin_lock_irqsave(&vector_lock, flags); - for (new = irq_want; new > 0; new--) { + for (new = irq_want; new < NR_IRQS; new++) { if (platform_legacy_irq(new)) continue; - cfg_new = irq_cfg(new); - if (cfg_new && cfg_new->vector != 0) + + desc_new = irq_to_desc_alloc_cpu(new, cpu); + if (!desc_new) { + printk(KERN_INFO "can not get irq_desc for %d\n", new); continue; - /* check if need to create one */ - if (!cfg_new) - cfg_new = irq_cfg_alloc(new); - if (__assign_irq_vector(new, TARGET_CPUS) == 0) + } + cfg_new = desc_new->chip_data; + + if (cfg_new->vector != 0) + continue; + if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0) irq = new; break; } @@ -2924,15 +3169,21 @@ unsigned int create_irq_nr(unsigned int irq_want) if (irq > 0) { dynamic_irq_init(irq); + /* restore it, in case dynamic_irq_init clear it */ + if (desc_new) + desc_new->chip_data = cfg_new; } return irq; } +static int nr_irqs_gsi = NR_IRQS_LEGACY; int create_irq(void) { + unsigned int irq_want; int irq; - irq = create_irq_nr(nr_irqs - 1); + irq_want = nr_irqs_gsi; + irq = create_irq_nr(irq_want); if (irq == 0) irq = -1; @@ -2943,14 +3194,22 @@ int create_irq(void) void destroy_irq(unsigned int irq) { unsigned long flags; + struct irq_cfg *cfg; + struct irq_desc *desc; + /* store it, in case dynamic_irq_cleanup clear it */ + desc = irq_to_desc(irq); + cfg = desc->chip_data; dynamic_irq_cleanup(irq); + /* connect back irq_cfg */ + if (desc) + desc->chip_data = cfg; #ifdef CONFIG_INTR_REMAP free_irte(irq); #endif spin_lock_irqsave(&vector_lock, flags); - __clear_irq_vector(irq); + __clear_irq_vector(irq, cfg); spin_unlock_irqrestore(&vector_lock, flags); } @@ -2965,12 +3224,12 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms unsigned dest; cpumask_t tmp; + cfg = irq_cfg(irq); tmp = TARGET_CPUS; - err = assign_irq_vector(irq, tmp); + err = assign_irq_vector(irq, cfg, tmp); if (err) return err; - cfg = irq_cfg(irq); cpus_and(tmp, cfg->domain, tmp); dest = cpu_mask_to_apicid(tmp); @@ -3028,35 +3287,35 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms #ifdef CONFIG_SMP static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) { + struct irq_desc *desc = irq_to_desc(irq); struct irq_cfg *cfg; struct msi_msg msg; unsigned int dest; cpumask_t tmp; - struct irq_desc *desc; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); - read_msi_msg(irq, &msg); + read_msi_msg_desc(desc, &msg); msg.data &= ~MSI_DATA_VECTOR_MASK; msg.data |= MSI_DATA_VECTOR(cfg->vector); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); - write_msi_msg(irq, &msg); - desc = irq_to_desc(irq); + write_msi_msg_desc(desc, &msg); desc->affinity = mask; } - #ifdef CONFIG_INTR_REMAP /* * Migrate the MSI irq to another cpumask. This migration is @@ -3064,11 +3323,11 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) */ static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask) { + struct irq_desc *desc = irq_to_desc(irq); struct irq_cfg *cfg; unsigned int dest; cpumask_t tmp, cleanup_mask; struct irte irte; - struct irq_desc *desc; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) @@ -3077,10 +3336,12 @@ static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask) if (get_irte(irq, &irte)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); @@ -3104,9 +3365,9 @@ static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask) cfg->move_in_progress = 0; } - desc = irq_to_desc(irq); desc->affinity = mask; } + #endif #endif /* CONFIG_SMP */ @@ -3165,7 +3426,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) } #endif -static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) +static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) { int ret; struct msi_msg msg; @@ -3174,7 +3435,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) if (ret < 0) return ret; - set_irq_msi(irq, desc); + set_irq_msi(irq, msidesc); write_msi_msg(irq, &msg); #ifdef CONFIG_INTR_REMAP @@ -3194,26 +3455,13 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) return 0; } -static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) -{ - unsigned int irq; - - irq = dev->bus->number; - irq <<= 8; - irq |= dev->devfn; - irq <<= 12; - - return irq; -} - -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc) { unsigned int irq; int ret; unsigned int irq_want; - irq_want = build_irq_for_pci_dev(dev) + 0x100; - + irq_want = nr_irqs_gsi; irq = create_irq_nr(irq_want); if (irq == 0) return -1; @@ -3227,7 +3475,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) goto error; no_ir: #endif - ret = setup_msi_irq(dev, desc, irq); + ret = setup_msi_irq(dev, msidesc, irq); if (ret < 0) { destroy_irq(irq); return ret; @@ -3245,7 +3493,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { unsigned int irq; int ret, sub_handle; - struct msi_desc *desc; + struct msi_desc *msidesc; unsigned int irq_want; #ifdef CONFIG_INTR_REMAP @@ -3253,10 +3501,11 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) int index = 0; #endif - irq_want = build_irq_for_pci_dev(dev) + 0x100; + irq_want = nr_irqs_gsi; sub_handle = 0; - list_for_each_entry(desc, &dev->msi_list, list) { - irq = create_irq_nr(irq_want--); + list_for_each_entry(msidesc, &dev->msi_list, list) { + irq = create_irq_nr(irq_want); + irq_want++; if (irq == 0) return -1; #ifdef CONFIG_INTR_REMAP @@ -3288,7 +3537,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) } no_ir: #endif - ret = setup_msi_irq(dev, desc, irq); + ret = setup_msi_irq(dev, msidesc, irq); if (ret < 0) goto error; sub_handle++; @@ -3309,20 +3558,22 @@ void arch_teardown_msi_irq(unsigned int irq) #ifdef CONFIG_SMP static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) { + struct irq_desc *desc = irq_to_desc(irq); struct irq_cfg *cfg; struct msi_msg msg; unsigned int dest; cpumask_t tmp; - struct irq_desc *desc; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); @@ -3334,9 +3585,9 @@ static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) msg.address_lo |= MSI_ADDR_DEST_ID(dest); dmar_msi_write(irq, &msg); - desc = irq_to_desc(irq); desc->affinity = mask; } + #endif /* CONFIG_SMP */ struct irq_chip dmar_msi_type = { @@ -3370,8 +3621,8 @@ int arch_setup_dmar_msi(unsigned int irq) #ifdef CONFIG_SMP static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask) { + struct irq_desc *desc = irq_to_desc(irq); struct irq_cfg *cfg; - struct irq_desc *desc; struct msi_msg msg; unsigned int dest; cpumask_t tmp; @@ -3380,10 +3631,12 @@ static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask) if (cpus_empty(tmp)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); @@ -3395,9 +3648,9 @@ static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask) msg.address_lo |= MSI_ADDR_DEST_ID(dest); hpet_msi_write(irq, &msg); - desc = irq_to_desc(irq); desc->affinity = mask; } + #endif /* CONFIG_SMP */ struct irq_chip hpet_msi_type = { @@ -3452,26 +3705,28 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) { + struct irq_desc *desc = irq_to_desc(irq); struct irq_cfg *cfg; unsigned int dest; cpumask_t tmp; - struct irq_desc *desc; cpus_and(tmp, mask, cpu_online_map); if (cpus_empty(tmp)) return; - if (assign_irq_vector(irq, mask)) + cfg = desc->chip_data; + if (assign_irq_vector(irq, cfg, mask)) return; - cfg = irq_cfg(irq); + set_extra_move_desc(desc, mask); + cpus_and(tmp, cfg->domain, mask); dest = cpu_mask_to_apicid(tmp); target_ht_irq(irq, dest, cfg->vector); - desc = irq_to_desc(irq); desc->affinity = mask; } + #endif static struct irq_chip ht_irq_chip = { @@ -3491,13 +3746,13 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) int err; cpumask_t tmp; + cfg = irq_cfg(irq); tmp = TARGET_CPUS; - err = assign_irq_vector(irq, tmp); + err = assign_irq_vector(irq, cfg, tmp); if (!err) { struct ht_irq_msg msg; unsigned dest; - cfg = irq_cfg(irq); cpus_and(tmp, cfg->domain, tmp); dest = cpu_mask_to_apicid(tmp); @@ -3543,7 +3798,9 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, unsigned long flags; int err; - err = assign_irq_vector(irq, *eligible_cpu); + cfg = irq_cfg(irq); + + err = assign_irq_vector(irq, cfg, *eligible_cpu); if (err != 0) return err; @@ -3552,8 +3809,6 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, irq_name); spin_unlock_irqrestore(&vector_lock, flags); - cfg = irq_cfg(irq); - mmr_value = 0; entry = (struct uv_IO_APIC_route_entry *)&mmr_value; BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); @@ -3605,9 +3860,16 @@ int __init io_apic_get_redir_entries (int ioapic) return reg_01.bits.entries; } -int __init probe_nr_irqs(void) +void __init probe_nr_irqs_gsi(void) { - return NR_IRQS; + int idx; + int nr = 0; + + for (idx = 0; idx < nr_ioapics; idx++) + nr += io_apic_get_redir_entries(idx) + 1; + + if (nr > nr_irqs_gsi) + nr_irqs_gsi = nr; } /* -------------------------------------------------------------------------- @@ -3706,19 +3968,31 @@ int __init io_apic_get_version(int ioapic) int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity) { + struct irq_desc *desc; + struct irq_cfg *cfg; + int cpu = boot_cpu_id; + if (!IO_APIC_IRQ(irq)) { apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", ioapic); return -EINVAL; } + desc = irq_to_desc_alloc_cpu(irq, cpu); + if (!desc) { + printk(KERN_INFO "can not get irq_desc %d\n", irq); + return 0; + } + /* * IRQs < 16 are already in the irq_2_pin[] map */ - if (irq >= 16) - add_pin_to_irq(irq, ioapic, pin); + if (irq >= NR_IRQS_LEGACY) { + cfg = desc->chip_data; + add_pin_to_irq_cpu(cfg, cpu, ioapic, pin); + } - setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity); + setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity); return 0; } @@ -3772,9 +4046,10 @@ void __init setup_ioapic_dest(void) * when you have too many devices, because at that time only boot * cpu is online. */ - cfg = irq_cfg(irq); + desc = irq_to_desc(irq); + cfg = desc->chip_data; if (!cfg->vector) { - setup_IO_APIC_irq(ioapic, pin, irq, + setup_IO_APIC_irq(ioapic, pin, irq, desc, irq_trigger(irq_entry), irq_polarity(irq_entry)); continue; @@ -3784,7 +4059,6 @@ void __init setup_ioapic_dest(void) /* * Honour affinities which have been set in early boot */ - desc = irq_to_desc(irq); if (desc->status & (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) mask = desc->affinity; @@ -3793,10 +4067,10 @@ void __init setup_ioapic_dest(void) #ifdef CONFIG_INTR_REMAP if (intr_remapping_enabled) - set_ir_ioapic_affinity_irq(irq, mask); + set_ir_ioapic_affinity_irq_desc(desc, mask); else #endif - set_ioapic_affinity_irq(irq, mask); + set_ioapic_affinity_irq_desc(desc, mask); } } @@ -3845,7 +4119,6 @@ void __init ioapic_init_mappings(void) struct resource *ioapic_res; int i; - irq_2_pin_init(); ioapic_res = ioapic_setup_resources(); for (i = 0; i < nr_ioapics; i++) { if (smp_found_config) { diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index d1d4dc52f649..3f1d9d18df67 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -118,6 +118,9 @@ int show_interrupts(struct seq_file *p, void *v) } desc = irq_to_desc(i); + if (!desc) + return 0; + spin_lock_irqsave(&desc->lock, flags); #ifndef CONFIG_SMP any_count = kstat_irqs(i); diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index a51382672de0..119fc9c8ff7f 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -242,6 +242,8 @@ void fixup_irqs(cpumask_t map) for_each_irq_desc(irq, desc) { cpumask_t mask; + if (!desc) + continue; if (irq == 2) continue; diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 1df869e5bd0b..a174a217eb1a 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -91,6 +91,8 @@ void fixup_irqs(cpumask_t map) int break_affinity = 0; int set_affinity = 1; + if (!desc) + continue; if (irq == 2) continue; diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 607db63044a5..203384ed2b5d 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c @@ -68,8 +68,7 @@ void __init init_ISA_irqs (void) /* * 16 old-style INTA-cycle interrupts: */ - for (i = 0; i < 16; i++) { - /* first time call this irq_desc */ + for (i = 0; i < NR_IRQS_LEGACY; i++) { struct irq_desc *desc = irq_to_desc(i); desc->status = IRQ_DISABLED; diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index 8670b3ce626e..6190e6ef546c 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c @@ -76,8 +76,7 @@ void __init init_ISA_irqs(void) init_bsp_APIC(); init_8259A(0); - for (i = 0; i < 16; i++) { - /* first time call this irq_desc */ + for (i = 0; i < NR_IRQS_LEGACY; i++) { struct irq_desc *desc = irq_to_desc(i); desc->status = IRQ_DISABLED; diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 7a3dfceb90e4..19a1044a0cd9 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -101,11 +101,15 @@ static void __init dma32_free_bootmem(void) dma32_bootmem_ptr = NULL; dma32_bootmem_size = 0; } +#endif void __init pci_iommu_alloc(void) { +#ifdef CONFIG_X86_64 /* free the range so iommu could get some range less than 4G */ dma32_free_bootmem(); +#endif + /* * The order of these functions is important for * fall-back/fail-over reasons @@ -121,15 +125,6 @@ void __init pci_iommu_alloc(void) pci_swiotlb_init(); } -unsigned long iommu_nr_pages(unsigned long addr, unsigned long len) -{ - unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE); - - return size >> PAGE_SHIFT; -} -EXPORT_SYMBOL(iommu_nr_pages); -#endif - void *dma_generic_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag) { diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c index 3c539d111abb..242c3440687f 100644 --- a/arch/x86/kernel/pci-swiotlb_64.c +++ b/arch/x86/kernel/pci-swiotlb_64.c @@ -3,6 +3,8 @@ #include <linux/pci.h> #include <linux/cache.h> #include <linux/module.h> +#include <linux/swiotlb.h> +#include <linux/bootmem.h> #include <linux/dma-mapping.h> #include <asm/iommu.h> @@ -11,6 +13,31 @@ int swiotlb __read_mostly; +void *swiotlb_alloc_boot(size_t size, unsigned long nslabs) +{ + return alloc_bootmem_low_pages(size); +} + +void *swiotlb_alloc(unsigned order, unsigned long nslabs) +{ + return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order); +} + +dma_addr_t swiotlb_phys_to_bus(phys_addr_t paddr) +{ + return paddr; +} + +phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr) +{ + return baddr; +} + +int __weak swiotlb_arch_range_needs_mapping(void *ptr, size_t size) +{ + return 0; +} + static dma_addr_t swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size, int direction) @@ -50,8 +77,10 @@ struct dma_mapping_ops swiotlb_dma_ops = { void __init pci_swiotlb_init(void) { /* don't initialize swiotlb if iommu=off (no_iommu=1) */ +#ifdef CONFIG_X86_64 if (!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) swiotlb = 1; +#endif if (swiotlb_force) swiotlb = 1; if (swiotlb) { diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 67465ed89310..309949e9e1c1 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -168,6 +168,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, ich_force_enable_hpet); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, ich_force_enable_hpet); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 08e02e8453c9..ae0d8042cf69 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -953,7 +953,7 @@ void __init setup_arch(char **cmdline_p) ioapic_init_mappings(); /* need to wait for io_apic is mapped */ - nr_irqs = probe_nr_irqs(); + probe_nr_irqs_gsi(); kvm_guest_init(); diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 5c7cef34c9e7..10b9bd35a8ff 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -30,21 +30,6 @@ ENTRY(lguest_entry) movl $lguest_data - __PAGE_OFFSET, %edx int $LGUEST_TRAP_ENTRY - /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl - * instruction uses %esi implicitly as the source for the copy we're - * about to do. */ - movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi - - /* Copy first 32 entries of page directory to __PAGE_OFFSET entries. - * This means the first 128M of kernel memory will be mapped at - * PAGE_OFFSET where the kernel expects to run. This will get it far - * enough through boot to switch to its own pagetables. */ - movl $32, %ecx - movl %esi, %edi - addl $((__PAGE_OFFSET >> 22) * 4), %edi - rep - movsl - /* Set up the initial stack so we can run C code. */ movl $(init_thread_union+THREAD_SIZE),%esp diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 9e68075544f6..4a20b2f9a381 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -39,7 +39,7 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon #define __do_strncpy_from_user(dst, src, count, res) \ do { \ int __d0, __d1, __d2; \ - might_sleep(); \ + might_fault(); \ __asm__ __volatile__( \ " testl %1,%1\n" \ " jz 2f\n" \ @@ -126,7 +126,7 @@ EXPORT_SYMBOL(strncpy_from_user); #define __do_clear_user(addr,size) \ do { \ int __d0; \ - might_sleep(); \ + might_fault(); \ __asm__ __volatile__( \ "0: rep; stosl\n" \ " movl %2,%0\n" \ @@ -155,7 +155,7 @@ do { \ unsigned long clear_user(void __user *to, unsigned long n) { - might_sleep(); + might_fault(); if (access_ok(VERIFY_WRITE, to, n)) __do_clear_user(to, n); return n; @@ -197,7 +197,7 @@ long strnlen_user(const char __user *s, long n) unsigned long mask = -__addr_ok(s); unsigned long res, tmp; - might_sleep(); + might_fault(); __asm__ __volatile__( " testl %0, %0\n" diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index f4df6e7c718b..64d6c84e6353 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -15,7 +15,7 @@ #define __do_strncpy_from_user(dst,src,count,res) \ do { \ long __d0, __d1, __d2; \ - might_sleep(); \ + might_fault(); \ __asm__ __volatile__( \ " testq %1,%1\n" \ " jz 2f\n" \ @@ -64,7 +64,7 @@ EXPORT_SYMBOL(strncpy_from_user); unsigned long __clear_user(void __user *addr, unsigned long size) { long __d0; - might_sleep(); + might_fault(); /* no memory constraint because it doesn't change any memory gcc knows about */ asm volatile( diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 800e1d94c1b5..8655b5bb0963 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/highmem.h> #include <linux/pagemap.h> +#include <linux/pci.h> #include <linux/pfn.h> #include <linux/poison.h> #include <linux/bootmem.h> @@ -967,6 +968,8 @@ void __init mem_init(void) int codesize, reservedpages, datasize, initsize; int tmp; + pci_iommu_alloc(); + #ifdef CONFIG_FLATMEM BUG_ON(!mem_map); #endif diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 509513760a6e..98658f25f542 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -65,11 +65,13 @@ static unsigned long reset_value[NUM_COUNTERS]; #define IBS_FETCH_BEGIN 3 #define IBS_OP_BEGIN 4 -/* The function interface needs to be fixed, something like add - data. Should then be added to linux/oprofile.h. */ +/* + * The function interface needs to be fixed, something like add + * data. Should then be added to linux/oprofile.h. + */ extern void -oprofile_add_ibs_sample(struct pt_regs *const regs, - unsigned int *const ibs_sample, int ibs_code); +oprofile_add_ibs_sample(struct pt_regs * const regs, + unsigned int * const ibs_sample, int ibs_code); struct ibs_fetch_sample { /* MSRC001_1031 IBS Fetch Linear Address Register */ @@ -104,11 +106,6 @@ struct ibs_op_sample { unsigned int ibs_dc_phys_high; }; -/* - * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ -*/ -static void clear_ibs_nmi(void); - static int ibs_allowed; /* AMD Family10h and later */ struct op_ibs_config { @@ -223,7 +220,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, (unsigned int *)&ibs_fetch, IBS_FETCH_BEGIN); - /*reenable the IRQ */ + /* reenable the IRQ */ rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); high &= ~IBS_FETCH_HIGH_VALID_BIT; high |= IBS_FETCH_HIGH_ENABLE; @@ -331,8 +328,10 @@ static void op_amd_stop(struct op_msrs const * const msrs) unsigned int low, high; int i; - /* Subtle: stop on all counters to avoid race with - * setting our pm callback */ + /* + * Subtle: stop on all counters to avoid race with setting our + * pm callback + */ for (i = 0 ; i < NUM_COUNTERS ; ++i) { if (!reset_value[i]) continue; @@ -343,13 +342,15 @@ static void op_amd_stop(struct op_msrs const * const msrs) #ifdef CONFIG_OPROFILE_IBS if (ibs_allowed && ibs_config.fetch_enabled) { - low = 0; /* clear max count and enable */ + /* clear max count and enable */ + low = 0; high = 0; wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); } if (ibs_allowed && ibs_config.op_enabled) { - low = 0; /* clear max count and enable */ + /* clear max count and enable */ + low = 0; high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } @@ -370,18 +371,7 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } -#ifndef CONFIG_OPROFILE_IBS - -/* no IBS support */ - -static int op_amd_init(struct oprofile_operations *ops) -{ - return 0; -} - -static void op_amd_exit(void) {} - -#else +#ifdef CONFIG_OPROFILE_IBS static u8 ibs_eilvt_off; @@ -395,7 +385,7 @@ static inline void apic_clear_ibs_nmi_per_cpu(void *arg) setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); } -static int pfm_amd64_setup_eilvt(void) +static int init_ibs_nmi(void) { #define IBSCTL_LVTOFFSETVAL (1 << 8) #define IBSCTL 0x1cc @@ -443,18 +433,22 @@ static int pfm_amd64_setup_eilvt(void) return 0; } -/* - * initialize the APIC for the IBS interrupts - * if available (AMD Family10h rev B0 and later) - */ -static void setup_ibs(void) +/* uninitialize the APIC for the IBS interrupts if needed */ +static void clear_ibs_nmi(void) +{ + if (ibs_allowed) + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); +} + +/* initialize the APIC for the IBS interrupts if available */ +static void ibs_init(void) { ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); if (!ibs_allowed) return; - if (pfm_amd64_setup_eilvt()) { + if (init_ibs_nmi()) { ibs_allowed = 0; return; } @@ -462,14 +456,12 @@ static void setup_ibs(void) printk(KERN_INFO "oprofile: AMD IBS detected\n"); } - -/* - * unitialize the APIC for the IBS interrupts if needed on AMD Family10h - * rev B0 and later */ -static void clear_ibs_nmi(void) +static void ibs_exit(void) { - if (ibs_allowed) - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); + if (!ibs_allowed) + return; + + clear_ibs_nmi(); } static int (*create_arch_files)(struct super_block *sb, struct dentry *root); @@ -519,7 +511,7 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root) static int op_amd_init(struct oprofile_operations *ops) { - setup_ibs(); + ibs_init(); create_arch_files = ops->create_files; ops->create_files = setup_ibs_files; return 0; @@ -527,10 +519,21 @@ static int op_amd_init(struct oprofile_operations *ops) static void op_amd_exit(void) { - clear_ibs_nmi(); + ibs_exit(); } -#endif +#else + +/* no IBS support */ + +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) {} + +#endif /* CONFIG_OPROFILE_IBS */ struct op_x86_model_spec const op_amd_spec = { .init = op_amd_init, diff --git a/block/Kconfig b/block/Kconfig index 290b219fad9c..ac0956f77785 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -24,21 +24,17 @@ menuconfig BLOCK if BLOCK config LBD - bool "Support for Large Block Devices" + bool "Support for large block devices and files" depends on !64BIT help - Enable block devices of size 2TB and larger. + Enable block devices or files of size 2TB and larger. This option is required to support the full capacity of large (2TB+) block devices, including RAID, disk, Network Block Device, Logical Volume Manager (LVM) and loopback. - - For example, RAID devices are frequently bigger than the capacity - of the largest individual hard drive. - - This option is not required if you have individual disk drives - which total 2TB+ and you are not aggregating the capacity into - a large block device (e.g. using RAID or LVM). + + This option also enables support for single files larger than + 2TB. If unsure, say N. @@ -58,15 +54,6 @@ config BLK_DEV_IO_TRACE If unsure, say N. -config LSF - bool "Support for Large Single Files" - depends on !64BIT - help - Say Y here if you want to be able to handle very large files (2TB - and larger), otherwise say N. - - If unsure, say Y. - config BLK_DEV_BSG bool "Block layer SG support v4 (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/block/as-iosched.c b/block/as-iosched.c index 71f0abb219ee..631f6f44460a 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1339,12 +1339,12 @@ static int as_may_queue(struct request_queue *q, int rw) return ret; } -static void as_exit_queue(elevator_t *e) +static void as_exit_queue(struct elevator_queue *e) { struct as_data *ad = e->elevator_data; del_timer_sync(&ad->antic_timer); - kblockd_flush_work(&ad->antic_work); + cancel_work_sync(&ad->antic_work); BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); @@ -1409,7 +1409,7 @@ as_var_store(unsigned long *var, const char *page, size_t count) return count; } -static ssize_t est_time_show(elevator_t *e, char *page) +static ssize_t est_time_show(struct elevator_queue *e, char *page) { struct as_data *ad = e->elevator_data; int pos = 0; @@ -1427,7 +1427,7 @@ static ssize_t est_time_show(elevator_t *e, char *page) } #define SHOW_FUNCTION(__FUNC, __VAR) \ -static ssize_t __FUNC(elevator_t *e, char *page) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ { \ struct as_data *ad = e->elevator_data; \ return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ @@ -1440,7 +1440,7 @@ SHOW_FUNCTION(as_write_batch_expire_show, ad->batch_expire[REQ_ASYNC]); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ -static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ { \ struct as_data *ad = e->elevator_data; \ int ret = as_var_store(__PTR, (page), count); \ diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 6e72d661ae42..8eba4e43bb0c 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -24,8 +24,8 @@ int blk_queue_ordered(struct request_queue *q, unsigned ordered, prepare_flush_fn *prepare_flush_fn) { - if (ordered & (QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH) && - prepare_flush_fn == NULL) { + if (!prepare_flush_fn && (ordered & (QUEUE_ORDERED_DO_PREFLUSH | + QUEUE_ORDERED_DO_POSTFLUSH))) { printk(KERN_ERR "%s: prepare_flush_fn required\n", __func__); return -EINVAL; } @@ -88,7 +88,7 @@ unsigned blk_ordered_req_seq(struct request *rq) return QUEUE_ORDSEQ_DONE; } -void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) +bool blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) { struct request *rq; @@ -99,7 +99,7 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) q->ordseq |= seq; if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE) - return; + return false; /* * Okay, sequence complete. @@ -109,6 +109,8 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error) if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq))) BUG(); + + return true; } static void pre_flush_end_io(struct request *rq, int error) @@ -134,7 +136,7 @@ static void queue_flush(struct request_queue *q, unsigned which) struct request *rq; rq_end_io_fn *end_io; - if (which == QUEUE_ORDERED_PREFLUSH) { + if (which == QUEUE_ORDERED_DO_PREFLUSH) { rq = &q->pre_flush_rq; end_io = pre_flush_end_io; } else { @@ -151,80 +153,110 @@ static void queue_flush(struct request_queue *q, unsigned which) elv_insert(q, rq, ELEVATOR_INSERT_FRONT); } -static inline struct request *start_ordered(struct request_queue *q, - struct request *rq) +static inline bool start_ordered(struct request_queue *q, struct request **rqp) { + struct request *rq = *rqp; + unsigned skip = 0; + q->orderr = 0; q->ordered = q->next_ordered; q->ordseq |= QUEUE_ORDSEQ_STARTED; /* - * Prep proxy barrier request. + * For an empty barrier, there's no actual BAR request, which + * in turn makes POSTFLUSH unnecessary. Mask them off. */ + if (!rq->hard_nr_sectors) { + q->ordered &= ~(QUEUE_ORDERED_DO_BAR | + QUEUE_ORDERED_DO_POSTFLUSH); + /* + * Empty barrier on a write-through device w/ ordered + * tag has no command to issue and without any command + * to issue, ordering by tag can't be used. Drain + * instead. + */ + if ((q->ordered & QUEUE_ORDERED_BY_TAG) && + !(q->ordered & QUEUE_ORDERED_DO_PREFLUSH)) { + q->ordered &= ~QUEUE_ORDERED_BY_TAG; + q->ordered |= QUEUE_ORDERED_BY_DRAIN; + } + } + + /* stash away the original request */ elv_dequeue_request(q, rq); q->orig_bar_rq = rq; - rq = &q->bar_rq; - blk_rq_init(q, rq); - if (bio_data_dir(q->orig_bar_rq->bio) == WRITE) - rq->cmd_flags |= REQ_RW; - if (q->ordered & QUEUE_ORDERED_FUA) - rq->cmd_flags |= REQ_FUA; - init_request_from_bio(rq, q->orig_bar_rq->bio); - rq->end_io = bar_end_io; + rq = NULL; /* * Queue ordered sequence. As we stack them at the head, we * need to queue in reverse order. Note that we rely on that * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs - * request gets inbetween ordered sequence. If this request is - * an empty barrier, we don't need to do a postflush ever since - * there will be no data written between the pre and post flush. - * Hence a single flush will suffice. + * request gets inbetween ordered sequence. */ - if ((q->ordered & QUEUE_ORDERED_POSTFLUSH) && !blk_empty_barrier(rq)) - queue_flush(q, QUEUE_ORDERED_POSTFLUSH); - else - q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH; + if (q->ordered & QUEUE_ORDERED_DO_POSTFLUSH) { + queue_flush(q, QUEUE_ORDERED_DO_POSTFLUSH); + rq = &q->post_flush_rq; + } else + skip |= QUEUE_ORDSEQ_POSTFLUSH; - elv_insert(q, rq, ELEVATOR_INSERT_FRONT); + if (q->ordered & QUEUE_ORDERED_DO_BAR) { + rq = &q->bar_rq; + + /* initialize proxy request and queue it */ + blk_rq_init(q, rq); + if (bio_data_dir(q->orig_bar_rq->bio) == WRITE) + rq->cmd_flags |= REQ_RW; + if (q->ordered & QUEUE_ORDERED_DO_FUA) + rq->cmd_flags |= REQ_FUA; + init_request_from_bio(rq, q->orig_bar_rq->bio); + rq->end_io = bar_end_io; - if (q->ordered & QUEUE_ORDERED_PREFLUSH) { - queue_flush(q, QUEUE_ORDERED_PREFLUSH); + elv_insert(q, rq, ELEVATOR_INSERT_FRONT); + } else + skip |= QUEUE_ORDSEQ_BAR; + + if (q->ordered & QUEUE_ORDERED_DO_PREFLUSH) { + queue_flush(q, QUEUE_ORDERED_DO_PREFLUSH); rq = &q->pre_flush_rq; } else - q->ordseq |= QUEUE_ORDSEQ_PREFLUSH; + skip |= QUEUE_ORDSEQ_PREFLUSH; - if ((q->ordered & QUEUE_ORDERED_TAG) || q->in_flight == 0) - q->ordseq |= QUEUE_ORDSEQ_DRAIN; - else + if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && q->in_flight) rq = NULL; + else + skip |= QUEUE_ORDSEQ_DRAIN; + + *rqp = rq; - return rq; + /* + * Complete skipped sequences. If whole sequence is complete, + * return false to tell elevator that this request is gone. + */ + return !blk_ordered_complete_seq(q, skip, 0); } -int blk_do_ordered(struct request_queue *q, struct request **rqp) +bool blk_do_ordered(struct request_queue *q, struct request **rqp) { struct request *rq = *rqp; const int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); if (!q->ordseq) { if (!is_barrier) - return 1; + return true; - if (q->next_ordered != QUEUE_ORDERED_NONE) { - *rqp = start_ordered(q, rq); - return 1; - } else { + if (q->next_ordered != QUEUE_ORDERED_NONE) + return start_ordered(q, rqp); + else { /* - * This can happen when the queue switches to - * ORDERED_NONE while this request is on it. + * Queue ordering not supported. Terminate + * with prejudice. */ elv_dequeue_request(q, rq); if (__blk_end_request(rq, -EOPNOTSUPP, blk_rq_bytes(rq))) BUG(); *rqp = NULL; - return 0; + return false; } } @@ -235,9 +267,9 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) /* Special requests are not subject to ordering rules. */ if (!blk_fs_request(rq) && rq != &q->pre_flush_rq && rq != &q->post_flush_rq) - return 1; + return true; - if (q->ordered & QUEUE_ORDERED_TAG) { + if (q->ordered & QUEUE_ORDERED_BY_TAG) { /* Ordered by tag. Blocking the next barrier is enough. */ if (is_barrier && rq != &q->bar_rq) *rqp = NULL; @@ -248,7 +280,7 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) *rqp = NULL; } - return 1; + return true; } static void bio_end_empty_barrier(struct bio *bio, int err) diff --git a/block/blk-core.c b/block/blk-core.c index 561e8a1b43a4..a824e49c0d0a 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -153,6 +153,9 @@ static void req_bio_endio(struct request *rq, struct bio *bio, nbytes = bio->bi_size; } + if (unlikely(rq->cmd_flags & REQ_QUIET)) + set_bit(BIO_QUIET, &bio->bi_flags); + bio->bi_size -= nbytes; bio->bi_sector += (nbytes >> 9); @@ -265,8 +268,7 @@ void __generic_unplug_device(struct request_queue *q) { if (unlikely(blk_queue_stopped(q))) return; - - if (!blk_remove_plug(q)) + if (!blk_remove_plug(q) && !blk_queue_nonrot(q)) return; q->request_fn(q); @@ -404,7 +406,8 @@ EXPORT_SYMBOL(blk_stop_queue); void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->unplug_timer); - kblockd_flush_work(&q->unplug_work); + del_timer_sync(&q->timeout); + cancel_work_sync(&q->unplug_work); } EXPORT_SYMBOL(blk_sync_queue); @@ -1135,7 +1138,7 @@ void init_request_from_bio(struct request *req, struct bio *bio) static int __make_request(struct request_queue *q, struct bio *bio) { struct request *req; - int el_ret, nr_sectors, barrier, discard, err; + int el_ret, nr_sectors; const unsigned short prio = bio_prio(bio); const int sync = bio_sync(bio); int rw_flags; @@ -1149,22 +1152,9 @@ static int __make_request(struct request_queue *q, struct bio *bio) */ blk_queue_bounce(q, &bio); - barrier = bio_barrier(bio); - if (unlikely(barrier) && bio_has_data(bio) && - (q->next_ordered == QUEUE_ORDERED_NONE)) { - err = -EOPNOTSUPP; - goto end_io; - } - - discard = bio_discard(bio); - if (unlikely(discard) && !q->prepare_discard_fn) { - err = -EOPNOTSUPP; - goto end_io; - } - spin_lock_irq(q->queue_lock); - if (unlikely(barrier) || elv_queue_empty(q)) + if (unlikely(bio_barrier(bio)) || elv_queue_empty(q)) goto get_rq; el_ret = elv_merge(q, &req, bio); @@ -1250,18 +1240,14 @@ get_rq: if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) || bio_flagged(bio, BIO_CPU_AFFINE)) req->cpu = blk_cpu_to_group(smp_processor_id()); - if (elv_queue_empty(q)) + if (!blk_queue_nonrot(q) && elv_queue_empty(q)) blk_plug_device(q); add_request(q, req); out: - if (sync) + if (sync || blk_queue_nonrot(q)) __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); return 0; - -end_io: - bio_endio(bio, err); - return 0; } /* @@ -1414,15 +1400,13 @@ static inline void __generic_make_request(struct bio *bio) char b[BDEVNAME_SIZE]; q = bdev_get_queue(bio->bi_bdev); - if (!q) { + if (unlikely(!q)) { printk(KERN_ERR "generic_make_request: Trying to access " "nonexistent block-device %s (%Lu)\n", bdevname(bio->bi_bdev, b), (long long) bio->bi_sector); -end_io: - bio_endio(bio, err); - break; + goto end_io; } if (unlikely(nr_sectors > q->max_hw_sectors)) { @@ -1459,14 +1443,19 @@ end_io: if (bio_check_eod(bio, nr_sectors)) goto end_io; - if ((bio_empty_barrier(bio) && !q->prepare_flush_fn) || - (bio_discard(bio) && !q->prepare_discard_fn)) { + + if (bio_discard(bio) && !q->prepare_discard_fn) { err = -EOPNOTSUPP; goto end_io; } ret = q->make_request_fn(q, bio); } while (ret); + + return; + +end_io: + bio_endio(bio, err); } /* @@ -1716,14 +1705,6 @@ static int __end_that_request_first(struct request *req, int error, while ((bio = req->bio) != NULL) { int nbytes; - /* - * For an empty barrier request, the low level driver must - * store a potential error location in ->sector. We pass - * that back up in ->bi_sector. - */ - if (blk_empty_barrier(req)) - bio->bi_sector = req->sector; - if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; @@ -2143,12 +2124,6 @@ int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) } EXPORT_SYMBOL(kblockd_schedule_work); -void kblockd_flush_work(struct work_struct *work) -{ - cancel_work_sync(work); -} -EXPORT_SYMBOL(kblockd_flush_work); - int __init blk_dev_init(void) { kblockd_workqueue = create_workqueue("kblockd"); diff --git a/block/blk-settings.c b/block/blk-settings.c index afa55e14e278..59fd05d9f1d5 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -319,9 +319,9 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b) t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask); - t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments); - t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments); - t->max_segment_size = min(t->max_segment_size, b->max_segment_size); + t->max_phys_segments = min_not_zero(t->max_phys_segments, b->max_phys_segments); + t->max_hw_segments = min_not_zero(t->max_hw_segments, b->max_hw_segments); + t->max_segment_size = min_not_zero(t->max_segment_size, b->max_segment_size); t->hardsect_size = max(t->hardsect_size, b->hardsect_size); if (!t->queue_lock) WARN_ON_ONCE(1); diff --git a/block/blk-softirq.c b/block/blk-softirq.c index e660d26ca656..ce0efc6b26dc 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -161,7 +161,7 @@ void blk_complete_request(struct request *req) } EXPORT_SYMBOL(blk_complete_request); -__init int blk_softirq_init(void) +static __init int blk_softirq_init(void) { int i; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 21e275d7eed9..a29cb788e408 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -88,9 +88,7 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count) unsigned long ra_kb; ssize_t ret = queue_var_store(&ra_kb, page, count); - spin_lock_irq(q->queue_lock); q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); - spin_unlock_irq(q->queue_lock); return ret; } @@ -117,10 +115,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb) return -EINVAL; - /* - * Take the queue lock to update the readahead and max_sectors - * values synchronously: - */ + spin_lock_irq(q->queue_lock); q->max_sectors = max_sectors_kb << 1; spin_unlock_irq(q->queue_lock); diff --git a/block/blk-tag.c b/block/blk-tag.c index c0d419e84ce7..3c518e3303ae 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -158,7 +158,6 @@ fail: /** * blk_init_tags - initialize the tag info for an external tag map * @depth: the maximum queue depth supported - * @tags: the tag to use **/ struct blk_queue_tag *blk_init_tags(int depth) { diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 69185ea9fae2..a09535377a94 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -73,11 +73,7 @@ ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr, */ void blk_delete_timer(struct request *req) { - struct request_queue *q = req->q; - list_del_init(&req->timeout_list); - if (list_empty(&q->timeout_list)) - del_timer(&q->timeout); } static void blk_rq_timed_out(struct request *req) @@ -111,7 +107,7 @@ static void blk_rq_timed_out(struct request *req) void blk_rq_timed_out_timer(unsigned long data) { struct request_queue *q = (struct request_queue *) data; - unsigned long flags, uninitialized_var(next), next_set = 0; + unsigned long flags, next = 0; struct request *rq, *tmp; spin_lock_irqsave(q->queue_lock, flags); @@ -126,15 +122,18 @@ void blk_rq_timed_out_timer(unsigned long data) if (blk_mark_rq_complete(rq)) continue; blk_rq_timed_out(rq); + } else { + if (!next || time_after(next, rq->deadline)) + next = rq->deadline; } - if (!next_set) { - next = rq->deadline; - next_set = 1; - } else if (time_after(next, rq->deadline)) - next = rq->deadline; } - if (next_set && !list_empty(&q->timeout_list)) + /* + * next can never be 0 here with the list non-empty, since we always + * bump ->deadline to 1 so we can detect if the timer was ever added + * or not. See comment in blk_add_timer() + */ + if (next) mod_timer(&q->timeout, round_jiffies_up(next)); spin_unlock_irqrestore(q->queue_lock, flags); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 6a062eebbd15..e8525fa72823 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1136,12 +1136,8 @@ static int cfq_dispatch_requests(struct request_queue *q, int force) if (cfq_class_idle(cfqq)) max_dispatch = 1; - if (cfqq->dispatched >= max_dispatch) { - if (cfqd->busy_queues > 1) - break; - if (cfqq->dispatched >= 4 * max_dispatch) - break; - } + if (cfqq->dispatched >= max_dispatch && cfqd->busy_queues > 1) + break; if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq)) break; @@ -1318,7 +1314,15 @@ static void cfq_exit_single_io_context(struct io_context *ioc, unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - __cfq_exit_single_io_context(cfqd, cic); + + /* + * Ensure we get a fresh copy of the ->key to prevent + * race between exiting task and queue + */ + smp_read_barrier_depends(); + if (cic->key) + __cfq_exit_single_io_context(cfqd, cic); + spin_unlock_irqrestore(q->queue_lock, flags); } } @@ -2160,7 +2164,7 @@ out_cont: static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) { del_timer_sync(&cfqd->idle_slice_timer); - kblockd_flush_work(&cfqd->unplug_work); + cancel_work_sync(&cfqd->unplug_work); } static void cfq_put_async_queues(struct cfq_data *cfqd) @@ -2178,7 +2182,7 @@ static void cfq_put_async_queues(struct cfq_data *cfqd) cfq_put_queue(cfqd->async_idle_cfqq); } -static void cfq_exit_queue(elevator_t *e) +static void cfq_exit_queue(struct elevator_queue *e) { struct cfq_data *cfqd = e->elevator_data; struct request_queue *q = cfqd->queue; @@ -2288,7 +2292,7 @@ cfq_var_store(unsigned int *var, const char *page, size_t count) } #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -static ssize_t __FUNC(elevator_t *e, char *page) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ { \ struct cfq_data *cfqd = e->elevator_data; \ unsigned int __data = __VAR; \ @@ -2308,7 +2312,7 @@ SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ { \ struct cfq_data *cfqd = e->elevator_data; \ unsigned int __data; \ diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 67eb93cff699..f87615dea46b 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -774,9 +774,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) bdi = blk_get_backing_dev_info(bdev); if (bdi == NULL) return -ENOTTY; - lock_kernel(); bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; - unlock_kernel(); return 0; case BLKGETSIZE: size = bdev->bd_inode->i_size; diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index fd311179f44c..c4d991d4adef 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -334,7 +334,7 @@ static int deadline_queue_empty(struct request_queue *q) && list_empty(&dd->fifo_list[READ]); } -static void deadline_exit_queue(elevator_t *e) +static void deadline_exit_queue(struct elevator_queue *e) { struct deadline_data *dd = e->elevator_data; @@ -387,7 +387,7 @@ deadline_var_store(int *var, const char *page, size_t count) } #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -static ssize_t __FUNC(elevator_t *e, char *page) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ { \ struct deadline_data *dd = e->elevator_data; \ int __data = __VAR; \ @@ -403,7 +403,7 @@ SHOW_FUNCTION(deadline_fifo_batch_show, dd->fifo_batch, 0); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ { \ struct deadline_data *dd = e->elevator_data; \ int __data; \ diff --git a/block/elevator.c b/block/elevator.c index 86836dd179c0..98259eda0ef6 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -65,7 +65,7 @@ DEFINE_TRACE(block_rq_issue); static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) { struct request_queue *q = rq->q; - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_allow_merge_fn) return e->ops->elevator_allow_merge_fn(q, rq, bio); @@ -208,13 +208,13 @@ __setup("elevator=", elevator_setup); static struct kobj_type elv_ktype; -static elevator_t *elevator_alloc(struct request_queue *q, +static struct elevator_queue *elevator_alloc(struct request_queue *q, struct elevator_type *e) { - elevator_t *eq; + struct elevator_queue *eq; int i; - eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL | __GFP_ZERO, q->node); + eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); if (unlikely(!eq)) goto err; @@ -240,8 +240,9 @@ err: static void elevator_release(struct kobject *kobj) { - elevator_t *e = container_of(kobj, elevator_t, kobj); + struct elevator_queue *e; + e = container_of(kobj, struct elevator_queue, kobj); elevator_put(e->elevator_type); kfree(e->hash); kfree(e); @@ -297,7 +298,7 @@ int elevator_init(struct request_queue *q, char *name) } EXPORT_SYMBOL(elevator_init); -void elevator_exit(elevator_t *e) +void elevator_exit(struct elevator_queue *e) { mutex_lock(&e->sysfs_lock); if (e->ops->elevator_exit_fn) @@ -311,7 +312,7 @@ EXPORT_SYMBOL(elevator_exit); static void elv_activate_rq(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_activate_req_fn) e->ops->elevator_activate_req_fn(q, rq); @@ -319,7 +320,7 @@ static void elv_activate_rq(struct request_queue *q, struct request *rq) static void elv_deactivate_rq(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_deactivate_req_fn) e->ops->elevator_deactivate_req_fn(q, rq); @@ -338,7 +339,7 @@ static void elv_rqhash_del(struct request_queue *q, struct request *rq) static void elv_rqhash_add(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; BUG_ON(ELV_ON_HASH(rq)); hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); @@ -352,7 +353,7 @@ static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; struct hlist_node *entry, *next; struct request *rq; @@ -494,7 +495,7 @@ EXPORT_SYMBOL(elv_dispatch_add_tail); int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; struct request *__rq; int ret; @@ -529,7 +530,7 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) void elv_merged_request(struct request_queue *q, struct request *rq, int type) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_merged_fn) e->ops->elevator_merged_fn(q, rq, type); @@ -543,7 +544,7 @@ void elv_merged_request(struct request_queue *q, struct request *rq, int type) void elv_merge_requests(struct request_queue *q, struct request *rq, struct request *next) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_merge_req_fn) e->ops->elevator_merge_req_fn(q, rq, next); @@ -755,14 +756,6 @@ struct request *elv_next_request(struct request_queue *q) int ret; while ((rq = __elv_next_request(q)) != NULL) { - /* - * Kill the empty barrier place holder, the driver must - * not ever see it. - */ - if (blk_empty_barrier(rq)) { - __blk_end_request(rq, 0, blk_rq_bytes(rq)); - continue; - } if (!(rq->cmd_flags & REQ_STARTED)) { /* * This is the first time the device driver @@ -854,7 +847,7 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq) int elv_queue_empty(struct request_queue *q) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (!list_empty(&q->queue_head)) return 0; @@ -868,7 +861,7 @@ EXPORT_SYMBOL(elv_queue_empty); struct request *elv_latter_request(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_latter_req_fn) return e->ops->elevator_latter_req_fn(q, rq); @@ -877,7 +870,7 @@ struct request *elv_latter_request(struct request_queue *q, struct request *rq) struct request *elv_former_request(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_former_req_fn) return e->ops->elevator_former_req_fn(q, rq); @@ -886,7 +879,7 @@ struct request *elv_former_request(struct request_queue *q, struct request *rq) int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_set_req_fn) return e->ops->elevator_set_req_fn(q, rq, gfp_mask); @@ -897,7 +890,7 @@ int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) void elv_put_request(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_put_req_fn) e->ops->elevator_put_req_fn(rq); @@ -905,7 +898,7 @@ void elv_put_request(struct request_queue *q, struct request *rq) int elv_may_queue(struct request_queue *q, int rw) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; if (e->ops->elevator_may_queue_fn) return e->ops->elevator_may_queue_fn(q, rw); @@ -928,7 +921,7 @@ EXPORT_SYMBOL(elv_abort_queue); void elv_completed_request(struct request_queue *q, struct request *rq) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; /* * request is released from the driver, io must be done @@ -944,10 +937,14 @@ void elv_completed_request(struct request_queue *q, struct request *rq) * drained for flush sequence. */ if (unlikely(q->ordseq)) { - struct request *first_rq = list_entry_rq(q->queue_head.next); - if (q->in_flight == 0 && + struct request *next = NULL; + + if (!list_empty(&q->queue_head)) + next = list_entry_rq(q->queue_head.next); + + if (!q->in_flight && blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && - blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { + (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) { blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); blk_start_queueing(q); } @@ -959,13 +956,14 @@ void elv_completed_request(struct request_queue *q, struct request *rq) static ssize_t elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { - elevator_t *e = container_of(kobj, elevator_t, kobj); struct elv_fs_entry *entry = to_elv(attr); + struct elevator_queue *e; ssize_t error; if (!entry->show) return -EIO; + e = container_of(kobj, struct elevator_queue, kobj); mutex_lock(&e->sysfs_lock); error = e->ops ? entry->show(e, page) : -ENOENT; mutex_unlock(&e->sysfs_lock); @@ -976,13 +974,14 @@ static ssize_t elv_attr_store(struct kobject *kobj, struct attribute *attr, const char *page, size_t length) { - elevator_t *e = container_of(kobj, elevator_t, kobj); struct elv_fs_entry *entry = to_elv(attr); + struct elevator_queue *e; ssize_t error; if (!entry->store) return -EIO; + e = container_of(kobj, struct elevator_queue, kobj); mutex_lock(&e->sysfs_lock); error = e->ops ? entry->store(e, page, length) : -ENOENT; mutex_unlock(&e->sysfs_lock); @@ -1001,7 +1000,7 @@ static struct kobj_type elv_ktype = { int elv_register_queue(struct request_queue *q) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; int error; error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); @@ -1019,7 +1018,7 @@ int elv_register_queue(struct request_queue *q) return error; } -static void __elv_unregister_queue(elevator_t *e) +static void __elv_unregister_queue(struct elevator_queue *e) { kobject_uevent(&e->kobj, KOBJ_REMOVE); kobject_del(&e->kobj); @@ -1082,7 +1081,7 @@ EXPORT_SYMBOL_GPL(elv_unregister); */ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) { - elevator_t *old_elevator, *e; + struct elevator_queue *old_elevator, *e; void *data; /* @@ -1188,7 +1187,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, ssize_t elv_iosched_show(struct request_queue *q, char *name) { - elevator_t *e = q->elevator; + struct elevator_queue *e = q->elevator; struct elevator_type *elv = e->elevator_type; struct elevator_type *__e; int len = 0; diff --git a/block/genhd.c b/block/genhd.c index 2f7feda61e35..d84a7df1e2a0 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -181,6 +181,12 @@ void disk_part_iter_exit(struct disk_part_iter *piter) } EXPORT_SYMBOL_GPL(disk_part_iter_exit); +static inline int sector_in_part(struct hd_struct *part, sector_t sector) +{ + return part->start_sect <= sector && + sector < part->start_sect + part->nr_sects; +} + /** * disk_map_sector_rcu - map sector to partition * @disk: gendisk of interest @@ -199,16 +205,22 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit); struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) { struct disk_part_tbl *ptbl; + struct hd_struct *part; int i; ptbl = rcu_dereference(disk->part_tbl); + part = rcu_dereference(ptbl->last_lookup); + if (part && sector_in_part(part, sector)) + return part; + for (i = 1; i < ptbl->len; i++) { - struct hd_struct *part = rcu_dereference(ptbl->part[i]); + part = rcu_dereference(ptbl->part[i]); - if (part && part->start_sect <= sector && - sector < part->start_sect + part->nr_sects) + if (part && sector_in_part(part, sector)) { + rcu_assign_pointer(ptbl->last_lookup, part); return part; + } } return &disk->part0; } @@ -888,8 +900,11 @@ static void disk_replace_part_tbl(struct gendisk *disk, struct disk_part_tbl *old_ptbl = disk->part_tbl; rcu_assign_pointer(disk->part_tbl, new_ptbl); - if (old_ptbl) + + if (old_ptbl) { + rcu_assign_pointer(old_ptbl->last_lookup, NULL); call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); + } } /** diff --git a/block/ioctl.c b/block/ioctl.c index d03985b04d67..0f22e629b13c 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -323,9 +323,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, bdi = blk_get_backing_dev_info(bdev); if (bdi == NULL) return -ENOTTY; - lock_kernel(); bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; - unlock_kernel(); return 0; case BLKBSZSET: /* set the logical block size */ diff --git a/block/noop-iosched.c b/block/noop-iosched.c index c23e02969650..3a0d369d08c7 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c @@ -76,7 +76,7 @@ static void *noop_init_queue(struct request_queue *q) return nd; } -static void noop_exit_queue(elevator_t *e) +static void noop_exit_queue(struct elevator_queue *e) { struct noop_data *nd = e->elevator_data; diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index d0bb92cbefb9..ee9c67d7e1be 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -60,7 +60,7 @@ static int scsi_get_bus(struct request_queue *q, int __user *p) static int sg_get_timeout(struct request_queue *q) { - return q->sg_timeout / (HZ / USER_HZ); + return jiffies_to_clock_t(q->sg_timeout); } static int sg_set_timeout(struct request_queue *q, int __user *p) @@ -68,7 +68,7 @@ static int sg_set_timeout(struct request_queue *q, int __user *p) int timeout, err = get_user(timeout, p); if (!err) - q->sg_timeout = timeout * (HZ / USER_HZ); + q->sg_timeout = clock_t_to_jiffies(timeout); return err; } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a67b8e7c712d..656448c7fef9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1119,14 +1119,14 @@ static void ahci_start_port(struct ata_port *ap) /* turn on LEDs */ if (ap->flags & ATA_FLAG_EM) { - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { emp = &pp->em_priv[link->pmp]; ahci_transmit_led_message(ap, emp->led_state, 4); } } if (ap->flags & ATA_FLAG_SW_ACTIVITY) - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) ahci_init_sw_activity(link); } @@ -1361,7 +1361,7 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf) struct ahci_em_priv *emp; int rc = 0; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { emp = &pp->em_priv[link->pmp]; rc += sprintf(buf, "%lx\n", emp->led_state); } @@ -1941,7 +1941,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) u32 serror; /* determine active link */ - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) if (ata_link_active(link)) break; if (!link) diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 5c33767e66de..dc48a6398abe 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -57,10 +57,7 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused) if (pdev->vendor == PCI_VENDOR_ID_CENATEK) dma_enabled = 0xFF; - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->dma_mode = XFER_MW_DMA_0; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index c11936e13dd3..5fdf1678d0cc 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1072,20 +1072,13 @@ static int piix_broken_suspend(void) * matching is necessary because dmi_system_id.matches is * limited to four entries. */ - if (dmi_get_system_info(DMI_SYS_VENDOR) && - dmi_get_system_info(DMI_PRODUCT_NAME) && - dmi_get_system_info(DMI_PRODUCT_VERSION) && - dmi_get_system_info(DMI_PRODUCT_SERIAL) && - dmi_get_system_info(DMI_BOARD_VENDOR) && - dmi_get_system_info(DMI_BOARD_NAME) && - dmi_get_system_info(DMI_BOARD_VERSION) && - !strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_NAME), "000000") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_VERSION), "000000") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_SERIAL), "000000") && - !strcmp(dmi_get_system_info(DMI_BOARD_VENDOR), "TOSHIBA") && - !strcmp(dmi_get_system_info(DMI_BOARD_NAME), "Portable PC") && - !strcmp(dmi_get_system_info(DMI_BOARD_VERSION), "Version A0")) + if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") && + dmi_match(DMI_PRODUCT_NAME, "000000") && + dmi_match(DMI_PRODUCT_VERSION, "000000") && + dmi_match(DMI_PRODUCT_SERIAL, "000000") && + dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") && + dmi_match(DMI_BOARD_NAME, "Portable PC") && + dmi_match(DMI_BOARD_VERSION, "Version A0")) return 1; return 0; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index c012307d0ba6..ef02e488d468 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -89,7 +89,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) ap->link.device->acpi_handle = NULL; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { acpi_integer adr = SATA_ADR(ap->port_no, link->pmp); link->device->acpi_handle = @@ -129,8 +129,8 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) struct ata_link *tlink; struct ata_device *tdev; - ata_port_for_each_link(tlink, ap) - ata_link_for_each_dev(tdev, tlink) + ata_for_each_link(tlink, ap, EDGE) + ata_for_each_dev(tdev, tlink, ALL) tdev->flags |= ATA_DFLAG_DETACH; } @@ -588,12 +588,9 @@ int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm) { struct ata_device *dev; - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ENABLED) { unsigned long xfer_mask, udma_mask; - if (!ata_dev_enabled(dev)) - continue; - xfer_mask = ata_acpi_gtm_xfermask(dev, gtm); ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask); @@ -893,7 +890,7 @@ void ata_acpi_on_resume(struct ata_port *ap) * use values set by _STM. Cache _GTF result and * schedule _GTF. */ - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { ata_acpi_clear_gtf(dev); if (ata_dev_enabled(dev) && ata_dev_get_GTF(dev, NULL) >= 0) @@ -904,7 +901,7 @@ void ata_acpi_on_resume(struct ata_port *ap) * there's no reason to evaluate IDE _GTF early * without _STM. Clear cache and schedule _GTF. */ - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { ata_acpi_clear_gtf(dev); if (ata_dev_enabled(dev)) dev->flags |= ATA_DFLAG_ACPI_PENDING; @@ -932,8 +929,8 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) if (state.event == PM_EVENT_ON) acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); - ata_link_for_each_dev(dev, &ap->link) { - if (dev->acpi_handle && ata_dev_enabled(dev)) + ata_for_each_dev(dev, &ap->link, ENABLED) { + if (dev->acpi_handle) acpi_bus_set_power(dev->acpi_handle, state.event == PM_EVENT_ON ? ACPI_STATE_D0 : ACPI_STATE_D3); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bc6695e3c848..fecca4223f8e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -163,43 +163,119 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -/* - * Iterator helpers. Don't use directly. +/** + * ata_link_next - link iteration helper + * @link: the previous link, NULL to start + * @ap: ATA port containing links to iterate + * @mode: iteration mode, one of ATA_LITER_* + * + * LOCKING: + * Host lock or EH context. * - * LOCKING: - * Host lock or EH context. + * RETURNS: + * Pointer to the next link. */ -struct ata_link *__ata_port_next_link(struct ata_port *ap, - struct ata_link *link, bool dev_only) +struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, + enum ata_link_iter_mode mode) { + BUG_ON(mode != ATA_LITER_EDGE && + mode != ATA_LITER_PMP_FIRST && mode != ATA_LITER_HOST_FIRST); + /* NULL link indicates start of iteration */ - if (!link) { - if (dev_only && sata_pmp_attached(ap)) - return ap->pmp_link; - return &ap->link; - } + if (!link) + switch (mode) { + case ATA_LITER_EDGE: + case ATA_LITER_PMP_FIRST: + if (sata_pmp_attached(ap)) + return ap->pmp_link; + /* fall through */ + case ATA_LITER_HOST_FIRST: + return &ap->link; + } - /* we just iterated over the host master link, what's next? */ - if (link == &ap->link) { - if (!sata_pmp_attached(ap)) { - if (unlikely(ap->slave_link) && !dev_only) + /* we just iterated over the host link, what's next? */ + if (link == &ap->link) + switch (mode) { + case ATA_LITER_HOST_FIRST: + if (sata_pmp_attached(ap)) + return ap->pmp_link; + /* fall through */ + case ATA_LITER_PMP_FIRST: + if (unlikely(ap->slave_link)) return ap->slave_link; + /* fall through */ + case ATA_LITER_EDGE: return NULL; } - return ap->pmp_link; - } /* slave_link excludes PMP */ if (unlikely(link == ap->slave_link)) return NULL; - /* iterate to the next PMP link */ + /* we were over a PMP link */ if (++link < ap->pmp_link + ap->nr_pmp_links) return link; + + if (mode == ATA_LITER_PMP_FIRST) + return &ap->link; + return NULL; } /** + * ata_dev_next - device iteration helper + * @dev: the previous device, NULL to start + * @link: ATA link containing devices to iterate + * @mode: iteration mode, one of ATA_DITER_* + * + * LOCKING: + * Host lock or EH context. + * + * RETURNS: + * Pointer to the next device. + */ +struct ata_device *ata_dev_next(struct ata_device *dev, struct ata_link *link, + enum ata_dev_iter_mode mode) +{ + BUG_ON(mode != ATA_DITER_ENABLED && mode != ATA_DITER_ENABLED_REVERSE && + mode != ATA_DITER_ALL && mode != ATA_DITER_ALL_REVERSE); + + /* NULL dev indicates start of iteration */ + if (!dev) + switch (mode) { + case ATA_DITER_ENABLED: + case ATA_DITER_ALL: + dev = link->device; + goto check; + case ATA_DITER_ENABLED_REVERSE: + case ATA_DITER_ALL_REVERSE: + dev = link->device + ata_link_max_devices(link) - 1; + goto check; + } + + next: + /* move to the next one */ + switch (mode) { + case ATA_DITER_ENABLED: + case ATA_DITER_ALL: + if (++dev < link->device + ata_link_max_devices(link)) + goto check; + return NULL; + case ATA_DITER_ENABLED_REVERSE: + case ATA_DITER_ALL_REVERSE: + if (--dev >= link->device) + goto check; + return NULL; + } + + check: + if ((mode == ATA_DITER_ENABLED || mode == ATA_DITER_ENABLED_REVERSE) && + !ata_dev_enabled(dev)) + goto next; + return dev; +} + +/** * ata_dev_phys_link - find physical link for a device * @dev: ATA device to look up physical link for * @@ -1107,8 +1183,8 @@ static void ata_lpm_enable(struct ata_host *host) for (i = 0; i < host->n_ports; i++) { ap = host->ports[i]; - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) ata_dev_disable_pm(dev); } } @@ -2594,11 +2670,11 @@ int ata_bus_probe(struct ata_port *ap) ata_port_probe(ap); - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) tries[dev->devno] = ATA_PROBE_MAX_TRIES; retry: - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { /* If we issue an SRST then an ATA drive (not ATAPI) * may change configuration and be in PIO0 timing. If * we do a hard reset (or are coming from power on) @@ -2620,7 +2696,7 @@ int ata_bus_probe(struct ata_port *ap) /* reset and determine device classes */ ap->ops->phy_reset(ap); - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { if (!(ap->flags & ATA_FLAG_DISABLED) && dev->class != ATA_DEV_UNKNOWN) classes[dev->devno] = dev->class; @@ -2636,7 +2712,7 @@ int ata_bus_probe(struct ata_port *ap) specific sequence bass-ackwards so that PDIAG- is released by the slave device */ - ata_link_for_each_dev_reverse(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL_REVERSE) { if (tries[dev->devno]) dev->class = classes[dev->devno]; @@ -2653,24 +2729,19 @@ int ata_bus_probe(struct ata_port *ap) if (ap->ops->cable_detect) ap->cbl = ap->ops->cable_detect(ap); - /* We may have SATA bridge glue hiding here irrespective of the - reported cable types and sensed types */ - ata_link_for_each_dev(dev, &ap->link) { - if (!ata_dev_enabled(dev)) - continue; - /* SATA drives indicate we have a bridge. We don't know which - end of the link the bridge is which is a problem */ + /* We may have SATA bridge glue hiding here irrespective of + * the reported cable types and sensed types. When SATA + * drives indicate we have a bridge, we don't know which end + * of the link the bridge is which is a problem. + */ + ata_for_each_dev(dev, &ap->link, ENABLED) if (ata_id_is_sata(dev->id)) ap->cbl = ATA_CBL_SATA; - } /* After the identify sequence we can now set up the devices. We do this in the normal order so that the user doesn't get confused */ - ata_link_for_each_dev(dev, &ap->link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, &ap->link, ENABLED) { ap->link.eh_context.i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ap->link.eh_context.i.flags &= ~ATA_EHI_PRINTINFO; @@ -2683,9 +2754,8 @@ int ata_bus_probe(struct ata_port *ap) if (rc) goto fail; - ata_link_for_each_dev(dev, &ap->link) - if (ata_dev_enabled(dev)) - return 0; + ata_for_each_dev(dev, &ap->link, ENABLED) + return 0; /* no device present, disable port */ ata_port_disable(ap); @@ -3331,13 +3401,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) int rc = 0, used_dma = 0, found = 0; /* step 1: calculate xfer_mask */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { unsigned long pio_mask, dma_mask; unsigned int mode_mask; - if (!ata_dev_enabled(dev)) - continue; - mode_mask = ATA_DMA_MASK_ATA; if (dev->class == ATA_DEV_ATAPI) mode_mask = ATA_DMA_MASK_ATAPI; @@ -3366,10 +3433,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) goto out; /* step 2: always set host PIO timings */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { if (dev->pio_mode == 0xff) { ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); rc = -EINVAL; @@ -3383,8 +3447,8 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) } /* step 3: set host DMA timings */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev)) + ata_for_each_dev(dev, link, ENABLED) { + if (!ata_dma_enabled(dev)) continue; dev->xfer_mode = dev->dma_mode; @@ -3394,11 +3458,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) } /* step 4: update devices' xfer mode */ - ata_link_for_each_dev(dev, link) { - /* don't update suspended devices' xfer mode */ - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { rc = ata_dev_set_mode(dev); if (rc) goto out; @@ -4048,6 +4108,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, + { "OCZ CORE_SSD", "02.10104", ATA_HORKAGE_NONCQ }, /* Seagate NCQ + FLUSH CACHE firmware bug */ { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ | @@ -4263,9 +4324,9 @@ static int cable_is_40wire(struct ata_port *ap) * - if you have a non detect capable drive you don't want it * to colour the choice */ - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev) && !ata_is_40wire(dev)) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { + if (!ata_is_40wire(dev)) return 0; } } @@ -4672,7 +4733,6 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /** * ata_qc_new_init - Request an available ATA command, and initialize it * @dev: Device from whom we request an available command structure - * @tag: command tag * * LOCKING: * None. @@ -5218,7 +5278,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, } ap->pflags |= ATA_PFLAG_PM_PENDING; - __ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, HOST_FIRST) { link->eh_info.action |= action; link->eh_info.flags |= ehi_flags; } @@ -6047,8 +6107,6 @@ int ata_host_activate(struct ata_host *host, int irq, static void ata_port_detach(struct ata_port *ap) { unsigned long flags; - struct ata_link *link; - struct ata_device *dev; if (!ap->ops->error_handler) goto skip_eh; @@ -6056,28 +6114,15 @@ static void ata_port_detach(struct ata_port *ap) /* tell EH we're leaving & flush EH */ spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_UNLOADING; + ata_port_schedule_eh(ap); spin_unlock_irqrestore(ap->lock, flags); + /* wait till EH commits suicide */ ata_port_wait_eh(ap); - /* EH is now guaranteed to see UNLOADING - EH context belongs - * to us. Restore SControl and disable all existing devices. - */ - __ata_port_for_each_link(link, ap) { - sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); - ata_link_for_each_dev(dev, link) - ata_dev_disable(dev); - } + /* it better be dead now */ + WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED)); - /* Final freeze & EH. All in-flight commands are aborted. EH - * will be skipped and retrials will be terminated with bad - * target. - */ - spin_lock_irqsave(ap->lock, flags); - ata_port_freeze(ap); /* won't be thawed */ - spin_unlock_irqrestore(ap->lock, flags); - - ata_port_wait_eh(ap); cancel_rearming_delayed_work(&ap->hotplug_task); skip_eh: @@ -6528,7 +6573,8 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops); EXPORT_SYMBOL_GPL(sata_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_info); -EXPORT_SYMBOL_GPL(__ata_port_next_link); +EXPORT_SYMBOL_GPL(ata_link_next); +EXPORT_SYMBOL_GPL(ata_dev_next); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_host_init); EXPORT_SYMBOL_GPL(ata_host_alloc); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 32da9a93ce44..8147a8386370 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -422,7 +422,7 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, if (!dev) { ehi->action &= ~action; - ata_link_for_each_dev(tdev, link) + ata_for_each_dev(tdev, link, ALL) ehi->dev_action[tdev->devno] &= ~action; } else { /* doesn't make sense for port-wide EH actions */ @@ -430,7 +430,7 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, /* break ehi->action into ehi->dev_action */ if (ehi->action & action) { - ata_link_for_each_dev(tdev, link) + ata_for_each_dev(tdev, link, ALL) ehi->dev_action[tdev->devno] |= ehi->action & action; ehi->action &= ~action; @@ -491,6 +491,31 @@ enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) return ret; } +static void ata_eh_unload(struct ata_port *ap) +{ + struct ata_link *link; + struct ata_device *dev; + unsigned long flags; + + /* Restore SControl IPM and SPD for the next driver and + * disable attached devices. + */ + ata_for_each_link(link, ap, PMP_FIRST) { + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); + ata_for_each_dev(dev, link, ALL) + ata_dev_disable(dev); + } + + /* freeze and set UNLOADED */ + spin_lock_irqsave(ap->lock, flags); + + ata_port_freeze(ap); /* won't be thawed */ + ap->pflags &= ~ATA_PFLAG_EH_PENDING; /* clear pending from freeze */ + ap->pflags |= ATA_PFLAG_UNLOADED; + + spin_unlock_irqrestore(ap->lock, flags); +} + /** * ata_scsi_error - SCSI layer error handler callback * @host: SCSI host on which error occurred @@ -592,7 +617,7 @@ void ata_scsi_error(struct Scsi_Host *host) /* fetch & clear EH info */ spin_lock_irqsave(ap->lock, flags); - __ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, HOST_FIRST) { struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev; @@ -600,12 +625,9 @@ void ata_scsi_error(struct Scsi_Host *host) link->eh_context.i = link->eh_info; memset(&link->eh_info, 0, sizeof(link->eh_info)); - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { int devno = dev->devno; - if (!ata_dev_enabled(dev)) - continue; - ehc->saved_xfer_mode[devno] = dev->xfer_mode; if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; @@ -621,8 +643,13 @@ void ata_scsi_error(struct Scsi_Host *host) /* invoke EH, skip if unloading or suspended */ if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) ap->ops->error_handler(ap); - else + else { + /* if unloading, commence suicide */ + if ((ap->pflags & ATA_PFLAG_UNLOADING) && + !(ap->pflags & ATA_PFLAG_UNLOADED)) + ata_eh_unload(ap); ata_eh_finish(ap); + } /* process port suspend request */ ata_eh_handle_port_suspend(ap); @@ -644,7 +671,7 @@ void ata_scsi_error(struct Scsi_Host *host) } /* this run is complete, make sure EH info is clear */ - __ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, HOST_FIRST) memset(&link->eh_info, 0, sizeof(link->eh_info)); /* Clear host_eh_scheduled while holding ap->lock such @@ -1025,7 +1052,7 @@ int sata_async_notification(struct ata_port *ap) struct ata_link *link; /* check and notify ATAPI AN */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(sntf & (1 << link->pmp))) continue; @@ -2005,7 +2032,7 @@ void ata_eh_autopsy(struct ata_port *ap) { struct ata_link *link; - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) ata_eh_link_autopsy(link); /* Handle the frigging slave link. Autopsy is done similarly @@ -2219,7 +2246,7 @@ void ata_eh_report(struct ata_port *ap) { struct ata_link *link; - __ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, HOST_FIRST) ata_eh_link_report(link); } @@ -2230,7 +2257,7 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, struct ata_device *dev; if (clear_classes) - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_UNKNOWN; return reset(link, classes, deadline); @@ -2294,7 +2321,7 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* If we issue an SRST then an ATA drive (not ATAPI) * may change configuration and be in PIO0 timing. If * we do a hard reset (or are coming from power on) @@ -2355,7 +2382,7 @@ int ata_eh_reset(struct ata_link *link, int classify, "port disabled. ignoring.\n"); ehc->i.action &= ~ATA_EH_RESET; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; rc = 0; @@ -2369,7 +2396,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * bang classes and return. */ if (reset && !(ehc->i.action & ATA_EH_RESET)) { - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; rc = 0; goto out; @@ -2454,7 +2481,7 @@ int ata_eh_reset(struct ata_link *link, int classify, /* * Post-reset processing */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* After the reset, the device state is PIO 0 and the * controller state is undefined. Reset also wakes up * drives from sleeping mode. @@ -2510,7 +2537,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * can be reliably detected and retried. */ nr_unknown = 0; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ if (classes[dev->devno] == ATA_DEV_UNKNOWN) { classes[dev->devno] = ATA_DEV_NONE; @@ -2619,8 +2646,8 @@ static inline void ata_eh_pull_park_action(struct ata_port *ap) spin_lock_irqsave(ap->lock, flags); INIT_COMPLETION(ap->park_req_pending); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { struct ata_eh_info *ehi = &link->eh_info; link->eh_context.i.dev_action[dev->devno] |= @@ -2675,7 +2702,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, * be done backwards such that PDIAG- is released by the slave * device before the master device is identified. */ - ata_link_for_each_dev_reverse(dev, link) { + ata_for_each_dev(dev, link, ALL_REVERSE) { unsigned int action = ata_eh_dev_action(dev); unsigned int readid_flags = 0; @@ -2744,7 +2771,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, /* Configure new devices forward such that user doesn't see * device detection messages backwards. */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (!(new_mask & (1 << dev->devno)) || dev->class == ATA_DEV_PMP) continue; @@ -2793,10 +2820,7 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) int rc; /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { struct ata_ering_entry *ent; @@ -2813,14 +2837,11 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) rc = ata_do_set_mode(link, r_failed_dev); /* if transfer mode has changed, set DUBIOUS_XFER on device */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { struct ata_eh_context *ehc = &link->eh_context; u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); - if (!ata_dev_enabled(dev)) - continue; - if (dev->xfer_mode != saved_xfer_mode || ata_ncq_enabled(dev) != saved_ncq) dev->flags |= ATA_DFLAG_DUBIOUS_XFER; @@ -2881,9 +2902,8 @@ static int ata_link_nr_enabled(struct ata_link *link) struct ata_device *dev; int cnt = 0; - ata_link_for_each_dev(dev, link) - if (ata_dev_enabled(dev)) - cnt++; + ata_for_each_dev(dev, link, ENABLED) + cnt++; return cnt; } @@ -2892,7 +2912,7 @@ static int ata_link_nr_vacant(struct ata_link *link) struct ata_device *dev; int cnt = 0; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) if (dev->class == ATA_DEV_UNKNOWN) cnt++; return cnt; @@ -2918,7 +2938,7 @@ static int ata_eh_skip_recovery(struct ata_link *link) return 0; /* skip if class codes for all vacant slots are ATA_DEV_NONE */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (dev->class == ATA_DEV_UNKNOWN && ehc->classes[dev->devno] != ATA_DEV_NONE) return 0; @@ -3026,7 +3046,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, DPRINTK("ENTER\n"); /* prep for recovery */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* re-enable link? */ @@ -3038,7 +3058,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_done(link, NULL, ATA_EH_ENABLE_LINK); } - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (link->flags & ATA_LFLAG_NO_RETRY) ehc->tries[dev->devno] = 1; else @@ -3068,19 +3088,19 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, goto out; /* prep for EH */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* skip EH if possible. */ if (ata_eh_skip_recovery(link)) ehc->i.action = 0; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) ehc->classes[dev->devno] = ATA_DEV_UNKNOWN; } /* reset */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; if (!(ehc->i.action & ATA_EH_RESET)) @@ -3105,8 +3125,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_pull_park_action(ap); deadline = jiffies; - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { struct ata_eh_context *ehc = &link->eh_context; unsigned long tmp; @@ -3134,8 +3154,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, deadline = wait_for_completion_timeout(&ap->park_req_pending, deadline - now); } while (deadline); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { if (!(link->eh_context.unloaded_mask & (1 << dev->devno))) continue; @@ -3146,7 +3166,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, } /* the rest */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* revalidate existing devices and attach new ones */ @@ -3172,7 +3192,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, * disrupting the current users of the device. */ if (ehc->i.flags & ATA_EHI_DID_RESET) { - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (dev->class != ATA_DEV_ATAPI) continue; rc = atapi_eh_clear_ua(dev); @@ -3183,7 +3203,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, /* configure link power saving */ if (ehc->i.action & ATA_EH_LPM) - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) ata_dev_enable_pm(dev, ap->pm_policy); /* this link is okay now */ @@ -3288,7 +3308,7 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, rc = ata_eh_recover(ap, prereset, softreset, hardreset, postreset, NULL); if (rc) { - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) ata_dev_disable(dev); } diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index b65db309c181..98ca07a2db87 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -321,7 +321,7 @@ static void sata_pmp_quirks(struct ata_port *ap) if (vendor == 0x1095 && devid == 0x3726) { /* sil3726 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* Class code report is unreliable and SRST * times out under certain configurations. */ @@ -336,7 +336,7 @@ static void sata_pmp_quirks(struct ata_port *ap) } } else if (vendor == 0x1095 && devid == 0x4723) { /* sil4723 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* class code report is unreliable */ if (link->pmp < 2) link->flags |= ATA_LFLAG_ASSUME_ATA; @@ -348,7 +348,7 @@ static void sata_pmp_quirks(struct ata_port *ap) } } else if (vendor == 0x1095 && devid == 0x4726) { /* sil4726 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* Class code report is unreliable and SRST * times out under certain configurations. * Config device can be at port 0 or 5 and @@ -450,7 +450,7 @@ int sata_pmp_attach(struct ata_device *dev) if (ap->ops->pmp_attach) ap->ops->pmp_attach(ap); - ata_port_for_each_link(tlink, ap) + ata_for_each_link(tlink, ap, EDGE) sata_link_init_spd(tlink); ata_acpi_associate_sata_port(ap); @@ -487,7 +487,7 @@ static void sata_pmp_detach(struct ata_device *dev) if (ap->ops->pmp_detach) ap->ops->pmp_detach(ap); - ata_port_for_each_link(tlink, ap) + ata_for_each_link(tlink, ap, EDGE) ata_eh_detach_dev(tlink->device); spin_lock_irqsave(ap->lock, flags); @@ -700,7 +700,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, } /* PMP is reset, SErrors cannot be trusted, scan all */ - ata_port_for_each_link(tlink, ap) { + ata_for_each_link(tlink, ap, EDGE) { struct ata_eh_context *ehc = &tlink->eh_context; ehc->i.probe_mask |= ATA_ALL_DEVICES; @@ -768,7 +768,7 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) spin_lock_irqsave(ap->lock, flags); - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(link->flags & ATA_LFLAG_DISABLED)) continue; @@ -852,7 +852,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) int cnt, rc; pmp_tries = ATA_EH_PMP_TRIES; - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; retry: @@ -861,7 +861,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) rc = ata_eh_recover(ap, ops->prereset, ops->softreset, ops->hardreset, ops->postreset, NULL); if (rc) { - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) ata_dev_disable(dev); return rc; } @@ -870,7 +870,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) return 0; /* new PMP online */ - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; /* fall through */ @@ -942,7 +942,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) } cnt = 0; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(gscr_error & (1 << link->pmp))) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 47c7afcb36f2..0b2e14f67655 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3229,12 +3229,12 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) return; repeat: - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { struct scsi_device *sdev; int channel = 0, id = 0; - if (!ata_dev_enabled(dev) || dev->sdev) + if (dev->sdev) continue; if (ata_is_host_link(link)) @@ -3255,9 +3255,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) * failure occurred, scan would have failed silently. Check * whether all devices are attached. */ - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev) && !dev->sdev) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { + if (!dev->sdev) goto exit_loop; } } @@ -3381,7 +3381,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) struct ata_port *ap = link->ap; struct ata_device *dev; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { unsigned long flags; if (!(dev->flags & ATA_DFLAG_DETACHED)) @@ -3496,7 +3496,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, if (devno == SCAN_WILD_CARD) { struct ata_link *link; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_info *ehi = &link->eh_info; ehi->probe_mask |= ATA_ALL_DEVICES; ehi->action |= ATA_EH_RESET; @@ -3544,11 +3544,11 @@ void ata_scsi_dev_rescan(struct work_struct *work) spin_lock_irqsave(ap->lock, flags); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { struct scsi_device *sdev = dev->sdev; - if (!ata_dev_enabled(dev) || !sdev) + if (!sdev) continue; if (scsi_device_get(sdev)) continue; diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 1266924c11f9..1050fed96b2b 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -356,7 +356,6 @@ static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev) * bfin_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: um - * @udma: udma mode, 0 - 6 * * Set UDMA mode for device. * diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 860ede526282..f828a29d7756 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -465,24 +465,22 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->dma_mode = XFER_MW_DMA_0; - /* We do need the right mode information for DMA or PIO - and this comes from the current configuration flags */ - if (ata_id_has_dma(dev->id)) { - ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); - dev->xfer_mode = XFER_MW_DMA_0; - dev->xfer_shift = ATA_SHIFT_MWDMA; - dev->flags &= ~ATA_DFLAG_PIO; - } else { - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = XFER_PIO_0; + dev->dma_mode = XFER_MW_DMA_0; + /* We do need the right mode information for DMA or PIO + and this comes from the current configuration flags */ + if (ata_id_has_dma(dev->id)) { + ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); + dev->xfer_mode = XFER_MW_DMA_0; + dev->xfer_shift = ATA_SHIFT_MWDMA; + dev->flags &= ~ATA_DFLAG_PIO; + } else { + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } } return 0; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 2014253f6c88..b173c157ab00 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -30,14 +30,12 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } return 0; } diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 930c2208640b..6c1d778b63a9 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -194,15 +194,12 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - ata_dev_printk(dev, KERN_INFO, - "configured for PIO\n"); - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } return 0; } @@ -641,7 +638,6 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) * qdi6580dp_set_piomode - PIO setup for dual channel * @ap: Port * @adev: Device - * @irq: interrupt line * * In dual channel mode the 6580 has one clock per channel and we have * to software clockswitch in qc_issue. @@ -1028,7 +1024,7 @@ static __init int legacy_init_one(struct legacy_probe *probe) /* Nothing found means we drop the port as its probably not there */ ret = -ENODEV; - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { if (!ata_dev_absent(dev)) { legacy_host[probe->slot] = host; ld->platform_dev = pdev; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index c0dbc46a348e..2c1a91c40c1a 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -116,7 +116,6 @@ static void oldpiix_set_piomode (struct ata_port *ap, struct ata_device *adev) * oldpiix_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers * * Set MWDMA mode for device, in host controller PCI config space. * diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 0e1c2c1134d3..e94efccaa482 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -281,7 +281,6 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long * pdc2027x_set_piomode - Initialize host controller PATA PIO timings * @ap: Port to configure * @adev: um - * @pio: PIO mode, 0 - 4 * * Set PIO mode for device. * @@ -326,7 +325,6 @@ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings * @ap: Port to configure * @adev: um - * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 * * Set UDMA mode for device. * @@ -406,23 +404,20 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed if (rc < 0) return rc; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { + ata_for_each_dev(dev, link, ENABLED) { + pdc2027x_set_piomode(ap, dev); - pdc2027x_set_piomode(ap, dev); + /* + * Enable prefetch if the device support PIO only. + */ + if (dev->xfer_shift == ATA_SHIFT_PIO) { + u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1)); + ctcr1 |= (1 << 25); + iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); - /* - * Enable prefetch if the device support PIO only. - */ - if (dev->xfer_shift == ATA_SHIFT_PIO) { - u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1)); - ctcr1 |= (1 << 25); - iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); - - PDPRINTK("Turn on prefetch\n"); - } else { - pdc2027x_set_dmamode(ap, dev); - } + PDPRINTK("Turn on prefetch\n"); + } else { + pdc2027x_set_dmamode(ap, dev); } } return 0; diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 77e4e3b17f54..6afa07a37648 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -34,14 +34,12 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); } return 0; } diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 0b0aa452de14..695d44ae52c6 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -81,7 +81,6 @@ static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev) * radisys_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers * * Set MWDMA mode for device, in host controller PCI config space. * diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 7dfd1f3f6f3a..46d6bc1bf1e9 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -38,15 +38,13 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); } return 0; } diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index cf3707e516a2..d447f1cb46ec 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -210,7 +210,6 @@ static void scc_set_piomode (struct ata_port *ap, struct ata_device *adev) * scc_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: um - * @udma: udma mode, 0 - 6 * * Set UDMA mode for device. * diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 72e41c9f969b..8d2fd9dd40c7 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -138,7 +138,6 @@ static struct sv_cable_table cable_detect[] = { /** * serverworks_cable_detect - cable detection * @ap: ATA port - * @deadline: deadline jiffies for the operation * * Perform cable detection according to the device and subvendor * identifications diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index e4be55e047f6..27ceb42a774b 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -112,7 +112,6 @@ static int sis_133_cable_detect(struct ata_port *ap) /** * sis_66_cable_detect - check for 40/80 pin * @ap: Port - * @deadline: deadline jiffies for the operation * * Perform cable detection on the UDMA66, UDMA100 and early UDMA133 * SiS IDE controllers. diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 2b24ae58b52e..86918634a4c5 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1836,7 +1836,6 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled) /** * mv_err_intr - Handle error interrupts on the port * @ap: ATA channel to manipulate - * @qc: affected command (non-NCQ), or NULL * * Most cases require a full reset of the chip's state machine, * which also performs a COMRESET. diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 031d7b7dee34..564c142b03b0 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -46,7 +46,9 @@ #include <linux/libata.h> #define DRV_NAME "sata_sil" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.4" + +#define SIL_DMA_BOUNDARY 0x7fffffffUL enum { SIL_MMIO_BAR = 5, @@ -118,6 +120,10 @@ static void sil_dev_config(struct ata_device *dev); static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); +static void sil_qc_prep(struct ata_queued_cmd *qc); +static void sil_bmdma_setup(struct ata_queued_cmd *qc); +static void sil_bmdma_start(struct ata_queued_cmd *qc); +static void sil_bmdma_stop(struct ata_queued_cmd *qc); static void sil_freeze(struct ata_port *ap); static void sil_thaw(struct ata_port *ap); @@ -167,13 +173,22 @@ static struct pci_driver sil_pci_driver = { }; static struct scsi_host_template sil_sht = { - ATA_BMDMA_SHT(DRV_NAME), + ATA_BASE_SHT(DRV_NAME), + /** These controllers support Large Block Transfer which allows + transfer chunks up to 2GB and which cross 64KB boundaries, + therefore the DMA limits are more relaxed than standard ATA SFF. */ + .dma_boundary = SIL_DMA_BOUNDARY, + .sg_tablesize = ATA_MAX_PRD }; static struct ata_port_operations sil_ops = { .inherits = &ata_bmdma_port_ops, .dev_config = sil_dev_config, .set_mode = sil_set_mode, + .bmdma_setup = sil_bmdma_setup, + .bmdma_start = sil_bmdma_start, + .bmdma_stop = sil_bmdma_stop, + .qc_prep = sil_qc_prep, .freeze = sil_freeze, .thaw = sil_thaw, .scr_read = sil_scr_read, @@ -249,6 +264,83 @@ module_param(slow_down, int, 0444); MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); +static void sil_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; + void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; + + /* clear start/stop bit - can safely always write 0 */ + iowrite8(0, bmdma2); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); +} + +static void sil_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *bmdma = ap->ioaddr.bmdma_addr; + + /* load PRD table addr. */ + iowrite32(ap->prd_dma, bmdma + ATA_DMA_TABLE_OFS); + + /* issue r/w command */ + ap->ops->sff_exec_command(ap, &qc->tf); +} + +static void sil_bmdma_start(struct ata_queued_cmd *qc) +{ + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + struct ata_port *ap = qc->ap; + void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; + void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; + u8 dmactl = ATA_DMA_START; + + /* set transfer direction, start host DMA transaction + Note: For Large Block Transfer to work, the DMA must be started + using the bmdma2 register. */ + if (!rw) + dmactl |= ATA_DMA_WR; + iowrite8(dmactl, bmdma2); +} + +/* The way God intended PCI IDE scatter/gather lists to look and behave... */ +static void sil_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg; + struct ata_port *ap = qc->ap; + struct ata_prd *prd, *last_prd = NULL; + unsigned int si; + + prd = &ap->prd[0]; + for_each_sg(qc->sg, sg, qc->n_elem, si) { + /* Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + u32 addr = (u32) sg_dma_address(sg); + u32 sg_len = sg_dma_len(sg); + + prd->addr = cpu_to_le32(addr); + prd->flags_len = cpu_to_le32(sg_len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len); + + last_prd = prd; + prd++; + } + + if (likely(last_prd)) + last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); +} + +static void sil_qc_prep(struct ata_queued_cmd *qc) +{ + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + sil_fill_sg(qc); +} + static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) { u8 cache_line = 0; @@ -278,7 +370,7 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) if (rc) return rc; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (!ata_dev_enabled(dev)) dev_mode[dev->devno] = 0; /* PIO0/1/2 */ else if (dev->flags & ATA_DFLAG_PIO) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9f7c543cc04b..01e69383d9c0 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -164,7 +164,7 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int cciss_revalidate(struct gendisk *disk); static int rebuild_lun_table(ctlr_info_t *h, int first_time); -static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, +static int deregister_disk(ctlr_info_t *h, int drv_index, int clear_all); static void cciss_read_capacity(int ctlr, int logvol, int withirq, @@ -215,31 +215,17 @@ static struct block_device_operations cciss_fops = { /* * Enqueuing and dequeuing functions for cmdlists. */ -static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) +static inline void addQ(struct hlist_head *list, CommandList_struct *c) { - if (*Qptr == NULL) { - *Qptr = c; - c->next = c->prev = c; - } else { - c->prev = (*Qptr)->prev; - c->next = (*Qptr); - (*Qptr)->prev->next = c; - (*Qptr)->prev = c; - } + hlist_add_head(&c->list, list); } -static inline CommandList_struct *removeQ(CommandList_struct **Qptr, - CommandList_struct *c) +static inline void removeQ(CommandList_struct *c) { - if (c && c->next != c) { - if (*Qptr == c) - *Qptr = c->next; - c->prev->next = c->next; - c->next->prev = c->prev; - } else { - *Qptr = NULL; - } - return c; + if (WARN_ON(hlist_unhashed(&c->list))) + return; + + hlist_del_init(&c->list); } #include "cciss_scsi.c" /* For SCSI tape support */ @@ -506,6 +492,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) c->cmdindex = i; } + INIT_HLIST_NODE(&c->list); c->busaddr = (__u32) cmd_dma_handle; temp64.val = (__u64) err_dma_handle; c->ErrDesc.Addr.lower = temp64.val32.lower; @@ -1492,8 +1479,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) * which keeps the interrupt handler from starting * the queue. */ - ret = deregister_disk(h->gendisk[drv_index], - &h->drv[drv_index], 0); + ret = deregister_disk(h, drv_index, 0); h->drv[drv_index].busy_configuring = 0; } @@ -1711,8 +1697,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); h->drv[i].busy_configuring = 1; spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); - return_code = deregister_disk(h->gendisk[i], - &h->drv[i], 1); + return_code = deregister_disk(h, i, 1); h->drv[i].busy_configuring = 0; } } @@ -1782,15 +1767,19 @@ mem_msg: * the highest_lun should be left unchanged and the LunID * should not be cleared. */ -static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, +static int deregister_disk(ctlr_info_t *h, int drv_index, int clear_all) { int i; - ctlr_info_t *h = get_host(disk); + struct gendisk *disk; + drive_info_struct *drv; if (!capable(CAP_SYS_RAWIO)) return -EPERM; + drv = &h->drv[drv_index]; + disk = h->gendisk[drv_index]; + /* make sure logical volume is NOT is use */ if (clear_all || (h->gendisk[0] == disk)) { if (drv->usage_count > 1) @@ -2548,7 +2537,8 @@ static void start_io(ctlr_info_t *h) { CommandList_struct *c; - while ((c = h->reqQ) != NULL) { + while (!hlist_empty(&h->reqQ)) { + c = hlist_entry(h->reqQ.first, CommandList_struct, list); /* can't do anything if fifo is full */ if ((h->access.fifo_full(h))) { printk(KERN_WARNING "cciss: fifo full\n"); @@ -2556,14 +2546,14 @@ static void start_io(ctlr_info_t *h) } /* Get the first entry from the Request Q */ - removeQ(&(h->reqQ), c); + removeQ(c); h->Qdepth--; /* Tell the controller execute command */ h->access.submit_command(h, c); /* Put job onto the completed Q */ - addQ(&(h->cmpQ), c); + addQ(&h->cmpQ, c); } } @@ -2576,7 +2566,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) memset(c->err_info, 0, sizeof(ErrorInfo_struct)); /* add it to software queue and then send it to the controller */ - addQ(&(h->reqQ), c); + addQ(&h->reqQ, c); h->Qdepth++; if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth; @@ -2897,7 +2887,7 @@ static void do_cciss_request(struct request_queue *q) spin_lock_irq(q->queue_lock); - addQ(&(h->reqQ), c); + addQ(&h->reqQ, c); h->Qdepth++; if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth; @@ -2985,16 +2975,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) a = c->busaddr; } else { + struct hlist_node *tmp; + a &= ~3; - if ((c = h->cmpQ) == NULL) { - printk(KERN_WARNING - "cciss: Completion of %08x ignored\n", - a1); - continue; - } - while (c->busaddr != a) { - c = c->next; - if (c == h->cmpQ) + c = NULL; + hlist_for_each_entry(c, tmp, &h->cmpQ, list) { + if (c->busaddr == a) break; } } @@ -3002,8 +2988,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) * If we've found the command, take it off the * completion Q and free it */ - if (c->busaddr == a) { - removeQ(&h->cmpQ, c); + if (c && c->busaddr == a) { + removeQ(c); if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); } else if (c->cmd_type == CMD_IOCTL_PEND) { @@ -3423,6 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, return -1; hba[i]->busy_initializing = 1; + INIT_HLIST_HEAD(&hba[i]->cmpQ); + INIT_HLIST_HEAD(&hba[i]->reqQ); if (cciss_pci_init(hba[i], pdev) != 0) goto clean1; @@ -3730,15 +3718,17 @@ static void fail_all_cmds(unsigned long ctlr) pci_disable_device(h->pdev); /* Make sure it is really dead. */ /* move everything off the request queue onto the completed queue */ - while ((c = h->reqQ) != NULL) { - removeQ(&(h->reqQ), c); + while (!hlist_empty(&h->reqQ)) { + c = hlist_entry(h->reqQ.first, CommandList_struct, list); + removeQ(c); h->Qdepth--; - addQ(&(h->cmpQ), c); + addQ(&h->cmpQ, c); } /* Now, fail everything on the completed queue with a HW error */ - while ((c = h->cmpQ) != NULL) { - removeQ(&h->cmpQ, c); + while (!hlist_empty(&h->cmpQ)) { + c = hlist_entry(h->cmpQ.first, CommandList_struct, list); + removeQ(c); c->err_info->CommandStatus = CMD_HARDWARE_ERR; if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 24a7efa993ab..15e2b84734e3 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -89,8 +89,8 @@ struct ctlr_info struct access_method access; /* queue and queue Info */ - CommandList_struct *reqQ; - CommandList_struct *cmpQ; + struct hlist_head reqQ; + struct hlist_head cmpQ; unsigned int Qdepth; unsigned int maxQsinceinit; unsigned int maxSG; diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 43bf5593b59b..24e22dea1a99 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -265,8 +265,7 @@ typedef struct _CommandList_struct { int ctlr; int cmd_type; long cmdindex; - struct _CommandList_struct *prev; - struct _CommandList_struct *next; + struct hlist_node list; struct request * rq; struct completion *waiting; int retry_count; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index fb06ed659212..edbaac6c0573 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -624,20 +624,38 @@ static int loop_switch(struct loop_device *lo, struct file *file) } /* + * Helper to flush the IOs in loop, but keeping loop thread running + */ +static int loop_flush(struct loop_device *lo) +{ + /* loop not yet configured, no running thread, nothing to flush */ + if (!lo->lo_thread) + return 0; + + return loop_switch(lo, NULL); +} + +/* * Do the actual switch; called from the BIO completion routine */ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) { struct file *file = p->file; struct file *old_file = lo->lo_backing_file; - struct address_space *mapping = file->f_mapping; + struct address_space *mapping; + + /* if no new file, only flush of queued bios requested */ + if (!file) + goto out; + mapping = file->f_mapping; mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); lo->lo_backing_file = file; lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ? mapping->host->i_bdev->bd_block_size : PAGE_SIZE; lo->old_gfp_mask = mapping_gfp_mask(mapping); mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); +out: complete(&p->wait); } @@ -901,6 +919,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) kthread_stop(lo->lo_thread); + lo->lo_queue->unplug_fn = NULL; lo->lo_backing_file = NULL; loop_release_xfer(lo); @@ -1345,11 +1364,25 @@ static int lo_release(struct gendisk *disk, fmode_t mode) struct loop_device *lo = disk->private_data; mutex_lock(&lo->lo_ctl_mutex); - --lo->lo_refcnt; - if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt) + if (--lo->lo_refcnt) + goto out; + + if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) { + /* + * In autoclear mode, stop the loop thread + * and remove configuration after last close. + */ loop_clr_fd(lo, NULL); + } else { + /* + * Otherwise keep thread (if running) and config, + * but flush possible ongoing bios in thread. + */ + loop_flush(lo); + } +out: mutex_unlock(&lo->lo_ctl_mutex); return 0; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d3a91cacee8c..7bcc1d8bc967 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -722,7 +722,6 @@ static int __init nbd_init(void) for (i = 0; i < nbds_max; i++) { struct gendisk *disk = alloc_disk(1 << part_shift); - elevator_t *old_e; if (!disk) goto out; nbd_dev[i].disk = disk; @@ -736,11 +735,10 @@ static int __init nbd_init(void) put_disk(disk); goto out; } - old_e = disk->queue->elevator; - if (elevator_init(disk->queue, "deadline") == 0 || - elevator_init(disk->queue, "noop") == 0) { - elevator_exit(old_e); - } + /* + * Tell the block layer that we are not a rotational device + */ + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); } if (register_blkdev(NBD_MAJOR, "nbd")) { diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 85d79a02d487..5d34764c8a87 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -6,7 +6,6 @@ #include <linux/virtio_blk.h> #include <linux/scatterlist.h> -#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) #define PART_BITS 4 static int major, index; @@ -26,8 +25,11 @@ struct virtio_blk mempool_t *pool; + /* What host tells us, plus 2 for header & tailer. */ + unsigned int sg_elems; + /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[VIRTIO_MAX_SG]; + struct scatterlist sg[/*sg_elems*/]; }; struct virtblk_req @@ -97,8 +99,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, if (blk_barrier_rq(vbr->req)) vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; - /* This init could be done at vblk creation time */ - sg_init_table(vblk->sg, VIRTIO_MAX_SG); sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); @@ -130,7 +130,7 @@ static void do_virtblk_request(struct request_queue *q) while ((req = elv_next_request(q)) != NULL) { vblk = req->rq_disk->private_data; - BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg)); + BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); /* If this request fails, stop queue and wait for something to finish to restart it. */ @@ -196,12 +196,22 @@ static int virtblk_probe(struct virtio_device *vdev) int err; u64 cap; u32 v; - u32 blk_size; + u32 blk_size, sg_elems; if (index_to_minor(index) >= 1 << MINORBITS) return -ENOSPC; - vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); + /* We need to know how many segments before we allocate. */ + err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, + offsetof(struct virtio_blk_config, seg_max), + &sg_elems); + if (err) + sg_elems = 1; + + /* We need an extra sg elements at head and tail. */ + sg_elems += 2; + vdev->priv = vblk = kmalloc(sizeof(*vblk) + + sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); if (!vblk) { err = -ENOMEM; goto out; @@ -210,6 +220,8 @@ static int virtblk_probe(struct virtio_device *vdev) INIT_LIST_HEAD(&vblk->reqs); spin_lock_init(&vblk->lock); vblk->vdev = vdev; + vblk->sg_elems = sg_elems; + sg_init_table(vblk->sg, vblk->sg_elems); /* We expect one virtqueue, for output. */ vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); @@ -237,6 +249,8 @@ static int virtblk_probe(struct virtio_device *vdev) goto out_put_disk; } + queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue); + if (index < 26) { sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); } else if (index < (26 + 1) * 26) { @@ -277,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev) } set_capacity(vblk->disk, cap); + /* We can handle whatever the host told us to handle. */ + blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); + blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); + + /* No real sector limit. */ + blk_queue_max_sectors(vblk->disk->queue, -1U); + /* Host can optionally specify maximum segment size and number of * segments. */ err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, @@ -284,12 +305,8 @@ static int virtblk_probe(struct virtio_device *vdev) &v); if (!err) blk_queue_max_segment_size(vblk->disk->queue, v); - - err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, - offsetof(struct virtio_blk_config, seg_max), - &v); - if (!err) - blk_queue_max_hw_segments(vblk->disk->queue, v); + else + blk_queue_max_segment_size(vblk->disk->queue, -1U); /* Host can optionally specify the block size of the device */ err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 2d19f0cc47f2..918ef725de41 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -338,18 +338,12 @@ wait: static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { struct request_queue *rq; - elevator_t *old_e; rq = blk_init_queue(do_blkif_request, &blkif_io_lock); if (rq == NULL) return -1; - old_e = rq->elevator; - if (IS_ERR_VALUE(elevator_init(rq, "noop"))) - printk(KERN_WARNING - "blkfront: Switch elevator failed, use default\n"); - else - elevator_exit(old_e); + queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); /* Hard sector size and max sectors impersonate the equiv. hardware. */ blk_queue_hardsect_size(rq, sector_size); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 7d2e91cccb13..cceace61ef28 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1712,29 +1712,30 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) return 0; } -static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { unsigned char buf[21], *base; struct dvd_layer *layer; - struct packet_command cgc; struct cdrom_device_ops *cdo = cdi->ops; int ret, layer_num = s->physical.layer_num; if (layer_num >= DVD_LAYERS) return -EINVAL; - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[6] = layer_num; - cgc.cmd[7] = s->type; - cgc.cmd[9] = cgc.buflen & 0xff; + init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); + cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; + cgc->cmd[6] = layer_num; + cgc->cmd[7] = s->type; + cgc->cmd[9] = cgc->buflen & 0xff; /* * refrain from reporting errors on non-existing layers (mainly) */ - cgc.quiet = 1; + cgc->quiet = 1; - if ((ret = cdo->generic_packet(cdi, &cgc))) + ret = cdo->generic_packet(cdi, cgc); + if (ret) return ret; base = &buf[4]; @@ -1762,21 +1763,22 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) return 0; } -static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { int ret; u_char buf[8]; - struct packet_command cgc; struct cdrom_device_ops *cdo = cdi->ops; - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[6] = s->copyright.layer_num; - cgc.cmd[7] = s->type; - cgc.cmd[8] = cgc.buflen >> 8; - cgc.cmd[9] = cgc.buflen & 0xff; + init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); + cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; + cgc->cmd[6] = s->copyright.layer_num; + cgc->cmd[7] = s->type; + cgc->cmd[8] = cgc->buflen >> 8; + cgc->cmd[9] = cgc->buflen & 0xff; - if ((ret = cdo->generic_packet(cdi, &cgc))) + ret = cdo->generic_packet(cdi, cgc); + if (ret) return ret; s->copyright.cpst = buf[4]; @@ -1785,79 +1787,89 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) return 0; } -static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { int ret, size; u_char *buf; - struct packet_command cgc; struct cdrom_device_ops *cdo = cdi->ops; size = sizeof(s->disckey.value) + 4; - if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) + buf = kmalloc(size, GFP_KERNEL); + if (!buf) return -ENOMEM; - init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[8] = size >> 8; - cgc.cmd[9] = size & 0xff; - cgc.cmd[10] = s->disckey.agid << 6; + init_cdrom_command(cgc, buf, size, CGC_DATA_READ); + cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; + cgc->cmd[7] = s->type; + cgc->cmd[8] = size >> 8; + cgc->cmd[9] = size & 0xff; + cgc->cmd[10] = s->disckey.agid << 6; - if (!(ret = cdo->generic_packet(cdi, &cgc))) + ret = cdo->generic_packet(cdi, cgc); + if (!ret) memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); kfree(buf); return ret; } -static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { - int ret; - u_char buf[4 + 188]; - struct packet_command cgc; + int ret, size = 4 + 188; + u_char *buf; struct cdrom_device_ops *cdo = cdi->ops; - init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[9] = cgc.buflen & 0xff; + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; + init_cdrom_command(cgc, buf, size, CGC_DATA_READ); + cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; + cgc->cmd[7] = s->type; + cgc->cmd[9] = cgc->buflen & 0xff; + + ret = cdo->generic_packet(cdi, cgc); + if (ret) + goto out; s->bca.len = buf[0] << 8 | buf[1]; if (s->bca.len < 12 || s->bca.len > 188) { cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); - return -EIO; + ret = -EIO; + goto out; } memcpy(s->bca.value, &buf[4], s->bca.len); - - return 0; + ret = 0; +out: + kfree(buf); + return ret; } -static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { int ret = 0, size; u_char *buf; - struct packet_command cgc; struct cdrom_device_ops *cdo = cdi->ops; size = sizeof(s->manufact.value) + 4; - if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) + buf = kmalloc(size, GFP_KERNEL); + if (!buf) return -ENOMEM; - init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc.cmd[7] = s->type; - cgc.cmd[8] = size >> 8; - cgc.cmd[9] = size & 0xff; + init_cdrom_command(cgc, buf, size, CGC_DATA_READ); + cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; + cgc->cmd[7] = s->type; + cgc->cmd[8] = size >> 8; + cgc->cmd[9] = size & 0xff; - if ((ret = cdo->generic_packet(cdi, &cgc))) { - kfree(buf); - return ret; - } + ret = cdo->generic_packet(cdi, cgc); + if (ret) + goto out; s->manufact.len = buf[0] << 8 | buf[1]; if (s->manufact.len < 0 || s->manufact.len > 2048) { @@ -1868,27 +1880,29 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) memcpy(s->manufact.value, &buf[4], s->manufact.len); } +out: kfree(buf); return ret; } -static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s) +static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s, + struct packet_command *cgc) { switch (s->type) { case DVD_STRUCT_PHYSICAL: - return dvd_read_physical(cdi, s); + return dvd_read_physical(cdi, s, cgc); case DVD_STRUCT_COPYRIGHT: - return dvd_read_copyright(cdi, s); + return dvd_read_copyright(cdi, s, cgc); case DVD_STRUCT_DISCKEY: - return dvd_read_disckey(cdi, s); + return dvd_read_disckey(cdi, s, cgc); case DVD_STRUCT_BCA: - return dvd_read_bca(cdi, s); + return dvd_read_bca(cdi, s, cgc); case DVD_STRUCT_MANUFACT: - return dvd_read_manufact(cdi, s); + return dvd_read_manufact(cdi, s, cgc); default: cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", @@ -2787,271 +2801,360 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) return cdo->generic_packet(cdi, &cgc); } -static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct packet_command cgc; +static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, + void __user *arg, + struct packet_command *cgc, + int cmd) +{ struct request_sense sense; - unsigned char buffer[32]; - int ret = 0; - - memset(&cgc, 0, sizeof(cgc)); + struct cdrom_msf msf; + int blocksize = 0, format = 0, lba; + int ret; - /* build a unified command and queue it through - cdo->generic_packet() */ switch (cmd) { case CDROMREADRAW: + blocksize = CD_FRAMESIZE_RAW; + break; case CDROMREADMODE1: - case CDROMREADMODE2: { - struct cdrom_msf msf; - int blocksize = 0, format = 0, lba; - - switch (cmd) { - case CDROMREADRAW: - blocksize = CD_FRAMESIZE_RAW; - break; - case CDROMREADMODE1: - blocksize = CD_FRAMESIZE; - format = 2; - break; - case CDROMREADMODE2: - blocksize = CD_FRAMESIZE_RAW0; - break; - } - IOCTL_IN(arg, struct cdrom_msf, msf); - lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0); - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0) - return -EINVAL; - cgc.buffer = kmalloc(blocksize, GFP_KERNEL); - if (cgc.buffer == NULL) - return -ENOMEM; - memset(&sense, 0, sizeof(sense)); - cgc.sense = &sense; - cgc.data_direction = CGC_DATA_READ; - ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize); - if (ret && sense.sense_key==0x05 && sense.asc==0x20 && sense.ascq==0x00) { - /* - * SCSI-II devices are not required to support - * READ_CD, so let's try switching block size - */ - /* FIXME: switch back again... */ - if ((ret = cdrom_switch_blocksize(cdi, blocksize))) { - kfree(cgc.buffer); - return ret; - } - cgc.sense = NULL; - ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); - ret |= cdrom_switch_blocksize(cdi, blocksize); - } - if (!ret && copy_to_user((char __user *)arg, cgc.buffer, blocksize)) - ret = -EFAULT; - kfree(cgc.buffer); + blocksize = CD_FRAMESIZE; + format = 2; + break; + case CDROMREADMODE2: + blocksize = CD_FRAMESIZE_RAW0; + break; + } + IOCTL_IN(arg, struct cdrom_msf, msf); + lba = msf_to_lba(msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0); + /* FIXME: we need upper bound checking, too!! */ + if (lba < 0) + return -EINVAL; + + cgc->buffer = kmalloc(blocksize, GFP_KERNEL); + if (cgc->buffer == NULL) + return -ENOMEM; + + memset(&sense, 0, sizeof(sense)); + cgc->sense = &sense; + cgc->data_direction = CGC_DATA_READ; + ret = cdrom_read_block(cdi, cgc, lba, 1, format, blocksize); + if (ret && sense.sense_key == 0x05 && + sense.asc == 0x20 && + sense.ascq == 0x00) { + /* + * SCSI-II devices are not required to support + * READ_CD, so let's try switching block size + */ + /* FIXME: switch back again... */ + ret = cdrom_switch_blocksize(cdi, blocksize); + if (ret) + goto out; + cgc->sense = NULL; + ret = cdrom_read_cd(cdi, cgc, lba, blocksize, 1); + ret |= cdrom_switch_blocksize(cdi, blocksize); + } + if (!ret && copy_to_user(arg, cgc->buffer, blocksize)) + ret = -EFAULT; +out: + kfree(cgc->buffer); + return ret; +} + +static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi, + void __user *arg) +{ + struct cdrom_read_audio ra; + int lba; + + IOCTL_IN(arg, struct cdrom_read_audio, ra); + + if (ra.addr_format == CDROM_MSF) + lba = msf_to_lba(ra.addr.msf.minute, + ra.addr.msf.second, + ra.addr.msf.frame); + else if (ra.addr_format == CDROM_LBA) + lba = ra.addr.lba; + else + return -EINVAL; + + /* FIXME: we need upper bound checking, too!! */ + if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES) + return -EINVAL; + + return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes); +} + +static noinline int mmc_ioctl_cdrom_subchannel(struct cdrom_device_info *cdi, + void __user *arg) +{ + int ret; + struct cdrom_subchnl q; + u_char requested, back; + IOCTL_IN(arg, struct cdrom_subchnl, q); + requested = q.cdsc_format; + if (!((requested == CDROM_MSF) || + (requested == CDROM_LBA))) + return -EINVAL; + q.cdsc_format = CDROM_MSF; + ret = cdrom_read_subchannel(cdi, &q, 0); + if (ret) return ret; - } - case CDROMREADAUDIO: { - struct cdrom_read_audio ra; - int lba; - - IOCTL_IN(arg, struct cdrom_read_audio, ra); - - if (ra.addr_format == CDROM_MSF) - lba = msf_to_lba(ra.addr.msf.minute, - ra.addr.msf.second, - ra.addr.msf.frame); - else if (ra.addr_format == CDROM_LBA) - lba = ra.addr.lba; - else - return -EINVAL; + back = q.cdsc_format; /* local copy */ + sanitize_format(&q.cdsc_absaddr, &back, requested); + sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); + IOCTL_OUT(arg, struct cdrom_subchnl, q); + /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ + return 0; +} - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES) - return -EINVAL; +static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi, + void __user *arg, + struct packet_command *cgc) +{ + struct cdrom_device_ops *cdo = cdi->ops; + struct cdrom_msf msf; + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); + IOCTL_IN(arg, struct cdrom_msf, msf); + cgc->cmd[0] = GPCMD_PLAY_AUDIO_MSF; + cgc->cmd[3] = msf.cdmsf_min0; + cgc->cmd[4] = msf.cdmsf_sec0; + cgc->cmd[5] = msf.cdmsf_frame0; + cgc->cmd[6] = msf.cdmsf_min1; + cgc->cmd[7] = msf.cdmsf_sec1; + cgc->cmd[8] = msf.cdmsf_frame1; + cgc->data_direction = CGC_DATA_NONE; + return cdo->generic_packet(cdi, cgc); +} - return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes); - } - case CDROMSUBCHNL: { - struct cdrom_subchnl q; - u_char requested, back; - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - if ((ret = cdrom_read_subchannel(cdi, &q, 0))) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; - } - case CDROMPLAYMSF: { - struct cdrom_msf msf; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; - cgc.cmd[3] = msf.cdmsf_min0; - cgc.cmd[4] = msf.cdmsf_sec0; - cgc.cmd[5] = msf.cdmsf_frame0; - cgc.cmd[6] = msf.cdmsf_min1; - cgc.cmd[7] = msf.cdmsf_sec1; - cgc.cmd[8] = msf.cdmsf_frame1; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - case CDROMPLAYBLK: { - struct cdrom_blk blk; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); - IOCTL_IN(arg, struct cdrom_blk, blk); - cgc.cmd[0] = GPCMD_PLAY_AUDIO_10; - cgc.cmd[2] = (blk.from >> 24) & 0xff; - cgc.cmd[3] = (blk.from >> 16) & 0xff; - cgc.cmd[4] = (blk.from >> 8) & 0xff; - cgc.cmd[5] = blk.from & 0xff; - cgc.cmd[7] = (blk.len >> 8) & 0xff; - cgc.cmd[8] = blk.len & 0xff; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } - case CDROMVOLCTRL: - case CDROMVOLREAD: { - struct cdrom_volctrl volctrl; - char mask[sizeof(buffer)]; - unsigned short offset; +static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi, + void __user *arg, + struct packet_command *cgc) +{ + struct cdrom_device_ops *cdo = cdi->ops; + struct cdrom_blk blk; + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); + IOCTL_IN(arg, struct cdrom_blk, blk); + cgc->cmd[0] = GPCMD_PLAY_AUDIO_10; + cgc->cmd[2] = (blk.from >> 24) & 0xff; + cgc->cmd[3] = (blk.from >> 16) & 0xff; + cgc->cmd[4] = (blk.from >> 8) & 0xff; + cgc->cmd[5] = blk.from & 0xff; + cgc->cmd[7] = (blk.len >> 8) & 0xff; + cgc->cmd[8] = blk.len & 0xff; + cgc->data_direction = CGC_DATA_NONE; + return cdo->generic_packet(cdi, cgc); +} + +static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi, + void __user *arg, + struct packet_command *cgc, + unsigned int cmd) +{ + struct cdrom_volctrl volctrl; + unsigned char buffer[32]; + char mask[sizeof(buffer)]; + unsigned short offset; + int ret; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); + cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volctrl); + IOCTL_IN(arg, struct cdrom_volctrl, volctrl); - cgc.buffer = buffer; - cgc.buflen = 24; - if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0))) - return ret; + cgc->buffer = buffer; + cgc->buflen = 24; + ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 0); + if (ret) + return ret; - /* originally the code depended on buffer[1] to determine - how much data is available for transfer. buffer[1] is - unfortunately ambigious and the only reliable way seem - to be to simply skip over the block descriptor... */ - offset = 8 + be16_to_cpu(*(__be16 *)(buffer+6)); - - if (offset + 16 > sizeof(buffer)) - return -E2BIG; - - if (offset + 16 > cgc.buflen) { - cgc.buflen = offset+16; - ret = cdrom_mode_sense(cdi, &cgc, - GPMODE_AUDIO_CTL_PAGE, 0); - if (ret) - return ret; - } + /* originally the code depended on buffer[1] to determine + how much data is available for transfer. buffer[1] is + unfortunately ambigious and the only reliable way seem + to be to simply skip over the block descriptor... */ + offset = 8 + be16_to_cpu(*(__be16 *)(buffer + 6)); + + if (offset + 16 > sizeof(buffer)) + return -E2BIG; + + if (offset + 16 > cgc->buflen) { + cgc->buflen = offset + 16; + ret = cdrom_mode_sense(cdi, cgc, + GPMODE_AUDIO_CTL_PAGE, 0); + if (ret) + return ret; + } - /* sanity check */ - if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || - buffer[offset+1] < 14) - return -EINVAL; + /* sanity check */ + if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || + buffer[offset + 1] < 14) + return -EINVAL; - /* now we have the current volume settings. if it was only - a CDROMVOLREAD, return these values */ - if (cmd == CDROMVOLREAD) { - volctrl.channel0 = buffer[offset+9]; - volctrl.channel1 = buffer[offset+11]; - volctrl.channel2 = buffer[offset+13]; - volctrl.channel3 = buffer[offset+15]; - IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); - return 0; - } + /* now we have the current volume settings. if it was only + a CDROMVOLREAD, return these values */ + if (cmd == CDROMVOLREAD) { + volctrl.channel0 = buffer[offset+9]; + volctrl.channel1 = buffer[offset+11]; + volctrl.channel2 = buffer[offset+13]; + volctrl.channel3 = buffer[offset+15]; + IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); + return 0; + } - /* get the volume mask */ - cgc.buffer = mask; - if ((ret = cdrom_mode_sense(cdi, &cgc, - GPMODE_AUDIO_CTL_PAGE, 1))) - return ret; + /* get the volume mask */ + cgc->buffer = mask; + ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 1); + if (ret) + return ret; - buffer[offset+9] = volctrl.channel0 & mask[offset+9]; - buffer[offset+11] = volctrl.channel1 & mask[offset+11]; - buffer[offset+13] = volctrl.channel2 & mask[offset+13]; - buffer[offset+15] = volctrl.channel3 & mask[offset+15]; + buffer[offset + 9] = volctrl.channel0 & mask[offset + 9]; + buffer[offset + 11] = volctrl.channel1 & mask[offset + 11]; + buffer[offset + 13] = volctrl.channel2 & mask[offset + 13]; + buffer[offset + 15] = volctrl.channel3 & mask[offset + 15]; - /* set volume */ - cgc.buffer = buffer + offset - 8; - memset(cgc.buffer, 0, 8); - return cdrom_mode_select(cdi, &cgc); - } + /* set volume */ + cgc->buffer = buffer + offset - 8; + memset(cgc->buffer, 0, 8); + return cdrom_mode_select(cdi, cgc); +} - case CDROMSTART: - case CDROMSTOP: { - cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); - cgc.cmd[0] = GPCMD_START_STOP_UNIT; - cgc.cmd[1] = 1; - cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } +static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi, + struct packet_command *cgc, + int cmd) +{ + struct cdrom_device_ops *cdo = cdi->ops; + cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); + cgc->cmd[0] = GPCMD_START_STOP_UNIT; + cgc->cmd[1] = 1; + cgc->cmd[4] = (cmd == CDROMSTART) ? 1 : 0; + cgc->data_direction = CGC_DATA_NONE; + return cdo->generic_packet(cdi, cgc); +} - case CDROMPAUSE: - case CDROMRESUME: { - cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); - cgc.cmd[0] = GPCMD_PAUSE_RESUME; - cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; - cgc.data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, &cgc); - } +static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi, + struct packet_command *cgc, + int cmd) +{ + struct cdrom_device_ops *cdo = cdi->ops; + cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); + cgc->cmd[0] = GPCMD_PAUSE_RESUME; + cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; + cgc->data_direction = CGC_DATA_NONE; + return cdo->generic_packet(cdi, cgc); +} - case DVD_READ_STRUCT: { - dvd_struct *s; - int size = sizeof(dvd_struct); - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - if ((s = kmalloc(size, GFP_KERNEL)) == NULL) - return -ENOMEM; - cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); - if (copy_from_user(s, (dvd_struct __user *)arg, size)) { - kfree(s); - return -EFAULT; - } - if ((ret = dvd_read_struct(cdi, s))) { - kfree(s); - return ret; - } - if (copy_to_user((dvd_struct __user *)arg, s, size)) - ret = -EFAULT; +static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, + void __user *arg, + struct packet_command *cgc) +{ + int ret; + dvd_struct *s; + int size = sizeof(dvd_struct); + + if (!CDROM_CAN(CDC_DVD)) + return -ENOSYS; + + s = kmalloc(size, GFP_KERNEL); + if (!s) + return -ENOMEM; + + cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); + if (copy_from_user(s, arg, size)) { kfree(s); + return -EFAULT; + } + + ret = dvd_read_struct(cdi, s, cgc); + if (ret) + goto out; + + if (copy_to_user(arg, s, size)) + ret = -EFAULT; +out: + kfree(s); + return ret; +} + +static noinline int mmc_ioctl_dvd_auth(struct cdrom_device_info *cdi, + void __user *arg) +{ + int ret; + dvd_authinfo ai; + if (!CDROM_CAN(CDC_DVD)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); + IOCTL_IN(arg, dvd_authinfo, ai); + ret = dvd_do_auth(cdi, &ai); + if (ret) return ret; - } + IOCTL_OUT(arg, dvd_authinfo, ai); + return 0; +} - case DVD_AUTH: { - dvd_authinfo ai; - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); - IOCTL_IN(arg, dvd_authinfo, ai); - if ((ret = dvd_do_auth (cdi, &ai))) - return ret; - IOCTL_OUT(arg, dvd_authinfo, ai); - return 0; - } +static noinline int mmc_ioctl_cdrom_next_writable(struct cdrom_device_info *cdi, + void __user *arg) +{ + int ret; + long next = 0; + cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); + ret = cdrom_get_next_writable(cdi, &next); + if (ret) + return ret; + IOCTL_OUT(arg, long, next); + return 0; +} - case CDROM_NEXT_WRITABLE: { - long next = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); - if ((ret = cdrom_get_next_writable(cdi, &next))) - return ret; - IOCTL_OUT(arg, long, next); - return 0; - } - case CDROM_LAST_WRITTEN: { - long last = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); - if ((ret = cdrom_get_last_written(cdi, &last))) - return ret; - IOCTL_OUT(arg, long, last); - return 0; - } - } /* switch */ +static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi, + void __user *arg) +{ + int ret; + long last = 0; + cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); + ret = cdrom_get_last_written(cdi, &last); + if (ret) + return ret; + IOCTL_OUT(arg, long, last); + return 0; +} + +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + unsigned long arg) +{ + struct packet_command cgc; + void __user *userptr = (void __user *)arg; + + memset(&cgc, 0, sizeof(cgc)); + + /* build a unified command and queue it through + cdo->generic_packet() */ + switch (cmd) { + case CDROMREADRAW: + case CDROMREADMODE1: + case CDROMREADMODE2: + return mmc_ioctl_cdrom_read_data(cdi, userptr, &cgc, cmd); + case CDROMREADAUDIO: + return mmc_ioctl_cdrom_read_audio(cdi, userptr); + case CDROMSUBCHNL: + return mmc_ioctl_cdrom_subchannel(cdi, userptr); + case CDROMPLAYMSF: + return mmc_ioctl_cdrom_play_msf(cdi, userptr, &cgc); + case CDROMPLAYBLK: + return mmc_ioctl_cdrom_play_blk(cdi, userptr, &cgc); + case CDROMVOLCTRL: + case CDROMVOLREAD: + return mmc_ioctl_cdrom_volume(cdi, userptr, &cgc, cmd); + case CDROMSTART: + case CDROMSTOP: + return mmc_ioctl_cdrom_start_stop(cdi, &cgc, cmd); + case CDROMPAUSE: + case CDROMRESUME: + return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd); + case DVD_READ_STRUCT: + return mmc_ioctl_dvd_read_struct(cdi, userptr, &cgc); + case DVD_AUTH: + return mmc_ioctl_dvd_auth(cdi, userptr); + case CDROM_NEXT_WRITABLE: + return mmc_ioctl_cdrom_next_writable(cdi, userptr); + case CDROM_LAST_WRITTEN: + return mmc_ioctl_cdrom_last_written(cdi, userptr); + } return -ENOTTY; } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 9cf6e9bb017e..c7714185f831 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -40,6 +40,8 @@ #define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12 #define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20 #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 +#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 +#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 /* cover 915 and 945 variants */ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ @@ -63,7 +65,8 @@ #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB) extern int agp_memory_reserved; @@ -1196,6 +1199,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) case PCI_DEVICE_ID_INTEL_IGD_E_HB: case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_G45_HB: + case PCI_DEVICE_ID_INTEL_G41_HB: *gtt_offset = *gtt_size = MB(2); break; default: @@ -2156,13 +2160,15 @@ static const struct intel_driver_description { { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, - "Mobile Intel? GM45 Express", NULL, &intel_i965_driver }, + "Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, "Q45/Q43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0, "G45/G43", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, + "G41", NULL, &intel_i965_driver }, { 0, 0, 0, NULL, NULL, NULL } }; @@ -2360,6 +2366,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_IGD_E_HB), ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB), + ID(PCI_DEVICE_ID_INTEL_G41_HB), { } }; diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 74e9cd81b5b2..61f0146e215d 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -43,52 +43,51 @@ static const char *fan_state[] = { "off", "on", "on (hardwired)" }; * chance that the WaveArtist driver could touch these bits to * enable or disable the speaker. */ -extern spinlock_t gpio_lock; extern unsigned int system_rev; static inline void netwinder_ds1620_set_clk(int clk) { - gpio_modify_op(GPIO_DSCLK, clk ? GPIO_DSCLK : 0); + nw_gpio_modify_op(GPIO_DSCLK, clk ? GPIO_DSCLK : 0); } static inline void netwinder_ds1620_set_data(int dat) { - gpio_modify_op(GPIO_DATA, dat ? GPIO_DATA : 0); + nw_gpio_modify_op(GPIO_DATA, dat ? GPIO_DATA : 0); } static inline int netwinder_ds1620_get_data(void) { - return gpio_read() & GPIO_DATA; + return nw_gpio_read() & GPIO_DATA; } static inline void netwinder_ds1620_set_data_dir(int dir) { - gpio_modify_io(GPIO_DATA, dir ? GPIO_DATA : 0); + nw_gpio_modify_io(GPIO_DATA, dir ? GPIO_DATA : 0); } static inline void netwinder_ds1620_reset(void) { - cpld_modify(CPLD_DS_ENABLE, 0); - cpld_modify(CPLD_DS_ENABLE, CPLD_DS_ENABLE); + nw_cpld_modify(CPLD_DS_ENABLE, 0); + nw_cpld_modify(CPLD_DS_ENABLE, CPLD_DS_ENABLE); } static inline void netwinder_lock(unsigned long *flags) { - spin_lock_irqsave(&gpio_lock, *flags); + spin_lock_irqsave(&nw_gpio_lock, *flags); } static inline void netwinder_unlock(unsigned long *flags) { - spin_unlock_irqrestore(&gpio_lock, *flags); + spin_unlock_irqrestore(&nw_gpio_lock, *flags); } static inline void netwinder_set_fan(int i) { unsigned long flags; - spin_lock_irqsave(&gpio_lock, flags); - gpio_modify_op(GPIO_FAN, i ? GPIO_FAN : 0); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_gpio_modify_op(GPIO_FAN, i ? GPIO_FAN : 0); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } static inline int netwinder_get_fan(void) @@ -96,7 +95,7 @@ static inline int netwinder_get_fan(void) if ((system_rev & 0xf000) == 0x4000) return FAN_ALWAYS_ON; - return (gpio_read() & GPIO_FAN) ? FAN_ON : FAN_OFF; + return (nw_gpio_read() & GPIO_FAN) ? FAN_ON : FAN_OFF; } /* diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 53fdc7ff3870..32b8bbf5003e 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -46,7 +46,7 @@ /* * The High Precision Event Timer driver. * This driver is closely modelled after the rtc.c driver. - * http://www.intel.com/hardwaredesign/hpetspec.htm + * http://www.intel.com/hardwaredesign/hpetspec_1.pdf */ #define HPET_USER_FREQ (64) #define HPET_DRIFT (500) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index fb57f67bb427..0587b66d6fc7 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -695,6 +695,7 @@ void hvc_resize(struct hvc_struct *hp, struct winsize ws) hp->ws = ws; schedule_work(&hp->tty_resize); } +EXPORT_SYMBOL_GPL(hvc_resize); /* * This kthread is either polling or interrupt driven. This is determined by diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 006be92ee3f3..8c7df5ba088f 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -58,8 +58,6 @@ static volatile unsigned char *FLASH_BASE; static int gbFlashSize = KFLASH_SIZE; static DEFINE_MUTEX(nwflash_mutex); -extern spinlock_t gpio_lock; - static int get_flash_id(void) { volatile unsigned int c1, c2; @@ -616,9 +614,9 @@ static void kick_open(void) * we want to write a bit pattern XXX1 to Xilinx to enable * the write gate, which will be open for about the next 2ms. */ - spin_lock_irqsave(&gpio_lock, flags); - cpld_modify(1, 1); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); + spin_unlock_irqrestore(&nw_gpio_lock, flags); /* * let the ISA bus to catch on... diff --git a/drivers/char/random.c b/drivers/char/random.c index 675076f5fca8..d26891bfcd41 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -558,23 +558,9 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -static struct timer_rand_state *irq_timer_state[NR_IRQS]; - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - if (irq >= nr_irqs) - return NULL; - - return irq_timer_state[irq]; -} - -static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state) -{ - if (irq >= nr_irqs) - return; - - irq_timer_state[irq] = state; -} +#ifndef CONFIG_SPARSE_IRQ +struct timer_rand_state *irq_timer_state[NR_IRQS]; +#endif static struct timer_rand_state input_timer_state; @@ -933,8 +919,10 @@ void rand_initialize_irq(int irq) { struct timer_rand_state *state; +#ifndef CONFIG_SPARSE_IRQ if (irq >= nr_irqs) return; +#endif state = get_timer_rand_state(irq); diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 3fb0d2c88ba5..ff6f5a4b58fb 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -138,12 +138,33 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) } /* + * virtio console configuration. This supports: + * - console resize + */ +static void virtcons_apply_config(struct virtio_device *dev) +{ + struct winsize ws; + + if (virtio_has_feature(dev, VIRTIO_CONSOLE_F_SIZE)) { + dev->config->get(dev, + offsetof(struct virtio_console_config, cols), + &ws.ws_col, sizeof(u16)); + dev->config->get(dev, + offsetof(struct virtio_console_config, rows), + &ws.ws_row, sizeof(u16)); + hvc_resize(hvc, ws); + } +} + +/* * we support only one console, the hvc struct is a global var - * There is no need to do anything + * We set the configuration at this point, since we now have a tty */ static int notifier_add_vio(struct hvc_struct *hp, int data) { hp->irq_requested = 1; + virtcons_apply_config(vdev); + return 0; } @@ -234,11 +255,18 @@ static struct virtio_device_id id_table[] = { { 0 }, }; +static unsigned int features[] = { + VIRTIO_CONSOLE_F_SIZE, +}; + static struct virtio_driver virtio_console = { + .feature_table = features, + .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtcons_probe, + .config_changed = virtcons_apply_config, }; static int __init init(void) diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index c20171078d1d..e1129fad96dd 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -57,11 +57,6 @@ u32 acpi_pm_read_verified(void) return v2; } -static cycle_t acpi_pm_read_slow(void) -{ - return (cycle_t)acpi_pm_read_verified(); -} - static cycle_t acpi_pm_read(void) { return (cycle_t)read_pmtmr(); @@ -88,6 +83,11 @@ static int __init acpi_pm_good_setup(char *__str) } __setup("acpi_pm_good", acpi_pm_good_setup); +static cycle_t acpi_pm_read_slow(void) +{ + return (cycle_t)acpi_pm_read_verified(); +} + static inline void acpi_pm_need_workaround(void) { clocksource_acpi_pm.read = acpi_pm_read_slow; diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 4a597d8c2f70..78b989d202a3 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -582,3 +582,19 @@ int dmi_walk(void (*decode)(const struct dmi_header *)) return 0; } EXPORT_SYMBOL_GPL(dmi_walk); + +/** + * dmi_match - compare a string to the dmi field (if exists) + * + * Returns true if the requested field equals to the str (including NULL). + */ +bool dmi_match(enum dmi_field f, const char *str) +{ + const char *info = dmi_get_system_info(f); + + if (info == NULL || str == NULL) + return info == str; + + return !strcmp(info, str); +} +EXPORT_SYMBOL_GPL(dmi_match); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index a8b33c2ec8d2..5130b72d593c 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -7,6 +7,8 @@ menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU + select I2C + select I2C_ALGOBIT help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select @@ -65,6 +67,10 @@ config DRM_I830 will load the correct one. config DRM_I915 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + depends on FB tristate "i915 driver" help Choose this option if you have a system that has Intel 830M, 845G, @@ -76,6 +82,17 @@ config DRM_I915 endchoice +config DRM_I915_KMS + bool "Enable modesetting on intel by default" + depends on DRM_I915 + help + Choose this option if you want kernel modesetting enabled by default, + and you have a new enough userspace to support this. Running old + userspaces with this enabled will cause pain. Note that this causes + the driver to bind to PCI devices, which precludes loading things + like intelfb. + + config DRM_MGA tristate "Matrox g200/g400" depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 74da99495e21..30022c4a5c12 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -9,7 +9,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.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 ati_pcigart.o drm_pci.o \ - drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o + drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ + drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o drm-$(CONFIG_COMPAT) += drm_ioc32.o diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index a73462723d2d..ca7a9ef5007b 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -45,14 +45,15 @@ * the one with matching magic number, while holding the drm_device::struct_mutex * lock. */ -static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic) +static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic) { struct drm_file *retval = NULL; struct drm_magic_entry *pt; struct drm_hash_item *hash; + struct drm_device *dev = master->minor->dev; mutex_lock(&dev->struct_mutex); - if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { + if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); retval = pt->priv; } @@ -71,11 +72,11 @@ static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic * associated the magic number hash key in drm_device::magiclist, while holding * the drm_device::struct_mutex lock. */ -static int drm_add_magic(struct drm_device * dev, struct drm_file * priv, +static int drm_add_magic(struct drm_master *master, struct drm_file *priv, drm_magic_t magic) { struct drm_magic_entry *entry; - + struct drm_device *dev = master->minor->dev; DRM_DEBUG("%d\n", magic); entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); @@ -83,11 +84,10 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv, return -ENOMEM; memset(entry, 0, sizeof(*entry)); entry->priv = priv; - entry->hash_item.key = (unsigned long)magic; mutex_lock(&dev->struct_mutex); - drm_ht_insert_item(&dev->magiclist, &entry->hash_item); - list_add_tail(&entry->head, &dev->magicfree); + drm_ht_insert_item(&master->magiclist, &entry->hash_item); + list_add_tail(&entry->head, &master->magicfree); mutex_unlock(&dev->struct_mutex); return 0; @@ -102,20 +102,21 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv, * Searches and unlinks the entry in drm_device::magiclist with the magic * number hash key, while holding the drm_device::struct_mutex lock. */ -static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic) +static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) { struct drm_magic_entry *pt; struct drm_hash_item *hash; + struct drm_device *dev = master->minor->dev; DRM_DEBUG("%d\n", magic); mutex_lock(&dev->struct_mutex); - if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { + if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { mutex_unlock(&dev->struct_mutex); return -EINVAL; } pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); - drm_ht_remove_item(&dev->magiclist, hash); + drm_ht_remove_item(&master->magiclist, hash); list_del(&pt->head); mutex_unlock(&dev->struct_mutex); @@ -153,9 +154,9 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) ++sequence; /* reserve 0 */ auth->magic = sequence++; spin_unlock(&lock); - } while (drm_find_file(dev, auth->magic)); + } while (drm_find_file(file_priv->master, auth->magic)); file_priv->magic = auth->magic; - drm_add_magic(dev, file_priv, auth->magic); + drm_add_magic(file_priv->master, file_priv, auth->magic); } DRM_DEBUG("%u\n", auth->magic); @@ -181,9 +182,9 @@ int drm_authmagic(struct drm_device *dev, void *data, struct drm_file *file; DRM_DEBUG("%u\n", auth->magic); - if ((file = drm_find_file(dev, auth->magic))) { + if ((file = drm_find_file(file_priv->master, auth->magic))) { file->authenticated = 1; - drm_remove_magic(dev, auth->magic); + drm_remove_magic(file_priv->master, auth->magic); return 0; } return -EINVAL; diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index bde64b84166e..72c667f9bee1 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -54,9 +54,9 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, { struct drm_map_list *entry; list_for_each_entry(entry, &dev->maplist, head) { - if (entry->map && map->type == entry->map->type && + if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && ((entry->map->offset == map->offset) || - (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) { + ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { return entry; } } @@ -210,12 +210,12 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, map->offset = (unsigned long)map->handle; if (map->flags & _DRM_CONTAINS_LOCK) { /* Prevent a 2nd X Server from creating a 2nd lock */ - if (dev->lock.hw_lock != NULL) { + if (dev->primary->master->lock.hw_lock != NULL) { vfree(map->handle); drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EBUSY; } - dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ + dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */ } break; case _DRM_AGP: { @@ -262,6 +262,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); break; + case _DRM_GEM: + DRM_ERROR("tried to rmmap GEM object\n"); + break; } case _DRM_SCATTER_GATHER: if (!dev->sg) { @@ -319,6 +322,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, list->user_token = list->hash.key << PAGE_SHIFT; mutex_unlock(&dev->struct_mutex); + list->master = dev->primary->master; *maplist = list; return 0; } @@ -345,7 +349,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data, struct drm_map_list *maplist; int err; - if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) + if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM)) return -EPERM; err = drm_addmap_core(dev, map->offset, map->size, map->type, @@ -380,10 +384,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) struct drm_map_list *r_list = NULL, *list_t; drm_dma_handle_t dmah; int found = 0; + struct drm_master *master; /* Find the list entry for the map and remove it */ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { if (r_list->map == map) { + master = r_list->master; list_del(&r_list->head); drm_ht_remove_key(&dev->map_hash, r_list->user_token >> PAGE_SHIFT); @@ -409,6 +415,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) break; case _DRM_SHM: vfree(map->handle); + if (master) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; /* SHM removed */ + master->lock.file_priv = NULL; + wake_up_interruptible(&master->lock.lock_queue); + } break; case _DRM_AGP: case _DRM_SCATTER_GATHER: @@ -419,11 +432,15 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) dmah.size = map->size; __drm_pci_free(dev, &dmah); break; + case _DRM_GEM: + DRM_ERROR("tried to rmmap GEM object\n"); + break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); return 0; } +EXPORT_SYMBOL(drm_rmmap_locked); int drm_rmmap(struct drm_device *dev, drm_local_map_t *map) { diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index d505f695421f..809ec0f03452 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -256,12 +256,13 @@ static int drm_context_switch(struct drm_device * dev, int old, int new) * hardware lock is held, clears the drm_device::context_flag and wakes up * drm_device::context_wait. */ -static int drm_context_switch_complete(struct drm_device * dev, int new) +static int drm_context_switch_complete(struct drm_device *dev, + struct drm_file *file_priv, int new) { dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ dev->last_switch = jiffies; - if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) { DRM_ERROR("Lock isn't held after context switch\n"); } @@ -420,7 +421,7 @@ int drm_newctx(struct drm_device *dev, void *data, struct drm_ctx *ctx = data; DRM_DEBUG("%d\n", ctx->handle); - drm_context_switch_complete(dev, ctx->handle); + drm_context_switch_complete(dev, file_priv, ctx->handle); return 0; } @@ -442,9 +443,6 @@ int drm_rmctx(struct drm_device *dev, void *data, struct drm_ctx *ctx = data; DRM_DEBUG("%d\n", ctx->handle); - if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { - file_priv->remove_auth_on_close = 1; - } if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) dev->driver->context_dtor(dev, ctx->handle); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c new file mode 100644 index 000000000000..53c87254be4c --- /dev/null +++ b/drivers/gpu/drm/drm_crtc.c @@ -0,0 +1,2446 @@ +/* + * Copyright (c) 2006-2008 Intel Corporation + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (c) 2008 Red Hat Inc. + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Keith Packard + * Eric Anholt <eric@anholt.net> + * Dave Airlie <airlied@linux.ie> + * Jesse Barnes <jesse.barnes@intel.com> + */ +#include <linux/list.h> +#include "drm.h" +#include "drmP.h" +#include "drm_crtc.h" + +struct drm_prop_enum_list { + int type; + char *name; +}; + +/* Avoid boilerplate. I'm tired of typing. */ +#define DRM_ENUM_NAME_FN(fnname, list) \ + char *fnname(int val) \ + { \ + int i; \ + for (i = 0; i < ARRAY_SIZE(list); i++) { \ + if (list[i].type == val) \ + return list[i].name; \ + } \ + return "(unknown)"; \ + } + +/* + * Global properties + */ +static struct drm_prop_enum_list drm_dpms_enum_list[] = +{ { DRM_MODE_DPMS_ON, "On" }, + { DRM_MODE_DPMS_STANDBY, "Standby" }, + { DRM_MODE_DPMS_SUSPEND, "Suspend" }, + { DRM_MODE_DPMS_OFF, "Off" } +}; + +DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) + +/* + * Optional properties + */ +static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = +{ + { DRM_MODE_SCALE_NON_GPU, "Non-GPU" }, + { DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" }, + { DRM_MODE_SCALE_NO_SCALE, "No scale" }, + { DRM_MODE_SCALE_ASPECT, "Aspect" }, +}; + +static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = +{ + { DRM_MODE_DITHERING_OFF, "Off" }, + { DRM_MODE_DITHERING_ON, "On" }, +}; + +/* + * Non-global properties, but "required" for certain connectors. + */ +static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ +}; + +DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) + +static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ +}; + +DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, + drm_dvi_i_subconnector_enum_list) + +static struct drm_prop_enum_list drm_tv_select_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ +}; + +DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) + +static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ +}; + +DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, + drm_tv_subconnector_enum_list) + +struct drm_conn_prop_enum_list { + int type; + char *name; + int count; +}; + +/* + * Connector and encoder types. + */ +static struct drm_conn_prop_enum_list drm_connector_enum_list[] = +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, + { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, + { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, + { DRM_MODE_CONNECTOR_Component, "Component", 0 }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, +}; + +static struct drm_prop_enum_list drm_encoder_enum_list[] = +{ { DRM_MODE_ENCODER_NONE, "None" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TV" }, +}; + +char *drm_get_encoder_name(struct drm_encoder *encoder) +{ + static char buf[32]; + + snprintf(buf, 32, "%s-%d", + drm_encoder_enum_list[encoder->encoder_type].name, + encoder->base.id); + return buf; +} + +char *drm_get_connector_name(struct drm_connector *connector) +{ + static char buf[32]; + + snprintf(buf, 32, "%s-%d", + drm_connector_enum_list[connector->connector_type].name, + connector->connector_type_id); + return buf; +} +EXPORT_SYMBOL(drm_get_connector_name); + +char *drm_get_connector_status_name(enum drm_connector_status status) +{ + if (status == connector_status_connected) + return "connected"; + else if (status == connector_status_disconnected) + return "disconnected"; + else + return "unknown"; +} + +/** + * drm_mode_object_get - allocate a new identifier + * @dev: DRM device + * @ptr: object pointer, used to generate unique ID + * @type: object type + * + * LOCKING: + * Caller must hold DRM mode_config lock. + * + * Create a unique identifier based on @ptr in @dev's identifier space. Used + * for tracking modes, CRTCs and connectors. + * + * RETURNS: + * New unique (relative to other objects in @dev) integer identifier for the + * object. + */ +static int drm_mode_object_get(struct drm_device *dev, + struct drm_mode_object *obj, uint32_t obj_type) +{ + int new_id = 0; + int ret; + + WARN(!mutex_is_locked(&dev->mode_config.mutex), + "%s called w/o mode_config lock\n", __FUNCTION__); +again: + if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Ran out memory getting a mode number\n"); + return -EINVAL; + } + + ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); + if (ret == -EAGAIN) + goto again; + + obj->id = new_id; + obj->type = obj_type; + return 0; +} + +/** + * drm_mode_object_put - free an identifer + * @dev: DRM device + * @id: ID to free + * + * LOCKING: + * Caller must hold DRM mode_config lock. + * + * Free @id from @dev's unique identifier pool. + */ +static void drm_mode_object_put(struct drm_device *dev, + struct drm_mode_object *object) +{ + idr_remove(&dev->mode_config.crtc_idr, object->id); +} + +void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) +{ + struct drm_mode_object *obj; + + obj = idr_find(&dev->mode_config.crtc_idr, id); + if (!obj || (obj->type != type) || (obj->id != id)) + return NULL; + + return obj; +} +EXPORT_SYMBOL(drm_mode_object_find); + +/** + * drm_crtc_from_fb - find the CRTC structure associated with an fb + * @dev: DRM device + * @fb: framebuffer in question + * + * LOCKING: + * Caller must hold mode_config lock. + * + * Find CRTC in the mode_config structure that matches @fb. + * + * RETURNS: + * Pointer to the CRTC or NULL if it wasn't found. + */ +struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, + struct drm_framebuffer *fb) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) + return crtc; + } + return NULL; +} + +/** + * drm_framebuffer_init - initialize a framebuffer + * @dev: DRM device + * + * LOCKING: + * Caller must hold mode config lock. + * + * Allocates an ID for the framebuffer's parent mode object, sets its mode + * functions & device file and adds it to the master fd list. + * + * RETURNS: + * Zero on success, error code on falure. + */ +int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, + const struct drm_framebuffer_funcs *funcs) +{ + int ret; + + ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); + if (ret) { + return ret; + } + + fb->dev = dev; + fb->funcs = funcs; + dev->mode_config.num_fb++; + list_add(&fb->head, &dev->mode_config.fb_list); + + return 0; +} +EXPORT_SYMBOL(drm_framebuffer_init); + +/** + * drm_framebuffer_cleanup - remove a framebuffer object + * @fb: framebuffer to remove + * + * LOCKING: + * Caller must hold mode config lock. + * + * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes + * it, setting it to NULL. + */ +void drm_framebuffer_cleanup(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb->dev; + struct drm_crtc *crtc; + + /* remove from any CRTC */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) + crtc->fb = NULL; + } + + drm_mode_object_put(dev, &fb->base); + list_del(&fb->head); + dev->mode_config.num_fb--; +} +EXPORT_SYMBOL(drm_framebuffer_cleanup); + +/** + * drm_crtc_init - Initialise a new CRTC object + * @dev: DRM device + * @crtc: CRTC object to init + * @funcs: callbacks for the new CRTC + * + * LOCKING: + * Caller must hold mode config lock. + * + * Inits a new object created as base part of an driver crtc object. + */ +void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + const struct drm_crtc_funcs *funcs) +{ + crtc->dev = dev; + crtc->funcs = funcs; + + mutex_lock(&dev->mode_config.mutex); + drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); + + list_add_tail(&crtc->head, &dev->mode_config.crtc_list); + dev->mode_config.num_crtc++; + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_crtc_init); + +/** + * drm_crtc_cleanup - Cleans up the core crtc usage. + * @crtc: CRTC to cleanup + * + * LOCKING: + * Caller must hold mode config lock. + * + * Cleanup @crtc. Removes from drm modesetting space + * does NOT free object, caller does that. + */ +void drm_crtc_cleanup(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + + if (crtc->gamma_store) { + kfree(crtc->gamma_store); + crtc->gamma_store = NULL; + } + + drm_mode_object_put(dev, &crtc->base); + list_del(&crtc->head); + dev->mode_config.num_crtc--; +} +EXPORT_SYMBOL(drm_crtc_cleanup); + +/** + * drm_mode_probed_add - add a mode to a connector's probed mode list + * @connector: connector the new mode + * @mode: mode data + * + * LOCKING: + * Caller must hold mode config lock. + * + * Add @mode to @connector's mode list for later use. + */ +void drm_mode_probed_add(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + list_add(&mode->head, &connector->probed_modes); +} +EXPORT_SYMBOL(drm_mode_probed_add); + +/** + * drm_mode_remove - remove and free a mode + * @connector: connector list to modify + * @mode: mode to remove + * + * LOCKING: + * Caller must hold mode config lock. + * + * Remove @mode from @connector's mode list, then free it. + */ +void drm_mode_remove(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + list_del(&mode->head); + kfree(mode); +} +EXPORT_SYMBOL(drm_mode_remove); + +/** + * drm_connector_init - Init a preallocated connector + * @dev: DRM device + * @connector: the connector to init + * @funcs: callbacks for this connector + * @name: user visible name of the connector + * + * LOCKING: + * Caller must hold @dev's mode_config lock. + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. + */ +void drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type) +{ + mutex_lock(&dev->mode_config.mutex); + + connector->dev = dev; + connector->funcs = funcs; + drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); + connector->connector_type = connector_type; + connector->connector_type_id = + ++drm_connector_enum_list[connector_type].count; /* TODO */ + INIT_LIST_HEAD(&connector->user_modes); + INIT_LIST_HEAD(&connector->probed_modes); + INIT_LIST_HEAD(&connector->modes); + connector->edid_blob_ptr = NULL; + + list_add_tail(&connector->head, &dev->mode_config.connector_list); + dev->mode_config.num_connector++; + + drm_connector_attach_property(connector, + dev->mode_config.edid_property, 0); + + drm_connector_attach_property(connector, + dev->mode_config.dpms_property, 0); + + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_connector_init); + +/** + * drm_connector_cleanup - cleans up an initialised connector + * @connector: connector to cleanup + * + * LOCKING: + * Caller must hold @dev's mode_config lock. + * + * Cleans up the connector but doesn't free the object. + */ +void drm_connector_cleanup(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode, *t; + + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) + drm_mode_remove(connector, mode); + + list_for_each_entry_safe(mode, t, &connector->modes, head) + drm_mode_remove(connector, mode); + + list_for_each_entry_safe(mode, t, &connector->user_modes, head) + drm_mode_remove(connector, mode); + + mutex_lock(&dev->mode_config.mutex); + drm_mode_object_put(dev, &connector->base); + list_del(&connector->head); + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_connector_cleanup); + +void drm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type) +{ + mutex_lock(&dev->mode_config.mutex); + + encoder->dev = dev; + + drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); + encoder->encoder_type = encoder_type; + encoder->funcs = funcs; + + list_add_tail(&encoder->head, &dev->mode_config.encoder_list); + dev->mode_config.num_encoder++; + + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_encoder_init); + +void drm_encoder_cleanup(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + mutex_lock(&dev->mode_config.mutex); + drm_mode_object_put(dev, &encoder->base); + list_del(&encoder->head); + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_encoder_cleanup); + +/** + * drm_mode_create - create a new display mode + * @dev: DRM device + * + * LOCKING: + * Caller must hold DRM mode_config lock. + * + * Create a new drm_display_mode, give it an ID, and return it. + * + * RETURNS: + * Pointer to new mode on success, NULL on error. + */ +struct drm_display_mode *drm_mode_create(struct drm_device *dev) +{ + struct drm_display_mode *nmode; + + nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); + if (!nmode) + return NULL; + + drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE); + return nmode; +} +EXPORT_SYMBOL(drm_mode_create); + +/** + * drm_mode_destroy - remove a mode + * @dev: DRM device + * @mode: mode to remove + * + * LOCKING: + * Caller must hold mode config lock. + * + * Free @mode's unique identifier, then free it. + */ +void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) +{ + drm_mode_object_put(dev, &mode->base); + + kfree(mode); +} +EXPORT_SYMBOL(drm_mode_destroy); + +static int drm_mode_create_standard_connector_properties(struct drm_device *dev) +{ + struct drm_property *edid; + struct drm_property *dpms; + int i; + + /* + * Standard properties (apply to all connectors) + */ + edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_IMMUTABLE, + "EDID", 0); + dev->mode_config.edid_property = edid; + + dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) + drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type, + drm_dpms_enum_list[i].name); + dev->mode_config.dpms_property = dpms; + + return 0; +} + +/** + * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties + * @dev: DRM device + * + * Called by a driver the first time a DVI-I connector is made. + */ +int drm_mode_create_dvi_i_properties(struct drm_device *dev) +{ + struct drm_property *dvi_i_selector; + struct drm_property *dvi_i_subconnector; + int i; + + if (dev->mode_config.dvi_i_select_subconnector_property) + return 0; + + dvi_i_selector = + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "select subconnector", + ARRAY_SIZE(drm_dvi_i_select_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++) + drm_property_add_enum(dvi_i_selector, i, + drm_dvi_i_select_enum_list[i].type, + drm_dvi_i_select_enum_list[i].name); + dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; + + dvi_i_subconnector = + drm_property_create(dev, DRM_MODE_PROP_ENUM | + DRM_MODE_PROP_IMMUTABLE, + "subconnector", + ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++) + drm_property_add_enum(dvi_i_subconnector, i, + drm_dvi_i_subconnector_enum_list[i].type, + drm_dvi_i_subconnector_enum_list[i].name); + dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); + +/** + * drm_create_tv_properties - create TV specific connector properties + * @dev: DRM device + * @num_modes: number of different TV formats (modes) supported + * @modes: array of pointers to strings containing name of each format + * + * Called by a driver's TV initialization routine, this function creates + * the TV specific connector properties for a given device. Caller is + * responsible for allocating a list of format names and passing them to + * this routine. + */ +int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, + char *modes[]) +{ + struct drm_property *tv_selector; + struct drm_property *tv_subconnector; + int i; + + if (dev->mode_config.tv_select_subconnector_property) + return 0; + + /* + * Basic connector properties + */ + tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "select subconnector", + ARRAY_SIZE(drm_tv_select_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++) + drm_property_add_enum(tv_selector, i, + drm_tv_select_enum_list[i].type, + drm_tv_select_enum_list[i].name); + dev->mode_config.tv_select_subconnector_property = tv_selector; + + tv_subconnector = + drm_property_create(dev, DRM_MODE_PROP_ENUM | + DRM_MODE_PROP_IMMUTABLE, "subconnector", + ARRAY_SIZE(drm_tv_subconnector_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++) + drm_property_add_enum(tv_subconnector, i, + drm_tv_subconnector_enum_list[i].type, + drm_tv_subconnector_enum_list[i].name); + dev->mode_config.tv_subconnector_property = tv_subconnector; + + /* + * Other, TV specific properties: margins & TV modes. + */ + dev->mode_config.tv_left_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "left margin", 2); + dev->mode_config.tv_left_margin_property->values[0] = 0; + dev->mode_config.tv_left_margin_property->values[1] = 100; + + dev->mode_config.tv_right_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "right margin", 2); + dev->mode_config.tv_right_margin_property->values[0] = 0; + dev->mode_config.tv_right_margin_property->values[1] = 100; + + dev->mode_config.tv_top_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "top margin", 2); + dev->mode_config.tv_top_margin_property->values[0] = 0; + dev->mode_config.tv_top_margin_property->values[1] = 100; + + dev->mode_config.tv_bottom_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "bottom margin", 2); + dev->mode_config.tv_bottom_margin_property->values[0] = 0; + dev->mode_config.tv_bottom_margin_property->values[1] = 100; + + dev->mode_config.tv_mode_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "mode", num_modes); + for (i = 0; i < num_modes; i++) + drm_property_add_enum(dev->mode_config.tv_mode_property, i, + i, modes[i]); + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_tv_properties); + +/** + * drm_mode_create_scaling_mode_property - create scaling mode property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + */ +int drm_mode_create_scaling_mode_property(struct drm_device *dev) +{ + struct drm_property *scaling_mode; + int i; + + if (dev->mode_config.scaling_mode_property) + return 0; + + scaling_mode = + drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode", + ARRAY_SIZE(drm_scaling_mode_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) + drm_property_add_enum(scaling_mode, i, + drm_scaling_mode_enum_list[i].type, + drm_scaling_mode_enum_list[i].name); + + dev->mode_config.scaling_mode_property = scaling_mode; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); + +/** + * drm_mode_create_dithering_property - create dithering property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + */ +int drm_mode_create_dithering_property(struct drm_device *dev) +{ + struct drm_property *dithering_mode; + int i; + + if (dev->mode_config.dithering_mode_property) + return 0; + + dithering_mode = + drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering", + ARRAY_SIZE(drm_dithering_mode_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++) + drm_property_add_enum(dithering_mode, i, + drm_dithering_mode_enum_list[i].type, + drm_dithering_mode_enum_list[i].name); + dev->mode_config.dithering_mode_property = dithering_mode; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_dithering_property); + +/** + * drm_mode_config_init - initialize DRM mode_configuration structure + * @dev: DRM device + * + * LOCKING: + * None, should happen single threaded at init time. + * + * Initialize @dev's mode_config structure, used for tracking the graphics + * configuration of @dev. + */ +void drm_mode_config_init(struct drm_device *dev) +{ + mutex_init(&dev->mode_config.mutex); + INIT_LIST_HEAD(&dev->mode_config.fb_list); + INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list); + INIT_LIST_HEAD(&dev->mode_config.crtc_list); + INIT_LIST_HEAD(&dev->mode_config.connector_list); + INIT_LIST_HEAD(&dev->mode_config.encoder_list); + INIT_LIST_HEAD(&dev->mode_config.property_list); + INIT_LIST_HEAD(&dev->mode_config.property_blob_list); + idr_init(&dev->mode_config.crtc_idr); + + mutex_lock(&dev->mode_config.mutex); + drm_mode_create_standard_connector_properties(dev); + mutex_unlock(&dev->mode_config.mutex); + + /* Just to be sure */ + dev->mode_config.num_fb = 0; + dev->mode_config.num_connector = 0; + dev->mode_config.num_crtc = 0; + dev->mode_config.num_encoder = 0; +} +EXPORT_SYMBOL(drm_mode_config_init); + +int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) +{ + uint32_t total_objects = 0; + + total_objects += dev->mode_config.num_crtc; + total_objects += dev->mode_config.num_connector; + total_objects += dev->mode_config.num_encoder; + + if (total_objects == 0) + return -EINVAL; + + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); + if (!group->id_list) + return -ENOMEM; + + group->num_crtcs = 0; + group->num_connectors = 0; + group->num_encoders = 0; + return 0; +} + +int drm_mode_group_init_legacy_group(struct drm_device *dev, + struct drm_mode_group *group) +{ + struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; + int ret; + + if ((ret = drm_mode_group_init(dev, group))) + return ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + group->id_list[group->num_crtcs++] = crtc->base.id; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + group->id_list[group->num_crtcs + group->num_encoders++] = + encoder->base.id; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + group->id_list[group->num_crtcs + group->num_encoders + + group->num_connectors++] = connector->base.id; + + return 0; +} + +/** + * drm_mode_config_cleanup - free up DRM mode_config info + * @dev: DRM device + * + * LOCKING: + * Caller must hold mode config lock. + * + * Free up all the connectors and CRTCs associated with this DRM device, then + * free up the framebuffers and associated buffer objects. + * + * FIXME: cleanup any dangling user buffer objects too + */ +void drm_mode_config_cleanup(struct drm_device *dev) +{ + struct drm_connector *connector, *ot; + struct drm_crtc *crtc, *ct; + struct drm_encoder *encoder, *enct; + struct drm_framebuffer *fb, *fbt; + struct drm_property *property, *pt; + + list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, + head) { + encoder->funcs->destroy(encoder); + } + + list_for_each_entry_safe(connector, ot, + &dev->mode_config.connector_list, head) { + connector->funcs->destroy(connector); + } + + list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, + head) { + drm_property_destroy(dev, property); + } + + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { + fb->funcs->destroy(fb); + } + + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + crtc->funcs->destroy(crtc); + } + +} +EXPORT_SYMBOL(drm_mode_config_cleanup); + +/** + * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo + * @out: drm_mode_modeinfo struct to return to the user + * @in: drm_display_mode to use + * + * LOCKING: + * None. + * + * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to + * the user. + */ +void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, + struct drm_display_mode *in) +{ + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + out->vrefresh = in->vrefresh; + out->flags = in->flags; + out->type = in->type; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; +} + +/** + * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode + * @out: drm_display_mode to return to the user + * @in: drm_mode_modeinfo to use + * + * LOCKING: + * None. + * + * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to + * the caller. + */ +void drm_crtc_convert_umode(struct drm_display_mode *out, + struct drm_mode_modeinfo *in) +{ + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + out->vrefresh = in->vrefresh; + out->flags = in->flags; + out->type = in->type; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; +} + +/** + * drm_mode_getresources - get graphics configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Takes mode config lock. + * + * Construct a set of configuration description structures and return + * them to the user, including CRTC, connector and framebuffer configuration. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_getresources(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_card_res *card_res = data; + struct list_head *lh; + struct drm_framebuffer *fb; + struct drm_connector *connector; + struct drm_crtc *crtc; + struct drm_encoder *encoder; + int ret = 0; + int connector_count = 0; + int crtc_count = 0; + int fb_count = 0; + int encoder_count = 0; + int copied = 0, i; + uint32_t __user *fb_id; + uint32_t __user *crtc_id; + uint32_t __user *connector_id; + uint32_t __user *encoder_id; + struct drm_mode_group *mode_group; + + mutex_lock(&dev->mode_config.mutex); + + /* + * For the non-control nodes we need to limit the list of resources + * by IDs in the group list for this node + */ + list_for_each(lh, &file_priv->fbs) + fb_count++; + + mode_group = &file_priv->master->minor->mode_group; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + + list_for_each(lh, &dev->mode_config.crtc_list) + crtc_count++; + + list_for_each(lh, &dev->mode_config.connector_list) + connector_count++; + + list_for_each(lh, &dev->mode_config.encoder_list) + encoder_count++; + } else { + + crtc_count = mode_group->num_crtcs; + connector_count = mode_group->num_connectors; + encoder_count = mode_group->num_encoders; + } + + card_res->max_height = dev->mode_config.max_height; + card_res->min_height = dev->mode_config.min_height; + card_res->max_width = dev->mode_config.max_width; + card_res->min_width = dev->mode_config.min_width; + + /* handle this in 4 parts */ + /* FBs */ + if (card_res->count_fbs >= fb_count) { + copied = 0; + fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; + list_for_each_entry(fb, &file_priv->fbs, head) { + if (put_user(fb->base.id, fb_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + card_res->count_fbs = fb_count; + + /* CRTCs */ + if (card_res->count_crtcs >= crtc_count) { + copied = 0; + crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, + head) { + DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); + if (put_user(crtc->base.id, crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = 0; i < mode_group->num_crtcs; i++) { + if (put_user(mode_group->id_list[i], + crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + card_res->count_crtcs = crtc_count; + + /* Encoders */ + if (card_res->count_encoders >= encoder_count) { + copied = 0; + encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(encoder, + &dev->mode_config.encoder_list, + head) { + DRM_DEBUG("ENCODER ID is %d\n", + encoder->base.id); + if (put_user(encoder->base.id, encoder_id + + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { + if (put_user(mode_group->id_list[i], + encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + + } + } + card_res->count_encoders = encoder_count; + + /* Connectors */ + if (card_res->count_connectors >= connector_count) { + copied = 0; + connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + DRM_DEBUG("CONNECTOR ID is %d\n", + connector->base.id); + if (put_user(connector->base.id, + connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + int start = mode_group->num_crtcs + + mode_group->num_encoders; + for (i = start; i < start + mode_group->num_connectors; i++) { + if (put_user(mode_group->id_list[i], + connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + card_res->count_connectors = connector_count; + + DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, + card_res->count_connectors, card_res->count_encoders); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_getcrtc - get CRTC configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Construct a CRTC configuration structure to return to the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_getcrtc(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc *crtc_resp = data; + struct drm_crtc *crtc; + struct drm_mode_object *obj; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, crtc_resp->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!obj) { + ret = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + + crtc_resp->x = crtc->x; + crtc_resp->y = crtc->y; + crtc_resp->gamma_size = crtc->gamma_size; + if (crtc->fb) + crtc_resp->fb_id = crtc->fb->base.id; + else + crtc_resp->fb_id = 0; + + if (crtc->enabled) { + + drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); + crtc_resp->mode_valid = 1; + + } else { + crtc_resp->mode_valid = 0; + } + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_getconnector - get connector configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Construct a connector configuration structure to return to the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_getconnector(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_get_connector *out_resp = data; + struct drm_mode_object *obj; + struct drm_connector *connector; + struct drm_display_mode *mode; + int mode_count = 0; + int props_count = 0; + int encoders_count = 0; + int ret = 0; + int copied = 0; + int i; + struct drm_mode_modeinfo u_mode; + struct drm_mode_modeinfo __user *mode_ptr; + uint32_t __user *prop_ptr; + uint64_t __user *prop_values; + uint32_t __user *encoder_ptr; + + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); + + DRM_DEBUG("connector id %d:\n", out_resp->connector_id); + + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, out_resp->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { + ret = -EINVAL; + goto out; + } + connector = obj_to_connector(obj); + + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] != 0) { + props_count++; + } + } + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] != 0) { + encoders_count++; + } + } + + if (out_resp->count_modes == 0) { + connector->funcs->fill_modes(connector, + dev->mode_config.max_width, + dev->mode_config.max_height); + } + + /* delayed so we get modes regardless of pre-fill_modes state */ + list_for_each_entry(mode, &connector->modes, head) + mode_count++; + + out_resp->connector_id = connector->base.id; + out_resp->connector_type = connector->connector_type; + out_resp->connector_type_id = connector->connector_type_id; + out_resp->mm_width = connector->display_info.width_mm; + out_resp->mm_height = connector->display_info.height_mm; + out_resp->subpixel = connector->display_info.subpixel_order; + out_resp->connection = connector->status; + if (connector->encoder) + out_resp->encoder_id = connector->encoder->base.id; + else + out_resp->encoder_id = 0; + + /* + * This ioctl is called twice, once to determine how much space is + * needed, and the 2nd time to fill it. + */ + if ((out_resp->count_modes >= mode_count) && mode_count) { + copied = 0; + mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; + list_for_each_entry(mode, &connector->modes, head) { + drm_crtc_convert_to_umode(&u_mode, mode); + if (copy_to_user(mode_ptr + copied, + &u_mode, sizeof(u_mode))) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + out_resp->count_modes = mode_count; + + if ((out_resp->count_props >= props_count) && props_count) { + copied = 0; + prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); + prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] != 0) { + if (put_user(connector->property_ids[i], + prop_ptr + copied)) { + ret = -EFAULT; + goto out; + } + + if (put_user(connector->property_values[i], + prop_values + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + out_resp->count_props = props_count; + + if ((out_resp->count_encoders >= encoders_count) && encoders_count) { + copied = 0; + encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] != 0) { + if (put_user(connector->encoder_ids[i], + encoder_ptr + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + out_resp->count_encoders = encoders_count; + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_getencoder(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_get_encoder *enc_resp = data; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, enc_resp->encoder_id, + DRM_MODE_OBJECT_ENCODER); + if (!obj) { + ret = -EINVAL; + goto out; + } + encoder = obj_to_encoder(obj); + + if (encoder->crtc) + enc_resp->crtc_id = encoder->crtc->base.id; + else + enc_resp->crtc_id = 0; + enc_resp->encoder_type = encoder->encoder_type; + enc_resp->encoder_id = encoder->base.id; + enc_resp->possible_crtcs = encoder->possible_crtcs; + enc_resp->possible_clones = encoder->possible_clones; + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_setcrtc - set CRTC configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Build a new CRTC configuration based on user request. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_setcrtc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_config *config = &dev->mode_config; + struct drm_mode_crtc *crtc_req = data; + struct drm_mode_object *obj; + struct drm_crtc *crtc, *crtcfb; + struct drm_connector **connector_set = NULL, *connector; + struct drm_framebuffer *fb = NULL; + struct drm_display_mode *mode = NULL; + struct drm_mode_set set; + uint32_t __user *set_connectors_ptr; + int ret = 0; + int i; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_req->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id); + ret = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + + if (crtc_req->mode_valid) { + /* If we have a mode we need a framebuffer. */ + /* If we pass -1, set the mode with the currently bound fb */ + if (crtc_req->fb_id == -1) { + list_for_each_entry(crtcfb, + &dev->mode_config.crtc_list, head) { + if (crtcfb == crtc) { + DRM_DEBUG("Using current fb for setmode\n"); + fb = crtc->fb; + } + } + } else { + obj = drm_mode_object_find(dev, crtc_req->fb_id, + DRM_MODE_OBJECT_FB); + if (!obj) { + DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); + ret = -EINVAL; + goto out; + } + fb = obj_to_fb(obj); + } + + mode = drm_mode_create(dev); + drm_crtc_convert_umode(mode, &crtc_req->mode); + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + } + + if (crtc_req->count_connectors == 0 && mode) { + DRM_DEBUG("Count connectors is 0 but mode set\n"); + ret = -EINVAL; + goto out; + } + + if (crtc_req->count_connectors > 0 && !mode && !fb) { + DRM_DEBUG("Count connectors is %d but no mode or fb set\n", + crtc_req->count_connectors); + ret = -EINVAL; + goto out; + } + + if (crtc_req->count_connectors > 0) { + u32 out_id; + + /* Avoid unbounded kernel memory allocation */ + if (crtc_req->count_connectors > config->num_connector) { + ret = -EINVAL; + goto out; + } + + connector_set = kmalloc(crtc_req->count_connectors * + sizeof(struct drm_connector *), + GFP_KERNEL); + if (!connector_set) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < crtc_req->count_connectors; i++) { + set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; + if (get_user(out_id, &set_connectors_ptr[i])) { + ret = -EFAULT; + goto out; + } + + obj = drm_mode_object_find(dev, out_id, + DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { + DRM_DEBUG("Connector id %d unknown\n", out_id); + ret = -EINVAL; + goto out; + } + connector = obj_to_connector(obj); + + connector_set[i] = connector; + } + } + + set.crtc = crtc; + set.x = crtc_req->x; + set.y = crtc_req->y; + set.mode = mode; + set.connectors = connector_set; + set.num_connectors = crtc_req->count_connectors; + set.fb =fb; + ret = crtc->funcs->set_config(&set); + +out: + kfree(connector_set); + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_cursor_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor *req = data; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + int ret = 0; + + DRM_DEBUG("\n"); + + if (!req->flags) { + DRM_ERROR("no operation set\n"); + return -EINVAL; + } + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc_id); + ret = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + + if (req->flags & DRM_MODE_CURSOR_BO) { + if (!crtc->funcs->cursor_set) { + DRM_ERROR("crtc does not support cursor\n"); + ret = -ENXIO; + goto out; + } + /* Turns off the cursor if handle is 0 */ + ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, + req->width, req->height); + } + + if (req->flags & DRM_MODE_CURSOR_MOVE) { + if (crtc->funcs->cursor_move) { + ret = crtc->funcs->cursor_move(crtc, req->x, req->y); + } else { + DRM_ERROR("crtc does not support cursor\n"); + ret = -EFAULT; + goto out; + } + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_addfb - add an FB to the graphics configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Takes mode config lock. + * + * Add a new FB to the specified CRTC, given a user request. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_addfb(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_fb_cmd *r = data; + struct drm_mode_config *config = &dev->mode_config; + struct drm_framebuffer *fb; + int ret = 0; + + if ((config->min_width > r->width) || (r->width > config->max_width)) { + DRM_ERROR("mode new framebuffer width not within limits\n"); + return -EINVAL; + } + if ((config->min_height > r->height) || (r->height > config->max_height)) { + DRM_ERROR("mode new framebuffer height not within limits\n"); + return -EINVAL; + } + + mutex_lock(&dev->mode_config.mutex); + + /* TODO check buffer is sufficently large */ + /* TODO setup destructor callback */ + + fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); + if (!fb) { + DRM_ERROR("could not create framebuffer\n"); + ret = -EINVAL; + goto out; + } + + r->fb_id = fb->base.id; + list_add(&fb->filp_head, &file_priv->fbs); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_rmfb - remove an FB from the configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Takes mode config lock. + * + * Remove the FB specified by the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_rmfb(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_object *obj; + struct drm_framebuffer *fb = NULL; + struct drm_framebuffer *fbl = NULL; + uint32_t *id = data; + int ret = 0; + int found = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); + /* TODO check that we realy get a framebuffer back. */ + if (!obj) { + DRM_ERROR("mode invalid framebuffer id\n"); + ret = -EINVAL; + goto out; + } + fb = obj_to_fb(obj); + + list_for_each_entry(fbl, &file_priv->fbs, filp_head) + if (fb == fbl) + found = 1; + + if (!found) { + DRM_ERROR("tried to remove a fb that we didn't own\n"); + ret = -EINVAL; + goto out; + } + + /* TODO release all crtc connected to the framebuffer */ + /* TODO unhock the destructor from the buffer object */ + + list_del(&fb->filp_head); + fb->funcs->destroy(fb); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_getfb - get FB info + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Lookup the FB given its ID and return info about it. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_getfb(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_fb_cmd *r = data; + struct drm_mode_object *obj; + struct drm_framebuffer *fb; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) { + DRM_ERROR("invalid framebuffer id\n"); + ret = -EINVAL; + goto out; + } + fb = obj_to_fb(obj); + + r->height = fb->height; + r->width = fb->width; + r->depth = fb->depth; + r->bpp = fb->bits_per_pixel; + r->pitch = fb->pitch; + fb->funcs->create_handle(fb, file_priv, &r->handle); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_fb_release - remove and free the FBs on this file + * @filp: file * from the ioctl + * + * LOCKING: + * Takes mode config lock. + * + * Destroy all the FBs associated with @filp. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +void drm_fb_release(struct file *filp) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_framebuffer *fb, *tfb; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { + list_del(&fb->filp_head); + fb->funcs->destroy(fb); + } + mutex_unlock(&dev->mode_config.mutex); +} + +/** + * drm_mode_attachmode - add a mode to the user mode list + * @dev: DRM device + * @connector: connector to add the mode to + * @mode: mode to add + * + * Add @mode to @connector's user mode list. + */ +static int drm_mode_attachmode(struct drm_device *dev, + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int ret = 0; + + list_add_tail(&mode->head, &connector->user_modes); + return ret; +} + +int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_connector *connector; + int ret = 0; + struct drm_display_mode *dup_mode; + int need_dup = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (!connector->encoder) + break; + if (connector->encoder->crtc == crtc) { + if (need_dup) + dup_mode = drm_mode_duplicate(dev, mode); + else + dup_mode = mode; + ret = drm_mode_attachmode(dev, connector, dup_mode); + if (ret) + return ret; + need_dup = 1; + } + } + return 0; +} +EXPORT_SYMBOL(drm_mode_attachmode_crtc); + +static int drm_mode_detachmode(struct drm_device *dev, + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int found = 0; + int ret = 0; + struct drm_display_mode *match_mode, *t; + + list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { + if (drm_mode_equal(match_mode, mode)) { + list_del(&match_mode->head); + drm_mode_destroy(dev, match_mode); + found = 1; + break; + } + } + + if (!found) + ret = -EINVAL; + + return ret; +} + +int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_mode_detachmode(dev, connector, mode); + } + return 0; +} +EXPORT_SYMBOL(drm_mode_detachmode_crtc); + +/** + * drm_fb_attachmode - Attach a user mode to an connector + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * This attaches a user specified mode to an connector. + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_attachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_mode_cmd *mode_cmd = data; + struct drm_connector *connector; + struct drm_display_mode *mode; + struct drm_mode_object *obj; + struct drm_mode_modeinfo *umode = &mode_cmd->mode; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { + ret = -EINVAL; + goto out; + } + connector = obj_to_connector(obj); + + mode = drm_mode_create(dev); + if (!mode) { + ret = -ENOMEM; + goto out; + } + + drm_crtc_convert_umode(mode, umode); + + ret = drm_mode_attachmode(dev, connector, mode); +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + + +/** + * drm_fb_detachmode - Detach a user specified mode from an connector + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_detachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_object *obj; + struct drm_mode_mode_cmd *mode_cmd = data; + struct drm_connector *connector; + struct drm_display_mode mode; + struct drm_mode_modeinfo *umode = &mode_cmd->mode; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { + ret = -EINVAL; + goto out; + } + connector = obj_to_connector(obj); + + drm_crtc_convert_umode(&mode, umode); + ret = drm_mode_detachmode(dev, connector, &mode); +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +struct drm_property *drm_property_create(struct drm_device *dev, int flags, + const char *name, int num_values) +{ + struct drm_property *property = NULL; + + property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); + if (!property) + return NULL; + + if (num_values) { + property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); + if (!property->values) + goto fail; + } + + drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); + property->flags = flags; + property->num_values = num_values; + INIT_LIST_HEAD(&property->enum_blob_list); + + if (name) + strncpy(property->name, name, DRM_PROP_NAME_LEN); + + list_add_tail(&property->head, &dev->mode_config.property_list); + return property; +fail: + kfree(property); + return NULL; +} +EXPORT_SYMBOL(drm_property_create); + +int drm_property_add_enum(struct drm_property *property, int index, + uint64_t value, const char *name) +{ + struct drm_property_enum *prop_enum; + + if (!(property->flags & DRM_MODE_PROP_ENUM)) + return -EINVAL; + + if (!list_empty(&property->enum_blob_list)) { + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { + if (prop_enum->value == value) { + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; + return 0; + } + } + } + + prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); + if (!prop_enum) + return -ENOMEM; + + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; + prop_enum->value = value; + + property->values[index] = value; + list_add_tail(&prop_enum->head, &property->enum_blob_list); + return 0; +} +EXPORT_SYMBOL(drm_property_add_enum); + +void drm_property_destroy(struct drm_device *dev, struct drm_property *property) +{ + struct drm_property_enum *prop_enum, *pt; + + list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { + list_del(&prop_enum->head); + kfree(prop_enum); + } + + if (property->num_values) + kfree(property->values); + drm_mode_object_put(dev, &property->base); + list_del(&property->head); + kfree(property); +} +EXPORT_SYMBOL(drm_property_destroy); + +int drm_connector_attach_property(struct drm_connector *connector, + struct drm_property *property, uint64_t init_val) +{ + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == 0) { + connector->property_ids[i] = property->base.id; + connector->property_values[i] = init_val; + break; + } + } + + if (i == DRM_CONNECTOR_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_property); + +int drm_connector_property_set_value(struct drm_connector *connector, + struct drm_property *property, uint64_t value) +{ + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == property->base.id) { + connector->property_values[i] = value; + break; + } + } + + if (i == DRM_CONNECTOR_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_connector_property_set_value); + +int drm_connector_property_get_value(struct drm_connector *connector, + struct drm_property *property, uint64_t *val) +{ + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == property->base.id) { + *val = connector->property_values[i]; + break; + } + } + + if (i == DRM_CONNECTOR_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_connector_property_get_value); + +int drm_mode_getproperty_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_object *obj; + struct drm_mode_get_property *out_resp = data; + struct drm_property *property; + int enum_count = 0; + int blob_count = 0; + int value_count = 0; + int ret = 0, i; + int copied; + struct drm_property_enum *prop_enum; + struct drm_mode_property_enum __user *enum_ptr; + struct drm_property_blob *prop_blob; + uint32_t *blob_id_ptr; + uint64_t __user *values_ptr; + uint32_t __user *blob_length_ptr; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); + if (!obj) { + ret = -EINVAL; + goto done; + } + property = obj_to_property(obj); + + if (property->flags & DRM_MODE_PROP_ENUM) { + list_for_each_entry(prop_enum, &property->enum_blob_list, head) + enum_count++; + } else if (property->flags & DRM_MODE_PROP_BLOB) { + list_for_each_entry(prop_blob, &property->enum_blob_list, head) + blob_count++; + } + + value_count = property->num_values; + + strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); + out_resp->name[DRM_PROP_NAME_LEN-1] = 0; + out_resp->flags = property->flags; + + if ((out_resp->count_values >= value_count) && value_count) { + values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; + for (i = 0; i < value_count; i++) { + if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { + ret = -EFAULT; + goto done; + } + } + } + out_resp->count_values = value_count; + + if (property->flags & DRM_MODE_PROP_ENUM) { + if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { + copied = 0; + enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { + + if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { + ret = -EFAULT; + goto done; + } + + if (copy_to_user(&enum_ptr[copied].name, + &prop_enum->name, DRM_PROP_NAME_LEN)) { + ret = -EFAULT; + goto done; + } + copied++; + } + } + out_resp->count_enum_blobs = enum_count; + } + + if (property->flags & DRM_MODE_PROP_BLOB) { + if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { + copied = 0; + blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; + blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; + + list_for_each_entry(prop_blob, &property->enum_blob_list, head) { + if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { + ret = -EFAULT; + goto done; + } + + if (put_user(prop_blob->length, blob_length_ptr + copied)) { + ret = -EFAULT; + goto done; + } + + copied++; + } + } + out_resp->count_enum_blobs = blob_count; + } +done: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, + void *data) +{ + struct drm_property_blob *blob; + + if (!length || !data) + return NULL; + + blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); + if (!blob) + return NULL; + + blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); + blob->length = length; + + memcpy(blob->data, data, length); + + drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); + + list_add_tail(&blob->head, &dev->mode_config.property_blob_list); + return blob; +} + +static void drm_property_destroy_blob(struct drm_device *dev, + struct drm_property_blob *blob) +{ + drm_mode_object_put(dev, &blob->base); + list_del(&blob->head); + kfree(blob); +} + +int drm_mode_getblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_object *obj; + struct drm_mode_get_blob *out_resp = data; + struct drm_property_blob *blob; + int ret = 0; + void *blob_ptr; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); + if (!obj) { + ret = -EINVAL; + goto done; + } + blob = obj_to_blob(obj); + + if (out_resp->length == blob->length) { + blob_ptr = (void *)(unsigned long)out_resp->data; + if (copy_to_user(blob_ptr, blob->data, blob->length)){ + ret = -EFAULT; + goto done; + } + } + out_resp->length = blob->length; + +done: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_connector_update_edid_property(struct drm_connector *connector, + struct edid *edid) +{ + struct drm_device *dev = connector->dev; + int ret = 0; + + if (connector->edid_blob_ptr) + drm_property_destroy_blob(dev, connector->edid_blob_ptr); + + /* Delete edid, when there is none. */ + if (!edid) { + connector->edid_blob_ptr = NULL; + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); + return ret; + } + + connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); + + ret = drm_connector_property_set_value(connector, + dev->mode_config.edid_property, + connector->edid_blob_ptr->base.id); + + return ret; +} +EXPORT_SYMBOL(drm_mode_connector_update_edid_property); + +int drm_mode_connector_property_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_connector_set_property *out_resp = data; + struct drm_mode_object *obj; + struct drm_property *property; + struct drm_connector *connector; + int ret = -EINVAL; + int i; + + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { + goto out; + } + connector = obj_to_connector(obj); + + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == out_resp->prop_id) + break; + } + + if (i == DRM_CONNECTOR_MAX_PROPERTY) { + goto out; + } + + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); + if (!obj) { + goto out; + } + property = obj_to_property(obj); + + if (property->flags & DRM_MODE_PROP_IMMUTABLE) + goto out; + + if (property->flags & DRM_MODE_PROP_RANGE) { + if (out_resp->value < property->values[0]) + goto out; + + if (out_resp->value > property->values[1]) + goto out; + } else { + int found = 0; + for (i = 0; i < property->num_values; i++) { + if (property->values[i] == out_resp->value) { + found = 1; + break; + } + } + if (!found) { + goto out; + } + } + + if (connector->funcs->set_property) + ret = connector->funcs->set_property(connector, property, out_resp->value); + + /* store the property value if succesful */ + if (!ret) + drm_connector_property_set_value(connector, property, out_resp->value); +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_connector_attach_encoder(struct drm_connector *connector, + struct drm_encoder *encoder) +{ + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) { + connector->encoder_ids[i] = encoder->base.id; + return 0; + } + } + return -ENOMEM; +} +EXPORT_SYMBOL(drm_mode_connector_attach_encoder); + +void drm_mode_connector_detach_encoder(struct drm_connector *connector, + struct drm_encoder *encoder) +{ + int i; + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == encoder->base.id) { + connector->encoder_ids[i] = 0; + if (connector->encoder == encoder) + connector->encoder = NULL; + break; + } + } +} +EXPORT_SYMBOL(drm_mode_connector_detach_encoder); + +bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, + int gamma_size) +{ + crtc->gamma_size = gamma_size; + + crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); + if (!crtc->gamma_store) { + crtc->gamma_size = 0; + return false; + } + + return true; +} +EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); + +int drm_mode_gamma_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + void *r_base, *g_base, *b_base; + int size; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + ret = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + + /* memcpy into gamma store */ + if (crtc_lut->gamma_size != crtc->gamma_size) { + ret = -EINVAL; + goto out; + } + + size = crtc_lut->gamma_size * (sizeof(uint16_t)); + r_base = crtc->gamma_store; + if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) { + ret = -EFAULT; + goto out; + } + + g_base = r_base + size; + if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) { + ret = -EFAULT; + goto out; + } + + b_base = g_base + size; + if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) { + ret = -EFAULT; + goto out; + } + + crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; + +} + +int drm_mode_gamma_get_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + void *r_base, *g_base, *b_base; + int size; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + ret = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + + /* memcpy into gamma store */ + if (crtc_lut->gamma_size != crtc->gamma_size) { + ret = -EINVAL; + goto out; + } + + size = crtc_lut->gamma_size * (sizeof(uint16_t)); + r_base = crtc->gamma_store; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { + ret = -EFAULT; + goto out; + } + + g_base = r_base + size; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) { + ret = -EFAULT; + goto out; + } + + b_base = g_base + size; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) { + ret = -EFAULT; + goto out; + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c new file mode 100644 index 000000000000..d8a982b71296 --- /dev/null +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -0,0 +1,826 @@ +/* + * Copyright (c) 2006-2008 Intel Corporation + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Keith Packard + * Eric Anholt <eric@anholt.net> + * Dave Airlie <airlied@linux.ie> + * Jesse Barnes <jesse.barnes@intel.com> + */ + +#include "drmP.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + +/* + * Detailed mode info for 800x600@60Hz + */ +static struct drm_display_mode std_mode[] = { + { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, + 968, 1056, 0, 600, 601, 605, 628, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, +}; + +/** + * drm_helper_probe_connector_modes - get complete set of display modes + * @dev: DRM device + * @maxX: max width for modes + * @maxY: max height for modes + * + * LOCKING: + * Caller must hold mode config lock. + * + * 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 used either at bootup time or when major configuration + * changes have occurred. + * + * FIXME: take into account monitor limits + */ +void drm_helper_probe_single_connector_modes(struct drm_connector *connector, + uint32_t maxX, uint32_t maxY) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode, *t; + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + int ret; + + DRM_DEBUG("%s\n", drm_get_connector_name(connector)); + /* set all modes to the unverified state */ + list_for_each_entry_safe(mode, t, &connector->modes, head) + mode->status = MODE_UNVERIFIED; + + connector->status = connector->funcs->detect(connector); + + if (connector->status == connector_status_disconnected) { + DRM_DEBUG("%s is disconnected\n", + drm_get_connector_name(connector)); + /* TODO set EDID to NULL */ + return; + } + + ret = (*connector_funcs->get_modes)(connector); + + if (ret) { + drm_mode_connector_list_update(connector); + } + + if (maxX && maxY) + drm_mode_validate_size(dev, &connector->modes, maxX, + maxY, 0); + list_for_each_entry_safe(mode, t, &connector->modes, head) { + if (mode->status == MODE_OK) + mode->status = connector_funcs->mode_valid(connector, + mode); + } + + + drm_mode_prune_invalid(dev, &connector->modes, true); + + if (list_empty(&connector->modes)) { + struct drm_display_mode *stdmode; + + DRM_DEBUG("No valid modes on %s\n", + drm_get_connector_name(connector)); + + /* Should we do this here ??? + * When no valid EDID modes are available we end up + * here and bailed in the past, now we add a standard + * 640x480@60Hz mode and carry on. + */ + stdmode = drm_mode_duplicate(dev, &std_mode[0]); + drm_mode_probed_add(connector, stdmode); + drm_mode_list_concat(&connector->probed_modes, + &connector->modes); + + DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", + drm_get_connector_name(connector)); + } + + drm_mode_sort(&connector->modes); + + DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); + list_for_each_entry_safe(mode, t, &connector->modes, head) { + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(mode); + } +} +EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); + +void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, + uint32_t maxY) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_probe_single_connector_modes(connector, maxX, maxY); + } +} +EXPORT_SYMBOL(drm_helper_probe_connector_modes); + + +/** + * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config + * @crtc: CRTC to check + * + * LOCKING: + * Caller must hold mode config lock. + * + * Walk @crtc's DRM device's mode_config and see if it's in use. + * + * RETURNS: + * True if @crtc is part of the mode_config, false otherwise. + */ +bool drm_helper_crtc_in_use(struct drm_crtc *crtc) +{ + struct drm_encoder *encoder; + struct drm_device *dev = crtc->dev; + /* FIXME: Locking around list access? */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + if (encoder->crtc == crtc) + return true; + return false; +} +EXPORT_SYMBOL(drm_helper_crtc_in_use); + +/** + * drm_disable_unused_functions - disable unused objects + * @dev: DRM device + * + * LOCKING: + * Caller must hold mode config lock. + * + * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled + * by calling its dpms function, which should power it off. + */ +void drm_helper_disable_unused_functions(struct drm_device *dev) +{ + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_crtc *crtc; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + encoder_funcs = encoder->helper_private; + if (!encoder->crtc) + (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc->enabled = drm_helper_crtc_in_use(crtc); + if (!crtc->enabled) { + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + crtc->fb = NULL; + } + } +} +EXPORT_SYMBOL(drm_helper_disable_unused_functions); + +static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) +{ + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->modes, head) { + if (drm_mode_width(mode) > width || + drm_mode_height(mode) > height) + continue; + if (mode->type & DRM_MODE_TYPE_PREFERRED) + return mode; + } + return NULL; +} + +static bool drm_connector_enabled(struct drm_connector *connector, bool strict) +{ + bool enable; + + if (strict) { + enable = connector->status == connector_status_connected; + } else { + enable = connector->status != connector_status_disconnected; + } + return enable; +} + +static void drm_enable_connectors(struct drm_device *dev, bool *enabled) +{ + bool any_enabled = false; + struct drm_connector *connector; + int i = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + enabled[i] = drm_connector_enabled(connector, true); + any_enabled |= enabled[i]; + i++; + } + + if (any_enabled) + return; + + i = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + enabled[i] = drm_connector_enabled(connector, false); + i++; + } +} + +static bool drm_target_preferred(struct drm_device *dev, + struct drm_display_mode **modes, + bool *enabled, int width, int height) +{ + struct drm_connector *connector; + int i = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + if (enabled[i] == false) { + i++; + continue; + } + + modes[i] = drm_has_preferred_mode(connector, width, height); + if (!modes[i]) { + list_for_each_entry(modes[i], &connector->modes, head) + break; + } + i++; + } + return true; +} + +static int drm_pick_crtcs(struct drm_device *dev, + struct drm_crtc **best_crtcs, + struct drm_display_mode **modes, + int n, int width, int height) +{ + int c, o; + struct drm_connector *connector; + struct drm_connector_helper_funcs *connector_funcs; + struct drm_encoder *encoder; + struct drm_crtc *best_crtc; + int my_score, best_score, score; + struct drm_crtc **crtcs, *crtc; + + if (n == dev->mode_config.num_connector) + return 0; + c = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (c == n) + break; + c++; + } + + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height); + if (modes[n] == NULL) + return best_score; + + crtcs = kmalloc(dev->mode_config.num_connector * + sizeof(struct drm_crtc *), GFP_KERNEL); + if (!crtcs) + return best_score; + + my_score = 1; + if (connector->status == connector_status_connected) + my_score++; + if (drm_has_preferred_mode(connector, width, height)) + my_score++; + + connector_funcs = connector->helper_private; + encoder = connector_funcs->best_encoder(connector); + if (!encoder) + goto out; + + connector->encoder = encoder; + + /* select a crtc for this connector and then attempt to configure + remaining connectors */ + c = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + if ((connector->encoder->possible_crtcs & (1 << c)) == 0) { + c++; + continue; + } + + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + + if (o < n) { + /* ignore cloning for now */ + c++; + continue; + } + + crtcs[n] = crtc; + memcpy(crtcs, best_crtcs, n * sizeof(struct drm_crtc *)); + score = my_score + drm_pick_crtcs(dev, crtcs, modes, n + 1, + width, height); + if (score > best_score) { + best_crtc = crtc; + best_score = score; + memcpy(best_crtcs, crtcs, + dev->mode_config.num_connector * + sizeof(struct drm_crtc *)); + } + c++; + } +out: + kfree(crtcs); + return best_score; +} + +static void drm_setup_crtcs(struct drm_device *dev) +{ + struct drm_crtc **crtcs; + struct drm_display_mode **modes; + struct drm_encoder *encoder; + struct drm_connector *connector; + bool *enabled; + int width, height; + int i, ret; + + width = dev->mode_config.max_width; + height = dev->mode_config.max_height; + + /* clean out all the encoder/crtc combos */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + encoder->crtc = NULL; + } + + crtcs = kcalloc(dev->mode_config.num_connector, + sizeof(struct drm_crtc *), GFP_KERNEL); + modes = kcalloc(dev->mode_config.num_connector, + sizeof(struct drm_display_mode *), GFP_KERNEL); + enabled = kcalloc(dev->mode_config.num_connector, + sizeof(bool), GFP_KERNEL); + + drm_enable_connectors(dev, enabled); + + ret = drm_target_preferred(dev, modes, enabled, width, height); + if (!ret) + DRM_ERROR("Unable to find initial modes\n"); + + drm_pick_crtcs(dev, crtcs, modes, 0, width, height); + + i = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct drm_display_mode *mode = modes[i]; + struct drm_crtc *crtc = crtcs[i]; + + if (connector->encoder == NULL) { + i++; + continue; + } + + if (mode && crtc) { + crtc->desired_mode = mode; + connector->encoder->crtc = crtc; + } else + connector->encoder->crtc = NULL; + i++; + } + + kfree(crtcs); + kfree(modes); + kfree(enabled); +} +/** + * drm_crtc_set_mode - set a mode + * @crtc: CRTC to program + * @mode: mode to use + * @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. + * + * RETURNS: + * True if the mode was set successfully, or false otherwise. + */ +bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, + struct drm_display_mode *mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_display_mode *adjusted_mode, saved_mode; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + struct drm_encoder_helper_funcs *encoder_funcs; + int saved_x, saved_y; + struct drm_encoder *encoder; + bool ret = true; + + adjusted_mode = drm_mode_duplicate(dev, mode); + + crtc->enabled = drm_helper_crtc_in_use(crtc); + + if (!crtc->enabled) + return true; + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + + /* Update crtc values up front so the driver can rely on them for mode + * setting. + */ + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + + if (drm_mode_equal(&saved_mode, &crtc->mode)) { + if (saved_x != crtc->x || saved_y != crtc->y) { + crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, + old_fb); + goto done; + } + } + + /* Pass our mode to the connectors and the CRTC to give them a chance to + * adjust it according to limitations or connector properties, and also + * a chance to reject the mode entirely. + */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if (encoder->crtc != crtc) + continue; + encoder_funcs = encoder->helper_private; + if (!(ret = encoder_funcs->mode_fixup(encoder, mode, + adjusted_mode))) { + goto done; + } + } + + if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { + goto done; + } + + /* Prepare the encoders and CRTCs before setting the mode. */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if (encoder->crtc != crtc) + continue; + encoder_funcs = encoder->helper_private; + /* Disable the encoders as the first thing we do. */ + encoder_funcs->prepare(encoder); + } + + crtc_funcs->prepare(crtc); + + /* Set up the DPLL and any encoders state that needs to adjust or depend + * on the DPLL. + */ + crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if (encoder->crtc != crtc) + continue; + + DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), + mode->name, mode->base.id); + encoder_funcs = encoder->helper_private; + encoder_funcs->mode_set(encoder, mode, adjusted_mode); + } + + /* Now enable the clocks, plane, pipe, and connectors that we set up. */ + crtc_funcs->commit(crtc); + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if (encoder->crtc != crtc) + continue; + + encoder_funcs = encoder->helper_private; + encoder_funcs->commit(encoder); + + } + + /* XXX free adjustedmode */ + drm_mode_destroy(dev, adjusted_mode); + /* FIXME: add subpixel order */ +done: + if (!ret) { + crtc->mode = saved_mode; + crtc->x = saved_x; + crtc->y = saved_y; + } + + return ret; +} +EXPORT_SYMBOL(drm_crtc_helper_set_mode); + + +/** + * drm_crtc_helper_set_config - set a new config from userspace + * @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 user in @crtc_info, and enable + * it. + * + * RETURNS: + * Zero. (FIXME) + */ +int drm_crtc_helper_set_config(struct drm_mode_set *set) +{ + struct drm_device *dev; + struct drm_crtc **save_crtcs, *new_crtc; + struct drm_encoder **save_encoders, *new_encoder; + struct drm_framebuffer *old_fb; + bool save_enabled; + bool changed = false; + bool flip_or_move = false; + struct drm_connector *connector; + int count = 0, ro, fail = 0; + struct drm_crtc_helper_funcs *crtc_funcs; + int ret = 0; + + DRM_DEBUG("\n"); + + if (!set) + return -EINVAL; + + if (!set->crtc) + return -EINVAL; + + if (!set->crtc->helper_private) + return -EINVAL; + + crtc_funcs = set->crtc->helper_private; + + DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n", + set->crtc, set->crtc->base.id, set->fb, set->connectors, + (int)set->num_connectors, set->x, set->y); + + dev = set->crtc->dev; + + /* save previous config */ + save_enabled = set->crtc->enabled; + + /* this is meant to be num_connector not num_crtc */ + save_crtcs = kzalloc(dev->mode_config.num_connector * + sizeof(struct drm_crtc *), GFP_KERNEL); + if (!save_crtcs) + return -ENOMEM; + + save_encoders = kzalloc(dev->mode_config.num_connector * + sizeof(struct drm_encoders *), GFP_KERNEL); + if (!save_encoders) { + kfree(save_crtcs); + return -ENOMEM; + } + + /* We should be able to check here if the fb has the same properties + * and then just flip_or_move it */ + if (set->crtc->fb != set->fb) { + /* if we have no fb then its a change not a flip */ + if (set->crtc->fb == NULL) + changed = true; + else + flip_or_move = true; + } + + if (set->x != set->crtc->x || set->y != set->crtc->y) + flip_or_move = true; + + if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { + DRM_DEBUG("modes are different\n"); + drm_mode_debug_printmodeline(&set->crtc->mode); + drm_mode_debug_printmodeline(set->mode); + changed = true; + } + + /* a) traverse passed in connector list and get encoders for them */ + count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + save_encoders[count++] = connector->encoder; + new_encoder = connector->encoder; + for (ro = 0; ro < set->num_connectors; ro++) { + if (set->connectors[ro] == connector) { + new_encoder = connector_funcs->best_encoder(connector); + /* if we can't get an encoder for a connector + we are setting now - then fail */ + if (new_encoder == NULL) + /* don't break so fail path works correct */ + fail = 1; + break; + } + } + + if (new_encoder != connector->encoder) { + changed = true; + connector->encoder = new_encoder; + } + } + + if (fail) { + ret = -EINVAL; + goto fail_no_encoder; + } + + count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (!connector->encoder) + continue; + + save_crtcs[count++] = connector->encoder->crtc; + + if (connector->encoder->crtc == set->crtc) + new_crtc = NULL; + else + new_crtc = connector->encoder->crtc; + + for (ro = 0; ro < set->num_connectors; ro++) { + if (set->connectors[ro] == connector) + new_crtc = set->crtc; + } + if (new_crtc != connector->encoder->crtc) { + changed = true; + connector->encoder->crtc = new_crtc; + } + } + + /* mode_set_base is not a required function */ + if (flip_or_move && !crtc_funcs->mode_set_base) + changed = true; + + if (changed) { + old_fb = set->crtc->fb; + set->crtc->fb = set->fb; + set->crtc->enabled = (set->mode != NULL); + if (set->mode != NULL) { + DRM_DEBUG("attempting to set mode from userspace\n"); + drm_mode_debug_printmodeline(set->mode); + if (!drm_crtc_helper_set_mode(set->crtc, set->mode, + set->x, set->y, + old_fb)) { + ret = -EINVAL; + goto fail_set_mode; + } + /* TODO are these needed? */ + set->crtc->desired_x = set->x; + set->crtc->desired_y = set->y; + set->crtc->desired_mode = set->mode; + } + drm_helper_disable_unused_functions(dev); + } else if (flip_or_move) { + old_fb = set->crtc->fb; + if (set->crtc->fb != set->fb) + set->crtc->fb = set->fb; + crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); + } + + kfree(save_encoders); + kfree(save_crtcs); + return 0; + +fail_set_mode: + set->crtc->enabled = save_enabled; + count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + connector->encoder->crtc = save_crtcs[count++]; +fail_no_encoder: + kfree(save_crtcs); + count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + connector->encoder = save_encoders[count++]; + } + kfree(save_encoders); + return ret; +} +EXPORT_SYMBOL(drm_crtc_helper_set_config); + +bool drm_helper_plugged_event(struct drm_device *dev) +{ + DRM_DEBUG("\n"); + + drm_helper_probe_connector_modes(dev, dev->mode_config.max_width, + dev->mode_config.max_height); + + drm_setup_crtcs(dev); + + /* alert the driver fb layer */ + dev->mode_config.funcs->fb_changed(dev); + + /* FIXME: send hotplug event */ + return true; +} +/** + * drm_initial_config - setup a sane initial connector configuration + * @dev: DRM device + * @can_grow: this configuration is growable + * + * LOCKING: + * Called at init time, must take mode config lock. + * + * 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. + * + * RETURNS: + * Zero if everything went ok, nonzero otherwise. + */ +bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) +{ + int ret = false; + + drm_helper_plugged_event(dev); + return ret; +} +EXPORT_SYMBOL(drm_helper_initial_config); + +/** + * drm_hotplug_stage_two + * @dev DRM device + * @connector hotpluged connector + * + * LOCKING. + * Caller must hold mode config lock, function might grab struct lock. + * + * Stage two of a hotplug. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_helper_hotplug_stage_two(struct drm_device *dev) +{ + drm_helper_plugged_event(dev); + + return 0; +} +EXPORT_SYMBOL(drm_helper_hotplug_stage_two); + +int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, + struct drm_mode_fb_cmd *mode_cmd) +{ + fb->width = mode_cmd->width; + fb->height = mode_cmd->height; + fb->pitch = mode_cmd->pitch; + fb->bits_per_pixel = mode_cmd->bpp; + fb->depth = mode_cmd->depth; + + return 0; +} +EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); + +int drm_helper_resume_force_mode(struct drm_device *dev) +{ + struct drm_crtc *crtc; + int ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + if (!crtc->enabled) + continue; + + ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, crtc->fb); + + if (ret == false) + DRM_ERROR("failed to set mode on crtc %p\n", crtc); + } + return 0; +} +EXPORT_SYMBOL(drm_helper_resume_force_mode); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 996097acb5e7..febb517ee679 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -74,6 +74,9 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -123,6 +126,23 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) @@ -138,8 +158,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { */ int drm_lastclose(struct drm_device * dev) { - struct drm_magic_entry *pt, *next; - struct drm_map_list *r_list, *list_t; struct drm_vma_entry *vma, *vma_temp; int i; @@ -149,13 +167,7 @@ int drm_lastclose(struct drm_device * dev) dev->driver->lastclose(dev); DRM_DEBUG("driver lastclose completed\n"); - if (dev->unique) { - drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); - dev->unique = NULL; - dev->unique_len = 0; - } - - if (dev->irq_enabled) + if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) drm_irq_uninstall(dev); mutex_lock(&dev->struct_mutex); @@ -164,18 +176,9 @@ int drm_lastclose(struct drm_device * dev) drm_drawable_free_all(dev); del_timer(&dev->timer); - /* Clear pid list */ - if (dev->magicfree.next) { - list_for_each_entry_safe(pt, next, &dev->magicfree, head) { - list_del(&pt->head); - drm_ht_remove_item(&dev->magiclist, &pt->hash_item); - drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); - } - drm_ht_remove(&dev->magiclist); - } - /* Clear AGP information */ - if (drm_core_has_AGP(dev) && dev->agp) { + if (drm_core_has_AGP(dev) && dev->agp && + !drm_core_check_feature(dev, DRIVER_MODESET)) { struct drm_agp_mem *entry, *tempe; /* Remove AGP resources, but leave dev->agp @@ -194,7 +197,8 @@ int drm_lastclose(struct drm_device * dev) dev->agp->acquired = 0; dev->agp->enabled = 0; } - if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { + if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg && + !drm_core_check_feature(dev, DRIVER_MODESET)) { drm_sg_cleanup(dev->sg); dev->sg = NULL; } @@ -205,13 +209,6 @@ int drm_lastclose(struct drm_device * dev) drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); } - list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { - if (!(r_list->map->flags & _DRM_DRIVER)) { - drm_rmmap_locked(dev, r_list->map); - r_list = NULL; - } - } - if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { for (i = 0; i < dev->queue_count; i++) { if (dev->queuelist[i]) { @@ -228,14 +225,11 @@ int drm_lastclose(struct drm_device * dev) } dev->queue_count = 0; - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && + !drm_core_check_feature(dev, DRIVER_MODESET)) drm_dma_takedown(dev); - if (dev->lock.hw_lock) { - dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ - dev->lock.file_priv = NULL; - wake_up_interruptible(&dev->lock.lock_queue); - } + dev->dev_mapping = NULL; mutex_unlock(&dev->struct_mutex); DRM_DEBUG("lastclose completed\n"); @@ -263,6 +257,8 @@ int drm_init(struct drm_driver *driver) DRM_DEBUG("\n"); + INIT_LIST_HEAD(&driver->device_list); + for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; @@ -329,35 +325,24 @@ static void drm_cleanup(struct drm_device * dev) drm_ht_remove(&dev->map_hash); drm_ctxbitmap_cleanup(dev); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); + + if (dev->driver->driver_features & DRIVER_GEM) + drm_gem_destroy(dev); + drm_put_minor(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } -static int drm_minors_cleanup(int id, void *ptr, void *data) -{ - struct drm_minor *minor = ptr; - struct drm_device *dev; - struct drm_driver *driver = data; - - dev = minor->dev; - if (minor->dev->driver != driver) - return 0; - - if (minor->type != DRM_MINOR_LEGACY) - return 0; - - if (dev) - pci_dev_put(dev->pdev); - drm_cleanup(dev); - return 1; -} - void drm_exit(struct drm_driver *driver) { + struct drm_device *dev, *tmp; DRM_DEBUG("\n"); - idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); + list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) + drm_cleanup(dev); DRM_INFO("Module unloaded\n"); } @@ -503,7 +488,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, retcode = -EINVAL; } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || - ((ioctl->flags & DRM_MASTER) && !file_priv->master)) { + ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) { retcode = -EACCES; } else { if (cmd & (IOC_IN | IOC_OUT)) { diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c new file mode 100644 index 000000000000..0fbb0da342cb --- /dev/null +++ b/drivers/gpu/drm/drm_edid.c @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2006 Luc Verhaegen (quirks list) + * Copyright (c) 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from + * FB layer. + * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> + * + * 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> +#include "drmP.h" +#include "drm_edid.h" + +/* + * TODO: + * - support EDID 1.4 (incl. CE blocks) + */ + +/* + * EDID blocks out in the wild have a variety of bugs, try to collect + * them here (note that userspace may work around broken monitors first, + * but fixes should make their way here so that the kernel "just works" + * on as many displays as possible). + */ + +/* First detailed mode wrong, use largest 60Hz mode */ +#define EDID_QUIRK_PREFER_LARGE_60 (1 << 0) +/* Reported 135MHz pixel clock is too high, needs adjustment */ +#define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1) +/* Prefer the largest mode at 75 Hz */ +#define EDID_QUIRK_PREFER_LARGE_75 (1 << 2) +/* Detail timing is in cm not mm */ +#define EDID_QUIRK_DETAILED_IN_CM (1 << 3) +/* Detailed timing descriptors have bogus size values, so just take the + * maximum size and use that. + */ +#define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) +/* Monitor forgot to set the first detailed is preferred bit. */ +#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) +/* use +hsync +vsync for detailed mode */ +#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) + +static struct edid_quirk { + char *vendor; + int product_id; + u32 quirks; +} edid_quirk_list[] = { + /* Acer AL1706 */ + { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, + /* Acer F51 */ + { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, + /* Unknown Acer */ + { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, + + /* Belinea 10 15 55 */ + { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, + { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, + + /* Envision Peripherals, Inc. EN-7100e */ + { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, + + /* Funai Electronics PM36B */ + { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | + EDID_QUIRK_DETAILED_IN_CM }, + + /* LG Philips LCD LP154W01-A5 */ + { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, + { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, + + /* Philips 107p5 CRT */ + { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, + + /* Proview AY765C */ + { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, + + /* Samsung SyncMaster 205BW. Note: irony */ + { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, + /* Samsung SyncMaster 22[5-6]BW */ + { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, + { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, +}; + + +/* Valid EDID header has these bytes */ +static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + +/** + * edid_is_valid - sanity check EDID data + * @edid: EDID data + * + * Sanity check the EDID block by looking at the header, the version number + * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's + * valid. + */ +static bool edid_is_valid(struct edid *edid) +{ + int i; + u8 csum = 0; + u8 *raw_edid = (u8 *)edid; + + if (memcmp(edid->header, edid_header, sizeof(edid_header))) + goto bad; + if (edid->version != 1) { + DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); + goto bad; + } + if (edid->revision <= 0 || edid->revision > 3) { + DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); + goto bad; + } + + for (i = 0; i < EDID_LENGTH; i++) + csum += raw_edid[i]; + if (csum) { + DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); + goto bad; + } + + return 1; + +bad: + if (raw_edid) { + DRM_ERROR("Raw EDID:\n"); + print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); + printk("\n"); + } + return 0; +} + +/** + * edid_vendor - match a string against EDID's obfuscated vendor field + * @edid: EDID to match + * @vendor: vendor string + * + * Returns true if @vendor is in @edid, false otherwise + */ +static bool edid_vendor(struct edid *edid, char *vendor) +{ + char edid_vendor[3]; + + edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; + edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) | + ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; + edid_vendor[2] = (edid->mfg_id[2] & 0x1f) + '@'; + + return !strncmp(edid_vendor, vendor, 3); +} + +/** + * edid_get_quirks - return quirk flags for a given EDID + * @edid: EDID to process + * + * This tells subsequent routines what fixes they need to apply. + */ +static u32 edid_get_quirks(struct edid *edid) +{ + struct edid_quirk *quirk; + int i; + + for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { + quirk = &edid_quirk_list[i]; + + if (edid_vendor(edid, quirk->vendor) && + (EDID_PRODUCT_ID(edid) == quirk->product_id)) + return quirk->quirks; + } + + return 0; +} + +#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) +#define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) + + +/** + * edid_fixup_preferred - set preferred modes based on quirk list + * @connector: has mode list to fix up + * @quirks: quirks list + * + * Walk the mode list for @connector, clearing the preferred status + * on existing modes and setting it anew for the right mode ala @quirks. + */ +static void edid_fixup_preferred(struct drm_connector *connector, + u32 quirks) +{ + struct drm_display_mode *t, *cur_mode, *preferred_mode; + int target_refresh = 0; + + if (list_empty(&connector->probed_modes)) + return; + + if (quirks & EDID_QUIRK_PREFER_LARGE_60) + target_refresh = 60; + if (quirks & EDID_QUIRK_PREFER_LARGE_75) + target_refresh = 75; + + preferred_mode = list_first_entry(&connector->probed_modes, + struct drm_display_mode, head); + + list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) { + cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; + + if (cur_mode == preferred_mode) + continue; + + /* Largest mode is preferred */ + if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) + preferred_mode = cur_mode; + + /* At a given size, try to get closest to target refresh */ + if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && + MODE_REFRESH_DIFF(cur_mode, target_refresh) < + MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { + preferred_mode = cur_mode; + } + } + + preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; +} + +/** + * drm_mode_std - convert standard mode info (width, height, refresh) into mode + * @t: standard timing params + * + * Take the standard timing params (in this case width, aspect, and refresh) + * and convert them into a real mode using CVT. + * + * Punts for now, but should eventually use the FB layer's CVT based mode + * generation code. + */ +struct drm_display_mode *drm_mode_std(struct drm_device *dev, + struct std_timing *t) +{ + struct drm_display_mode *mode; + int hsize = t->hsize * 8 + 248, vsize; + + mode = drm_mode_create(dev); + if (!mode) + return NULL; + + if (t->aspect_ratio == 0) + vsize = (hsize * 10) / 16; + else if (t->aspect_ratio == 1) + vsize = (hsize * 3) / 4; + else if (t->aspect_ratio == 2) + vsize = (hsize * 4) / 5; + else + vsize = (hsize * 9) / 16; + + drm_mode_set_name(mode); + + return mode; +} + +/** + * drm_mode_detailed - create a new mode from an EDID detailed timing section + * @dev: DRM device (needed to create new mode) + * @edid: EDID block + * @timing: EDID detailed timing info + * @quirks: quirks to apply + * + * An EDID detailed timing block contains enough info for us to create and + * return a new struct drm_display_mode. + */ +static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, + struct edid *edid, + struct detailed_timing *timing, + u32 quirks) +{ + struct drm_display_mode *mode; + struct detailed_pixel_timing *pt = &timing->data.pixel_data; + + if (pt->stereo) { + printk(KERN_WARNING "stereo mode not supported\n"); + return NULL; + } + if (!pt->separate_sync) { + printk(KERN_WARNING "integrated sync not supported\n"); + return NULL; + } + + mode = drm_mode_create(dev); + if (!mode) + return NULL; + + mode->type = DRM_MODE_TYPE_DRIVER; + + if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) + timing->pixel_clock = 1088; + + mode->clock = timing->pixel_clock * 10; + + mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo; + mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) | + pt->hsync_offset_lo); + mode->hsync_end = mode->hsync_start + + ((pt->hsync_pulse_width_hi << 8) | + pt->hsync_pulse_width_lo); + mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); + + mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; + mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | + pt->vsync_offset_lo); + mode->vsync_end = mode->vsync_start + + ((pt->vsync_pulse_width_hi << 8) | + pt->vsync_pulse_width_lo); + mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); + + drm_mode_set_name(mode); + + if (pt->interlaced) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + + if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { + pt->hsync_positive = 1; + pt->vsync_positive = 1; + } + + mode->flags |= pt->hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; + mode->flags |= pt->vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; + + mode->width_mm = pt->width_mm_lo | (pt->width_mm_hi << 8); + mode->height_mm = pt->height_mm_lo | (pt->height_mm_hi << 8); + + if (quirks & EDID_QUIRK_DETAILED_IN_CM) { + mode->width_mm *= 10; + mode->height_mm *= 10; + } + + if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + mode->width_mm = edid->width_cm * 10; + mode->height_mm = edid->height_cm * 10; + } + + return mode; +} + +/* + * Detailed mode info for the EDID "established modes" data to use. + */ +static struct drm_display_mode edid_est_modes[] = { + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, + 968, 1056, 0, 600, 601, 605, 628, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, + 896, 1024, 0, 600, 601, 603, 625, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, + 720, 840, 0, 480, 481, 484, 500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, + 704, 832, 0, 480, 489, 491, 520, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, + 768, 864, 0, 480, 483, 486, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, + 752, 800, 0, 480, 490, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ + { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, + 846, 900, 0, 400, 421, 423, 449, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ + { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, + 846, 900, 0, 400, 412, 414, 449, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, + 1136, 1312, 0, 768, 769, 772, 800, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, + 1184, 1328, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, + 1184, 1344, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, + 1208, 1264, 0, 768, 768, 776, 817, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ + { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, + 928, 1152, 0, 624, 625, 628, 667, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, + 896, 1056, 0, 600, 601, 604, 625, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, + 976, 1040, 0, 600, 637, 643, 666, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, + 1344, 1600, 0, 864, 865, 868, 900, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ +}; + +#define EDID_EST_TIMINGS 16 +#define EDID_STD_TIMINGS 8 +#define EDID_DETAILED_TIMINGS 4 + +/** + * add_established_modes - get est. modes from EDID and add them + * @edid: EDID block to scan + * + * Each EDID block contains a bitmap of the supported "established modes" list + * (defined above). Tease them out and add them to the global modes list. + */ +static int add_established_modes(struct drm_connector *connector, struct edid *edid) +{ + struct drm_device *dev = connector->dev; + unsigned long est_bits = edid->established_timings.t1 | + (edid->established_timings.t2 << 8) | + ((edid->established_timings.mfg_rsvd & 0x80) << 9); + int i, modes = 0; + + for (i = 0; i <= EDID_EST_TIMINGS; i++) + if (est_bits & (1<<i)) { + struct drm_display_mode *newmode; + newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + + return modes; +} + +/** + * add_standard_modes - get std. modes from EDID and add them + * @edid: EDID block to scan + * + * Standard modes can be calculated using the CVT standard. Grab them from + * @edid, calculate them, and add them to the list. + */ +static int add_standard_modes(struct drm_connector *connector, struct edid *edid) +{ + struct drm_device *dev = connector->dev; + int i, modes = 0; + + for (i = 0; i < EDID_STD_TIMINGS; i++) { + struct std_timing *t = &edid->standard_timings[i]; + struct drm_display_mode *newmode; + + /* If std timings bytes are 1, 1 it's empty */ + if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1) + continue; + + newmode = drm_mode_std(dev, &edid->standard_timings[i]); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + + return modes; +} + +/** + * add_detailed_modes - get detailed mode info from EDID data + * @connector: attached connector + * @edid: EDID block to scan + * @quirks: quirks to apply + * + * Some of the detailed timing sections may contain mode information. Grab + * it and add it to the list. + */ +static int add_detailed_info(struct drm_connector *connector, + struct edid *edid, u32 quirks) +{ + struct drm_device *dev = connector->dev; + int i, j, modes = 0; + + for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { + struct detailed_timing *timing = &edid->detailed_timings[i]; + struct detailed_non_pixel *data = &timing->data.other_data; + struct drm_display_mode *newmode; + + /* EDID up to and including 1.2 may put monitor info here */ + if (edid->version == 1 && edid->revision < 3) + continue; + + /* Detailed mode timing */ + if (timing->pixel_clock) { + newmode = drm_mode_detailed(dev, edid, timing, quirks); + if (!newmode) + continue; + + /* First detailed mode is preferred */ + if (i == 0 && edid->preferred_timing) + newmode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, newmode); + + modes++; + continue; + } + + /* Other timing or info */ + switch (data->type) { + case EDID_DETAIL_MONITOR_SERIAL: + break; + case EDID_DETAIL_MONITOR_STRING: + break; + case EDID_DETAIL_MONITOR_RANGE: + /* Get monitor range data */ + break; + case EDID_DETAIL_MONITOR_NAME: + break; + case EDID_DETAIL_MONITOR_CPDATA: + break; + case EDID_DETAIL_STD_MODES: + /* Five modes per detailed section */ + for (j = 0; j < 5; i++) { + struct std_timing *std; + struct drm_display_mode *newmode; + + std = &data->data.timings[j]; + newmode = drm_mode_std(dev, std); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + break; + default: + break; + } + } + + return modes; +} + +#define DDC_ADDR 0x50 + +unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter) +{ + unsigned char start = 0x0; + unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL); + struct i2c_msg msgs[] = { + { + .addr = DDC_ADDR, + .flags = 0, + .len = 1, + .buf = &start, + }, { + .addr = DDC_ADDR, + .flags = I2C_M_RD, + .len = EDID_LENGTH, + .buf = buf, + } + }; + + if (!buf) { + dev_warn(&adapter->dev, "unable to allocate memory for EDID " + "block.\n"); + return NULL; + } + + if (i2c_transfer(adapter, msgs, 2) == 2) + return buf; + + dev_info(&adapter->dev, "unable to read EDID block.\n"); + kfree(buf); + return NULL; +} +EXPORT_SYMBOL(drm_do_probe_ddc_edid); + +static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) +{ + struct i2c_algo_bit_data *algo_data = adapter->algo_data; + unsigned char *edid = NULL; + int i, j; + + algo_data->setscl(algo_data->data, 1); + + for (i = 0; i < 1; i++) { + /* For some old monitors we need the + * following process to initialize/stop DDC + */ + algo_data->setsda(algo_data->data, 1); + msleep(13); + + algo_data->setscl(algo_data->data, 1); + for (j = 0; j < 5; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + if (j == 5) + continue; + + algo_data->setsda(algo_data->data, 0); + msleep(15); + algo_data->setscl(algo_data->data, 0); + msleep(15); + algo_data->setsda(algo_data->data, 1); + msleep(15); + + /* Do the real work */ + edid = drm_do_probe_ddc_edid(adapter); + algo_data->setsda(algo_data->data, 0); + algo_data->setscl(algo_data->data, 0); + msleep(15); + + algo_data->setscl(algo_data->data, 1); + for (j = 0; j < 10; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + + algo_data->setsda(algo_data->data, 1); + msleep(15); + algo_data->setscl(algo_data->data, 0); + algo_data->setsda(algo_data->data, 0); + if (edid) + break; + } + /* Release the DDC lines when done or the Apple Cinema HD display + * will switch off + */ + algo_data->setsda(algo_data->data, 1); + algo_data->setscl(algo_data->data, 1); + + return edid; +} + +/** + * drm_get_edid - get EDID data, if available + * @connector: connector we're probing + * @adapter: i2c adapter to use for DDC + * + * Poke the given connector's i2c channel to grab EDID data if possible. + * + * Return edid data or NULL if we couldn't find any. + */ +struct edid *drm_get_edid(struct drm_connector *connector, + struct i2c_adapter *adapter) +{ + struct edid *edid; + + edid = (struct edid *)drm_ddc_read(adapter); + if (!edid) { + dev_warn(&connector->dev->pdev->dev, "%s: no EDID data\n", + drm_get_connector_name(connector)); + return NULL; + } + if (!edid_is_valid(edid)) { + dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", + drm_get_connector_name(connector)); + kfree(edid); + return NULL; + } + + connector->display_info.raw_edid = (char *)edid; + + return edid; +} +EXPORT_SYMBOL(drm_get_edid); + +/** + * drm_add_edid_modes - add modes from EDID data, if available + * @connector: connector we're probing + * @edid: edid data + * + * Add the specified modes to the connector's mode list. + * + * Return number of modes added or 0 if we couldn't find any. + */ +int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) +{ + int num_modes = 0; + u32 quirks; + + if (edid == NULL) { + return 0; + } + if (!edid_is_valid(edid)) { + dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", + drm_get_connector_name(connector)); + return 0; + } + + quirks = edid_get_quirks(edid); + + num_modes += add_established_modes(connector, edid); + num_modes += add_standard_modes(connector, edid); + num_modes += add_detailed_info(connector, edid, quirks); + + if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) + edid_fixup_preferred(connector, quirks); + + connector->display_info.serration_vsync = edid->serration_vsync; + connector->display_info.sync_on_green = edid->sync_on_green; + connector->display_info.composite_sync = edid->composite_sync; + connector->display_info.separate_syncs = edid->separate_syncs; + connector->display_info.blank_to_black = edid->blank_to_black; + connector->display_info.video_level = edid->video_level; + connector->display_info.digital = edid->digital; + connector->display_info.width_mm = edid->width_cm * 10; + connector->display_info.height_mm = edid->height_cm * 10; + connector->display_info.gamma = edid->gamma; + connector->display_info.gtf_supported = edid->default_gtf; + connector->display_info.standard_color = edid->standard_color; + connector->display_info.display_type = edid->display_type; + connector->display_info.active_off_supported = edid->pm_active_off; + connector->display_info.suspend_supported = edid->pm_suspend; + connector->display_info.standby_supported = edid->pm_standby; + connector->display_info.gamma = edid->gamma; + + return num_modes; +} +EXPORT_SYMBOL(drm_add_edid_modes); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 78eeed5caaff..3733e36d135e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -35,7 +35,6 @@ */ #include "drmP.h" -#include "drm_sarea.h" #include <linux/poll.h> #include <linux/smp_lock.h> @@ -44,10 +43,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp, static int drm_setup(struct drm_device * dev) { - drm_local_map_t *map; int i; int ret; - u32 sareapage; if (dev->driver->firstopen) { ret = dev->driver->firstopen(dev); @@ -55,20 +52,14 @@ static int drm_setup(struct drm_device * dev) return ret; } - dev->magicfree.next = NULL; - - /* prebuild the SAREA */ - sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE); - i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); - if (i != 0) - return i; - atomic_set(&dev->ioctl_count, 0); atomic_set(&dev->vma_count, 0); - dev->buf_use = 0; - atomic_set(&dev->buf_alloc, 0); - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) { + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && + !drm_core_check_feature(dev, DRIVER_MODESET)) { + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + i = drm_dma_setup(dev); if (i < 0) return i; @@ -77,16 +68,12 @@ static int drm_setup(struct drm_device * dev) for (i = 0; i < ARRAY_SIZE(dev->counts); i++) atomic_set(&dev->counts[i], 0); - drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER); - INIT_LIST_HEAD(&dev->magicfree); - dev->sigdata.lock = NULL; - init_waitqueue_head(&dev->lock.lock_queue); + dev->queue_count = 0; dev->queue_reserved = 0; dev->queue_slots = 0; dev->queuelist = NULL; - dev->irq_enabled = 0; dev->context_flag = 0; dev->interrupt_flag = 0; dev->dma_flag = 0; @@ -147,10 +134,20 @@ int drm_open(struct inode *inode, struct file *filp) spin_lock(&dev->count_lock); if (!dev->open_count++) { spin_unlock(&dev->count_lock); - return drm_setup(dev); + retcode = drm_setup(dev); + goto out; } spin_unlock(&dev->count_lock); } +out: + mutex_lock(&dev->struct_mutex); + if (minor->type == DRM_MINOR_LEGACY) { + BUG_ON((dev->dev_mapping != NULL) && + (dev->dev_mapping != inode->i_mapping)); + if (dev->dev_mapping == NULL) + dev->dev_mapping = inode->i_mapping; + } + mutex_unlock(&dev->struct_mutex); return retcode; } @@ -255,6 +252,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->lock_count = 0; INIT_LIST_HEAD(&priv->lhead); + INIT_LIST_HEAD(&priv->fbs); if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); @@ -265,10 +263,42 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_free; } + + /* if there is no current master make this fd it */ mutex_lock(&dev->struct_mutex); - if (list_empty(&dev->filelist)) - priv->master = 1; + if (!priv->minor->master) { + /* create a new master */ + priv->minor->master = drm_master_create(priv->minor); + if (!priv->minor->master) { + ret = -ENOMEM; + goto out_free; + } + priv->is_master = 1; + /* take another reference for the copy in the local file priv */ + priv->master = drm_master_get(priv->minor->master); + + priv->authenticated = 1; + + mutex_unlock(&dev->struct_mutex); + if (dev->driver->master_create) { + ret = dev->driver->master_create(dev, priv->master); + if (ret) { + mutex_lock(&dev->struct_mutex); + /* drop both references if this fails */ + drm_master_put(&priv->minor->master); + drm_master_put(&priv->master); + mutex_unlock(&dev->struct_mutex); + goto out_free; + } + } + } else { + /* get a reference to the master */ + priv->master = drm_master_get(priv->minor->master); + mutex_unlock(&dev->struct_mutex); + } + + mutex_lock(&dev->struct_mutex); list_add(&priv->lhead, &dev->filelist); mutex_unlock(&dev->struct_mutex); @@ -314,6 +344,74 @@ int drm_fasync(int fd, struct file *filp, int on) } EXPORT_SYMBOL(drm_fasync); +/* + * Reclaim locked buffers; note that this may be a bad idea if the current + * context doesn't have the hw lock... + */ +static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) +{ + struct drm_file *file_priv = f->private_data; + + if (drm_i_have_hw_lock(dev, file_priv)) { + dev->driver->reclaim_buffers_locked(dev, file_priv); + } else { + unsigned long _end = jiffies + 3 * DRM_HZ; + int locked = 0; + + drm_idlelock_take(&file_priv->master->lock); + + /* + * Wait for a while. + */ + do { + spin_lock_bh(&file_priv->master->lock.spinlock); + locked = file_priv->master->lock.idle_has_lock; + spin_unlock_bh(&file_priv->master->lock.spinlock); + if (locked) + break; + schedule(); + } while (!time_after_eq(jiffies, _end)); + + if (!locked) { + DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" + "\tdriver to use reclaim_buffers_idlelocked() instead.\n" + "\tI will go on reclaiming the buffers anyway.\n"); + } + + dev->driver->reclaim_buffers_locked(dev, file_priv); + drm_idlelock_release(&file_priv->master->lock); + } +} + +static void drm_master_release(struct drm_device *dev, struct file *filp) +{ + struct drm_file *file_priv = filp->private_data; + + if (dev->driver->reclaim_buffers_locked && + file_priv->master->lock.hw_lock) + drm_reclaim_locked_buffers(dev, filp); + + if (dev->driver->reclaim_buffers_idlelocked && + file_priv->master->lock.hw_lock) { + drm_idlelock_take(&file_priv->master->lock); + dev->driver->reclaim_buffers_idlelocked(dev, file_priv); + drm_idlelock_release(&file_priv->master->lock); + } + + + if (drm_i_have_hw_lock(dev, file_priv)) { + DRM_DEBUG("File %p released, freeing lock for context %d\n", + filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); + drm_lock_free(&file_priv->master->lock, + _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); + } + + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && + !dev->driver->reclaim_buffers_locked) { + dev->driver->reclaim_buffers(dev, file_priv); + } +} + /** * Release file. * @@ -348,60 +446,9 @@ int drm_release(struct inode *inode, struct file *filp) (long)old_encode_dev(file_priv->minor->device), dev->open_count); - if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { - if (drm_i_have_hw_lock(dev, file_priv)) { - dev->driver->reclaim_buffers_locked(dev, file_priv); - } else { - unsigned long endtime = jiffies + 3 * DRM_HZ; - int locked = 0; - - drm_idlelock_take(&dev->lock); - - /* - * Wait for a while. - */ - - do{ - spin_lock_bh(&dev->lock.spinlock); - locked = dev->lock.idle_has_lock; - spin_unlock_bh(&dev->lock.spinlock); - if (locked) - break; - schedule(); - } while (!time_after_eq(jiffies, endtime)); - - if (!locked) { - DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" - "\tdriver to use reclaim_buffers_idlelocked() instead.\n" - "\tI will go on reclaiming the buffers anyway.\n"); - } - - dev->driver->reclaim_buffers_locked(dev, file_priv); - drm_idlelock_release(&dev->lock); - } - } - - if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) { - - drm_idlelock_take(&dev->lock); - dev->driver->reclaim_buffers_idlelocked(dev, file_priv); - drm_idlelock_release(&dev->lock); - - } - - if (drm_i_have_hw_lock(dev, file_priv)) { - DRM_DEBUG("File %p released, freeing lock for context %d\n", - filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - - drm_lock_free(&dev->lock, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - } - - - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && - !dev->driver->reclaim_buffers_locked) { - dev->driver->reclaim_buffers(dev, file_priv); - } + /* if the master has gone away we can't do anything with the lock */ + if (file_priv->minor->master) + drm_master_release(dev, filp); if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); @@ -428,12 +475,24 @@ int drm_release(struct inode *inode, struct file *filp) mutex_unlock(&dev->ctxlist_mutex); mutex_lock(&dev->struct_mutex); - if (file_priv->remove_auth_on_close == 1) { + + if (file_priv->is_master) { struct drm_file *temp; + list_for_each_entry(temp, &dev->filelist, lhead) { + if ((temp->master == file_priv->master) && + (temp != file_priv)) + temp->authenticated = 0; + } - list_for_each_entry(temp, &dev->filelist, lhead) - temp->authenticated = 0; + if (file_priv->minor->master == file_priv->master) { + /* drop the reference held my the minor */ + drm_master_put(&file_priv->minor->master); + } } + + /* drop the reference held my the file priv */ + drm_master_put(&file_priv->master); + file_priv->is_master = 0; list_del(&file_priv->lhead); mutex_unlock(&dev->struct_mutex); @@ -448,9 +507,9 @@ int drm_release(struct inode *inode, struct file *filp) atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); spin_lock(&dev->count_lock); if (!--dev->open_count) { - if (atomic_read(&dev->ioctl_count) || dev->blocked) { - DRM_ERROR("Device busy: %d %d\n", - atomic_read(&dev->ioctl_count), dev->blocked); + if (atomic_read(&dev->ioctl_count)) { + DRM_ERROR("Device busy: %d\n", + atomic_read(&dev->ioctl_count)); spin_unlock(&dev->count_lock); unlock_kernel(); return -EBUSY; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index ccd1afdede02..9da581452874 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -64,6 +64,13 @@ * up at a later date, and as our interface with shmfs for memory allocation. */ +/* + * We make up offsets for buffer objects so we can recognize them at + * mmap time. + */ +#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) +#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) + /** * Initialize the GEM device fields */ @@ -71,6 +78,8 @@ int drm_gem_init(struct drm_device *dev) { + struct drm_gem_mm *mm; + spin_lock_init(&dev->object_name_lock); idr_init(&dev->object_name_idr); atomic_set(&dev->object_count, 0); @@ -79,9 +88,41 @@ drm_gem_init(struct drm_device *dev) atomic_set(&dev->pin_memory, 0); atomic_set(&dev->gtt_count, 0); atomic_set(&dev->gtt_memory, 0); + + mm = drm_calloc(1, sizeof(struct drm_gem_mm), DRM_MEM_MM); + if (!mm) { + DRM_ERROR("out of memory\n"); + return -ENOMEM; + } + + dev->mm_private = mm; + + if (drm_ht_create(&mm->offset_hash, 19)) { + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM); + return -ENOMEM; + } + + if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START, + DRM_FILE_PAGE_OFFSET_SIZE)) { + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM); + drm_ht_remove(&mm->offset_hash); + return -ENOMEM; + } + return 0; } +void +drm_gem_destroy(struct drm_device *dev) +{ + struct drm_gem_mm *mm = dev->mm_private; + + drm_mm_takedown(&mm->offset_manager); + drm_ht_remove(&mm->offset_hash); + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM); + dev->mm_private = NULL; +} + /** * Allocate a GEM object of the specified size with shmfs backing store */ @@ -419,3 +460,73 @@ drm_gem_object_handle_free(struct kref *kref) } EXPORT_SYMBOL(drm_gem_object_handle_free); +/** + * drm_gem_mmap - memory map routine for GEM objects + * @filp: DRM file pointer + * @vma: VMA for the area to be mapped + * + * If a driver supports GEM object mapping, mmap calls on the DRM file + * descriptor will end up here. + * + * If we find the object based on the offset passed in (vma->vm_pgoff will + * contain the fake offset we created when the GTT map ioctl was called on + * the object), we set up the driver fault handler so that any accesses + * to the object can be trapped, to perform migration, GTT binding, surface + * register allocation, or performance monitoring. + */ +int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_map *map = NULL; + struct drm_gem_object *obj; + struct drm_hash_item *hash; + unsigned long prot; + int ret = 0; + + mutex_lock(&dev->struct_mutex); + + if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { + mutex_unlock(&dev->struct_mutex); + return drm_mmap(filp, vma); + } + + map = drm_hash_entry(hash, struct drm_map_list, hash)->map; + if (!map || + ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) { + ret = -EPERM; + goto out_unlock; + } + + /* Check for valid size. */ + if (map->size < vma->vm_end - vma->vm_start) { + ret = -EINVAL; + goto out_unlock; + } + + obj = map->handle; + if (!obj->dev->driver->gem_vm_ops) { + ret = -EINVAL; + goto out_unlock; + } + + vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; + vma->vm_ops = obj->dev->driver->gem_vm_ops; + vma->vm_private_data = map->handle; + /* FIXME: use pgprot_writecombine when available */ + prot = pgprot_val(vma->vm_page_prot); +#ifdef CONFIG_X86 + prot |= _PAGE_CACHE_WC; +#endif + vma->vm_page_prot = __pgprot(prot); + + vma->vm_file = filp; /* Needed for drm_vm_open() */ + drm_vm_open_locked(vma); + +out_unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} +EXPORT_SYMBOL(drm_gem_mmap); diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index 33160673a7b7..af539f7d87dd 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c @@ -127,6 +127,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) } return 0; } +EXPORT_SYMBOL(drm_ht_insert_item); /* * Just insert an item and return any "bits" bit key that hasn't been @@ -188,6 +189,7 @@ int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) ht->fill--; return 0; } +EXPORT_SYMBOL(drm_ht_remove_item); void drm_ht_remove(struct drm_open_hash *ht) { diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 16829fb3089d..1fad76289e66 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -53,12 +53,13 @@ int drm_getunique(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_unique *u = data; + struct drm_master *master = file_priv->master; - if (u->unique_len >= dev->unique_len) { - if (copy_to_user(u->unique, dev->unique, dev->unique_len)) + if (u->unique_len >= master->unique_len) { + if (copy_to_user(u->unique, master->unique, master->unique_len)) return -EFAULT; } - u->unique_len = dev->unique_len; + u->unique_len = master->unique_len; return 0; } @@ -81,36 +82,38 @@ int drm_setunique(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_unique *u = data; + struct drm_master *master = file_priv->master; int domain, bus, slot, func, ret; - if (dev->unique_len || dev->unique) + if (master->unique_len || master->unique) return -EBUSY; if (!u->unique_len || u->unique_len > 1024) return -EINVAL; - dev->unique_len = u->unique_len; - dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); - if (!dev->unique) + master->unique_len = u->unique_len; + master->unique_size = u->unique_len + 1; + master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER); + if (!master->unique) return -ENOMEM; - if (copy_from_user(dev->unique, u->unique, dev->unique_len)) + if (copy_from_user(master->unique, u->unique, master->unique_len)) return -EFAULT; - dev->unique[dev->unique_len] = '\0'; + master->unique[master->unique_len] = '\0'; dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + - strlen(dev->unique) + 2, DRM_MEM_DRIVER); + strlen(master->unique) + 2, DRM_MEM_DRIVER); if (!dev->devname) return -ENOMEM; sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, - dev->unique); + master->unique); /* Return error if the busid submitted doesn't match the device's actual * busid. */ - ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); + ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); if (ret != 3) return -EINVAL; domain = bus >> 8; @@ -125,34 +128,38 @@ int drm_setunique(struct drm_device *dev, void *data, return 0; } -static int drm_set_busid(struct drm_device * dev) +static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) { + struct drm_master *master = file_priv->master; int len; - if (dev->unique != NULL) - return 0; + if (master->unique != NULL) + return -EBUSY; - dev->unique_len = 40; - dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); - if (dev->unique == NULL) + master->unique_len = 40; + master->unique_size = master->unique_len; + master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER); + if (master->unique == NULL) return -ENOMEM; - len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", - drm_get_pci_domain(dev), dev->pdev->bus->number, + len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d", + drm_get_pci_domain(dev), + dev->pdev->bus->number, PCI_SLOT(dev->pdev->devfn), PCI_FUNC(dev->pdev->devfn)); - - if (len > dev->unique_len) - DRM_ERROR("Unique buffer overflowed\n"); + if (len >= master->unique_len) + DRM_ERROR("buffer overflow"); + else + master->unique_len = len; dev->devname = - drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + + drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len + 2, DRM_MEM_DRIVER); if (dev->devname == NULL) return -ENOMEM; sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, - dev->unique); + master->unique); return 0; } @@ -276,7 +283,7 @@ int drm_getstats(struct drm_device *dev, void *data, for (i = 0; i < dev->counters; i++) { if (dev->types[i] == _DRM_STAT_LOCK) stats->data[i].value = - (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); + (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0); else stats->data[i].value = atomic_read(&dev->counts[i]); stats->data[i].type = dev->types[i]; @@ -318,7 +325,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri /* * Version 1.1 includes tying of DRM to specific device */ - drm_set_busid(dev); + drm_set_busid(dev, file_priv); } } diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 1e787f894b3c..724e505873cf 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -116,6 +116,9 @@ void drm_vblank_cleanup(struct drm_device *dev) dev->num_crtcs, DRM_MEM_DRIVER); drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->last_vblank_wait, + sizeof(*dev->last_vblank_wait) * dev->num_crtcs, + DRM_MEM_DRIVER); drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) * dev->num_crtcs, DRM_MEM_DRIVER); @@ -161,6 +164,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->last_vblank) goto err; + dev->last_vblank_wait = drm_calloc(num_crtcs, sizeof(u32), + DRM_MEM_DRIVER); + if (!dev->last_vblank_wait) + goto err; + dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int), DRM_MEM_DRIVER); if (!dev->vblank_inmodeset) @@ -305,6 +313,8 @@ int drm_control(struct drm_device *dev, void *data, case DRM_INST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != dev->pdev->irq) return -EINVAL; @@ -312,6 +322,8 @@ int drm_control(struct drm_device *dev, void *data, case DRM_UNINST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; return drm_irq_uninstall(dev); default: return -EINVAL; @@ -427,6 +439,45 @@ void drm_vblank_put(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_put); /** + * drm_vblank_pre_modeset - account for vblanks across mode sets + * @dev: DRM device + * @crtc: CRTC in question + * @post: post or pre mode set? + * + * Account for vblank events across mode setting events, which will likely + * reset the hardware frame counter. + */ +void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) +{ + /* + * To avoid all the problems that might happen if interrupts + * were enabled/disabled around or between these calls, we just + * have the kernel take a reference on the CRTC (just once though + * to avoid corrupting the count if multiple, mismatch calls occur), + * so that interrupts remain enabled in the interim. + */ + if (!dev->vblank_inmodeset[crtc]) { + dev->vblank_inmodeset[crtc] = 1; + drm_vblank_get(dev, crtc); + } +} +EXPORT_SYMBOL(drm_vblank_pre_modeset); + +void drm_vblank_post_modeset(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + + if (dev->vblank_inmodeset[crtc]) { + spin_lock_irqsave(&dev->vbl_lock, irqflags); + dev->vblank_disable_allowed = 1; + dev->vblank_inmodeset[crtc] = 0; + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + drm_vblank_put(dev, crtc); + } +} +EXPORT_SYMBOL(drm_vblank_post_modeset); + +/** * drm_modeset_ctl - handle vblank event counter changes across mode switch * @DRM_IOCTL_ARGS: standard ioctl arguments * @@ -441,7 +492,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; - unsigned long irqflags; int crtc, ret = 0; /* If drm_vblank_init() hasn't been called yet, just no-op */ @@ -454,28 +504,12 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, goto out; } - /* - * To avoid all the problems that might happen if interrupts - * were enabled/disabled around or between these calls, we just - * have the kernel take a reference on the CRTC (just once though - * to avoid corrupting the count if multiple, mismatch calls occur), - * so that interrupts remain enabled in the interim. - */ switch (modeset->cmd) { case _DRM_PRE_MODESET: - if (!dev->vblank_inmodeset[crtc]) { - dev->vblank_inmodeset[crtc] = 1; - drm_vblank_get(dev, crtc); - } + drm_vblank_pre_modeset(dev, crtc); break; case _DRM_POST_MODESET: - if (dev->vblank_inmodeset[crtc]) { - spin_lock_irqsave(&dev->vbl_lock, irqflags); - dev->vblank_disable_allowed = 1; - dev->vblank_inmodeset[crtc] = 0; - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - drm_vblank_put(dev, crtc); - } + drm_vblank_post_modeset(dev, crtc); break; default: ret = -EINVAL; @@ -616,6 +650,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, } else { DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); + dev->last_vblank_wait[crtc] = vblwait->request.sequence; DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, ((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23))); diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 1cfa72031f8f..46e7b28f0707 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -52,6 +52,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) { DECLARE_WAITQUEUE(entry, current); struct drm_lock *lock = data; + struct drm_master *master = file_priv->master; int ret = 0; ++file_priv->lock_count; @@ -64,26 +65,27 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", lock->context, task_pid_nr(current), - dev->lock.hw_lock->lock, lock->flags); + master->lock.hw_lock->lock, lock->flags); if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) if (lock->context < 0) return -EINVAL; - add_wait_queue(&dev->lock.lock_queue, &entry); - spin_lock_bh(&dev->lock.spinlock); - dev->lock.user_waiters++; - spin_unlock_bh(&dev->lock.spinlock); + add_wait_queue(&master->lock.lock_queue, &entry); + spin_lock_bh(&master->lock.spinlock); + master->lock.user_waiters++; + spin_unlock_bh(&master->lock.spinlock); + for (;;) { __set_current_state(TASK_INTERRUPTIBLE); - if (!dev->lock.hw_lock) { + if (!master->lock.hw_lock) { /* Device has been unregistered */ ret = -EINTR; break; } - if (drm_lock_take(&dev->lock, lock->context)) { - dev->lock.file_priv = file_priv; - dev->lock.lock_time = jiffies; + if (drm_lock_take(&master->lock, lock->context)) { + master->lock.file_priv = file_priv; + master->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ } @@ -95,11 +97,11 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) break; } } - spin_lock_bh(&dev->lock.spinlock); - dev->lock.user_waiters--; - spin_unlock_bh(&dev->lock.spinlock); + spin_lock_bh(&master->lock.spinlock); + master->lock.user_waiters--; + spin_unlock_bh(&master->lock.spinlock); __set_current_state(TASK_RUNNING); - remove_wait_queue(&dev->lock.lock_queue, &entry); + remove_wait_queue(&master->lock.lock_queue, &entry); DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock"); @@ -108,14 +110,14 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* don't set the block all signals on the master process for now * really probably not the correct answer but lets us debug xkb * xserver for now */ - if (!file_priv->master) { + if (!file_priv->is_master) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGTSTP); sigaddset(&dev->sigmask, SIGTTIN); sigaddset(&dev->sigmask, SIGTTOU); dev->sigdata.context = lock->context; - dev->sigdata.lock = dev->lock.hw_lock; + dev->sigdata.lock = master->lock.hw_lock; block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); } @@ -154,6 +156,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_lock *lock = data; + struct drm_master *master = file_priv->master; if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -169,7 +172,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) if (dev->driver->kernel_context_switch_unlock) dev->driver->kernel_context_switch_unlock(dev); else { - if (drm_lock_free(&dev->lock,lock->context)) { + if (drm_lock_free(&master->lock, lock->context)) { /* FIXME: Should really bail out here. */ } } @@ -379,9 +382,10 @@ EXPORT_SYMBOL(drm_idlelock_release); int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) { - return (file_priv->lock_count && dev->lock.hw_lock && - _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.file_priv == file_priv); + struct drm_master *master = file_priv->master; + return (file_priv->lock_count && master->lock.hw_lock && + _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && + master->lock.file_priv == file_priv); } EXPORT_SYMBOL(drm_i_have_hw_lock); diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 217ad7dc7076..367c590ffbba 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -296,3 +296,4 @@ void drm_mm_takedown(struct drm_mm * mm) drm_free(entry, sizeof(*entry), DRM_MEM_MM); } +EXPORT_SYMBOL(drm_mm_takedown); diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c new file mode 100644 index 000000000000..c9b80fdd4630 --- /dev/null +++ b/drivers/gpu/drm/drm_modes.c @@ -0,0 +1,576 @@ +/* + * The list_sort function is (presumably) licensed under the GPL (see the + * top level "COPYING" file for details). + * + * The remainder of this file is: + * + * Copyright © 1997-2003 by The XFree86 Project, Inc. + * Copyright © 2007 Dave Airlie + * Copyright © 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#include <linux/list.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" + +/** + * drm_mode_debug_printmodeline - debug print a mode + * @dev: DRM device + * @mode: mode to print + * + * LOCKING: + * None. + * + * Describe @mode using DRM_DEBUG. + */ +void drm_mode_debug_printmodeline(struct drm_display_mode *mode) +{ + DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", + mode->base.id, mode->name, mode->vrefresh, mode->clock, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, mode->type, mode->flags); +} +EXPORT_SYMBOL(drm_mode_debug_printmodeline); + +/** + * drm_mode_set_name - set the name on a mode + * @mode: name will be set in this mode + * + * LOCKING: + * None. + * + * Set the name of @mode to a standard format. + */ +void drm_mode_set_name(struct drm_display_mode *mode) +{ + snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, + mode->vdisplay); +} +EXPORT_SYMBOL(drm_mode_set_name); + +/** + * drm_mode_list_concat - move modes from one list to another + * @head: source list + * @new: dst list + * + * LOCKING: + * Caller must ensure both lists are locked. + * + * Move all the modes from @head to @new. + */ +void drm_mode_list_concat(struct list_head *head, struct list_head *new) +{ + + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, head) { + list_move_tail(entry, new); + } +} +EXPORT_SYMBOL(drm_mode_list_concat); + +/** + * drm_mode_width - get the width of a mode + * @mode: mode + * + * LOCKING: + * None. + * + * Return @mode's width (hdisplay) value. + * + * FIXME: is this needed? + * + * RETURNS: + * @mode->hdisplay + */ +int drm_mode_width(struct drm_display_mode *mode) +{ + return mode->hdisplay; + +} +EXPORT_SYMBOL(drm_mode_width); + +/** + * drm_mode_height - get the height of a mode + * @mode: mode + * + * LOCKING: + * None. + * + * Return @mode's height (vdisplay) value. + * + * FIXME: is this needed? + * + * RETURNS: + * @mode->vdisplay + */ +int drm_mode_height(struct drm_display_mode *mode) +{ + return mode->vdisplay; +} +EXPORT_SYMBOL(drm_mode_height); + +/** + * drm_mode_vrefresh - get the vrefresh of a mode + * @mode: mode + * + * LOCKING: + * None. + * + * Return @mode's vrefresh rate or calculate it if necessary. + * + * FIXME: why is this needed? shouldn't vrefresh be set already? + * + * RETURNS: + * Vertical refresh rate of @mode x 1000. For precision reasons. + */ +int drm_mode_vrefresh(struct drm_display_mode *mode) +{ + int refresh = 0; + unsigned int calc_val; + + if (mode->vrefresh > 0) + refresh = mode->vrefresh; + else if (mode->htotal > 0 && mode->vtotal > 0) { + /* work out vrefresh the value will be x1000 */ + calc_val = (mode->clock * 1000); + + calc_val /= mode->htotal; + calc_val *= 1000; + calc_val /= mode->vtotal; + + refresh = calc_val; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + refresh *= 2; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + refresh /= 2; + if (mode->vscan > 1) + refresh /= mode->vscan; + } + return refresh; +} +EXPORT_SYMBOL(drm_mode_vrefresh); + +/** + * drm_mode_set_crtcinfo - set CRTC modesetting parameters + * @p: mode + * @adjust_flags: unused? (FIXME) + * + * LOCKING: + * None. + * + * Setup the CRTC modesetting parameters for @p, adjusting if necessary. + */ +void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) +{ + if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN)) + return; + + p->crtc_hdisplay = p->hdisplay; + p->crtc_hsync_start = p->hsync_start; + p->crtc_hsync_end = p->hsync_end; + p->crtc_htotal = p->htotal; + p->crtc_hskew = p->hskew; + p->crtc_vdisplay = p->vdisplay; + p->crtc_vsync_start = p->vsync_start; + p->crtc_vsync_end = p->vsync_end; + p->crtc_vtotal = p->vtotal; + + if (p->flags & DRM_MODE_FLAG_INTERLACE) { + if (adjust_flags & CRTC_INTERLACE_HALVE_V) { + p->crtc_vdisplay /= 2; + p->crtc_vsync_start /= 2; + p->crtc_vsync_end /= 2; + p->crtc_vtotal /= 2; + } + + p->crtc_vtotal |= 1; + } + + if (p->flags & DRM_MODE_FLAG_DBLSCAN) { + p->crtc_vdisplay *= 2; + p->crtc_vsync_start *= 2; + p->crtc_vsync_end *= 2; + p->crtc_vtotal *= 2; + } + + if (p->vscan > 1) { + p->crtc_vdisplay *= p->vscan; + p->crtc_vsync_start *= p->vscan; + p->crtc_vsync_end *= p->vscan; + p->crtc_vtotal *= p->vscan; + } + + p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay); + p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); + p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); + p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); + + p->crtc_hadjusted = false; + p->crtc_vadjusted = false; +} +EXPORT_SYMBOL(drm_mode_set_crtcinfo); + + +/** + * drm_mode_duplicate - allocate and duplicate an existing mode + * @m: mode to duplicate + * + * LOCKING: + * None. + * + * Just allocate a new mode, copy the existing mode into it, and return + * a pointer to it. Used to create new instances of established modes. + */ +struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, + struct drm_display_mode *mode) +{ + struct drm_display_mode *nmode; + int new_id; + + nmode = drm_mode_create(dev); + if (!nmode) + return NULL; + + new_id = nmode->base.id; + *nmode = *mode; + nmode->base.id = new_id; + INIT_LIST_HEAD(&nmode->head); + return nmode; +} +EXPORT_SYMBOL(drm_mode_duplicate); + +/** + * drm_mode_equal - test modes for equality + * @mode1: first mode + * @mode2: second mode + * + * LOCKING: + * None. + * + * Check to see if @mode1 and @mode2 are equivalent. + * + * RETURNS: + * True if the modes are equal, false otherwise. + */ +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 */ + if (mode1->clock && mode2->clock) { + if (KHZ2PICOS(mode1->clock) != KHZ2PICOS(mode2->clock)) + return false; + } else if (mode1->clock != mode2->clock) + return false; + + if (mode1->hdisplay == mode2->hdisplay && + mode1->hsync_start == mode2->hsync_start && + mode1->hsync_end == mode2->hsync_end && + mode1->htotal == mode2->htotal && + mode1->hskew == mode2->hskew && + mode1->vdisplay == mode2->vdisplay && + mode1->vsync_start == mode2->vsync_start && + mode1->vsync_end == mode2->vsync_end && + mode1->vtotal == mode2->vtotal && + mode1->vscan == mode2->vscan && + mode1->flags == mode2->flags) + return true; + + return false; +} +EXPORT_SYMBOL(drm_mode_equal); + +/** + * drm_mode_validate_size - make sure modes adhere to size constraints + * @dev: DRM device + * @mode_list: list of modes to check + * @maxX: maximum width + * @maxY: maximum height + * @maxPitch: max pitch + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * The DRM device (@dev) has size and pitch limits. Here we validate the + * modes we probed for @dev against those limits and set their status as + * necessary. + */ +void drm_mode_validate_size(struct drm_device *dev, + struct list_head *mode_list, + int maxX, int maxY, int maxPitch) +{ + struct drm_display_mode *mode; + + list_for_each_entry(mode, mode_list, head) { + if (maxPitch > 0 && mode->hdisplay > maxPitch) + mode->status = MODE_BAD_WIDTH; + + if (maxX > 0 && mode->hdisplay > maxX) + mode->status = MODE_VIRTUAL_X; + + if (maxY > 0 && mode->vdisplay > maxY) + mode->status = MODE_VIRTUAL_Y; + } +} +EXPORT_SYMBOL(drm_mode_validate_size); + +/** + * drm_mode_validate_clocks - validate modes against clock limits + * @dev: DRM device + * @mode_list: list of modes to check + * @min: minimum clock rate array + * @max: maximum clock rate array + * @n_ranges: number of clock ranges (size of arrays) + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * Some code may need to check a mode list against the clock limits of the + * device in question. This function walks the mode list, testing to make + * sure each mode falls within a given range (defined by @min and @max + * arrays) and sets @mode->status as needed. + */ +void drm_mode_validate_clocks(struct drm_device *dev, + struct list_head *mode_list, + int *min, int *max, int n_ranges) +{ + struct drm_display_mode *mode; + int i; + + list_for_each_entry(mode, mode_list, head) { + bool good = false; + for (i = 0; i < n_ranges; i++) { + if (mode->clock >= min[i] && mode->clock <= max[i]) { + good = true; + break; + } + } + if (!good) + mode->status = MODE_CLOCK_RANGE; + } +} +EXPORT_SYMBOL(drm_mode_validate_clocks); + +/** + * drm_mode_prune_invalid - remove invalid modes from mode list + * @dev: DRM device + * @mode_list: list of modes to check + * @verbose: be verbose about it + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * Once mode list generation is complete, a caller can use this routine to + * remove invalid modes from a mode list. If any of the modes have a + * status other than %MODE_OK, they are removed from @mode_list and freed. + */ +void drm_mode_prune_invalid(struct drm_device *dev, + struct list_head *mode_list, bool verbose) +{ + struct drm_display_mode *mode, *t; + + list_for_each_entry_safe(mode, t, mode_list, head) { + if (mode->status != MODE_OK) { + list_del(&mode->head); + if (verbose) { + drm_mode_debug_printmodeline(mode); + DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status); + } + drm_mode_destroy(dev, mode); + } + } +} +EXPORT_SYMBOL(drm_mode_prune_invalid); + +/** + * drm_mode_compare - compare modes for favorability + * @lh_a: list_head for first mode + * @lh_b: list_head for second mode + * + * LOCKING: + * None. + * + * Compare two modes, given by @lh_a and @lh_b, returning a value indicating + * which is better. + * + * RETURNS: + * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or + * positive if @lh_b is better than @lh_a. + */ +static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b) +{ + struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head); + struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head); + int diff; + + diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) - + ((a->type & DRM_MODE_TYPE_PREFERRED) != 0); + if (diff) + return diff; + diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay; + if (diff) + return diff; + diff = b->clock - a->clock; + return diff; +} + +/* FIXME: what we don't have a list sort function? */ +/* list sort from Mark J Roberts (mjr@znex.org) */ +void list_sort(struct list_head *head, + int (*cmp)(struct list_head *a, struct list_head *b)) +{ + struct list_head *p, *q, *e, *list, *tail, *oldhead; + int insize, nmerges, psize, qsize, i; + + list = head->next; + list_del(head); + insize = 1; + for (;;) { + p = oldhead = list; + list = tail = NULL; + nmerges = 0; + + while (p) { + nmerges++; + q = p; + psize = 0; + for (i = 0; i < insize; i++) { + psize++; + q = q->next == oldhead ? NULL : q->next; + if (!q) + break; + } + + qsize = insize; + while (psize > 0 || (qsize > 0 && q)) { + if (!psize) { + e = q; + q = q->next; + qsize--; + if (q == oldhead) + q = NULL; + } else if (!qsize || !q) { + e = p; + p = p->next; + psize--; + if (p == oldhead) + p = NULL; + } else if (cmp(p, q) <= 0) { + e = p; + p = p->next; + psize--; + if (p == oldhead) + p = NULL; + } else { + e = q; + q = q->next; + qsize--; + if (q == oldhead) + q = NULL; + } + if (tail) + tail->next = e; + else + list = e; + e->prev = tail; + tail = e; + } + p = q; + } + + tail->next = list; + list->prev = tail; + + if (nmerges <= 1) + break; + + insize *= 2; + } + + head->next = list; + head->prev = list->prev; + list->prev->next = head; + list->prev = head; +} + +/** + * drm_mode_sort - sort mode list + * @mode_list: list to sort + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * Sort @mode_list by favorability, putting good modes first. + */ +void drm_mode_sort(struct list_head *mode_list) +{ + list_sort(mode_list, drm_mode_compare); +} +EXPORT_SYMBOL(drm_mode_sort); + +/** + * drm_mode_connector_list_update - update the mode list for the connector + * @connector: the connector to update + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * This moves the modes from the @connector probed_modes list + * to the actual mode list. It compares the probed mode against the current + * list and only adds different modes. All modes unverified after this point + * will be removed by the prune invalid modes. + */ +void drm_mode_connector_list_update(struct drm_connector *connector) +{ + struct drm_display_mode *mode; + struct drm_display_mode *pmode, *pt; + int found_it; + + list_for_each_entry_safe(pmode, pt, &connector->probed_modes, + head) { + found_it = 0; + /* go through current modes checking for the new probed mode */ + list_for_each_entry(mode, &connector->modes, head) { + if (drm_mode_equal(pmode, mode)) { + found_it = 1; + /* if equal delete the probed mode */ + mode->status = pmode->status; + list_del(&pmode->head); + drm_mode_destroy(connector->dev, pmode); + break; + } + } + + if (!found_it) { + list_move_tail(&pmode->head, &connector->modes); + } + } +} +EXPORT_SYMBOL(drm_mode_connector_list_update); diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index ae73b7f7249a..8df849f66830 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -49,6 +49,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); static int drm_bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); +static int drm_vblank_info(char *buf, char **start, off_t offset, + int request, int *eof, void *data); static int drm_gem_name_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); static int drm_gem_object_info(char *buf, char **start, off_t offset, @@ -72,6 +74,7 @@ static struct drm_proc_list { {"clients", drm_clients_info, 0}, {"queues", drm_queues_info, 0}, {"bufs", drm_bufs_info, 0}, + {"vblank", drm_vblank_info, 0}, {"gem_names", drm_gem_name_info, DRIVER_GEM}, {"gem_objects", drm_gem_object_info, DRIVER_GEM}, #if DRM_DEBUG_CODE @@ -195,6 +198,7 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { struct drm_minor *minor = (struct drm_minor *) data; + struct drm_master *master = minor->master; struct drm_device *dev = minor->dev; int len = 0; @@ -203,13 +207,16 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request, return 0; } + if (!master) + return 0; + *start = &buf[offset]; *eof = 0; - if (dev->unique) { + if (master->unique) { DRM_PROC_PRINT("%s %s %s\n", dev->driver->pci_driver.name, - pci_name(dev->pdev), dev->unique); + pci_name(dev->pdev), master->unique); } else { DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev)); @@ -454,6 +461,66 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, } /** + * Called when "/proc/dri/.../vblank" is read. + * + * \param buf output buffer. + * \param start start of output data. + * \param offset requested start offset. + * \param request requested number of bytes. + * \param eof whether there is no more data to return. + * \param data private data. + * \return number of written bytes. + */ +static int drm__vblank_info(char *buf, char **start, off_t offset, int request, + int *eof, void *data) +{ + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; + int len = 0; + int crtc; + + if (offset > DRM_PROC_LIMIT) { + *eof = 1; + return 0; + } + + *start = &buf[offset]; + *eof = 0; + + for (crtc = 0; crtc < dev->num_crtcs; crtc++) { + DRM_PROC_PRINT("CRTC %d enable: %d\n", + crtc, atomic_read(&dev->vblank_refcount[crtc])); + DRM_PROC_PRINT("CRTC %d counter: %d\n", + crtc, drm_vblank_count(dev, crtc)); + DRM_PROC_PRINT("CRTC %d last wait: %d\n", + crtc, dev->last_vblank_wait[crtc]); + DRM_PROC_PRINT("CRTC %d in modeset: %d\n", + crtc, dev->vblank_inmodeset[crtc]); + } + + if (len > request + offset) + return request; + *eof = 1; + return len - offset; +} + +/** + * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock. + */ +static int drm_vblank_info(char *buf, char **start, off_t offset, int request, + int *eof, void *data) +{ + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; + int ret; + + mutex_lock(&dev->struct_mutex); + ret = drm__vblank_info(buf, start, offset, request, eof, data); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +/** * Called when "/proc/dri/.../clients" is read. * * \param buf output buffer. diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 66c96ec66672..5ca132afa4f2 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -57,6 +57,14 @@ static int drm_minor_get_id(struct drm_device *dev, int type) int ret; int base = 0, limit = 63; + if (type == DRM_MINOR_CONTROL) { + base += 64; + limit = base + 127; + } else if (type == DRM_MINOR_RENDER) { + base += 128; + limit = base + 255; + } + again: if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { DRM_ERROR("Out of memory expanding drawable idr\n"); @@ -79,6 +87,104 @@ again: return new_id; } +struct drm_master *drm_master_create(struct drm_minor *minor) +{ + struct drm_master *master; + + master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER); + if (!master) + return NULL; + + kref_init(&master->refcount); + spin_lock_init(&master->lock.spinlock); + init_waitqueue_head(&master->lock.lock_queue); + drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); + INIT_LIST_HEAD(&master->magicfree); + master->minor = minor; + + list_add_tail(&master->head, &minor->master_list); + + return master; +} + +struct drm_master *drm_master_get(struct drm_master *master) +{ + kref_get(&master->refcount); + return master; +} + +static void drm_master_destroy(struct kref *kref) +{ + struct drm_master *master = container_of(kref, struct drm_master, refcount); + struct drm_magic_entry *pt, *next; + struct drm_device *dev = master->minor->dev; + + list_del(&master->head); + + if (dev->driver->master_destroy) + dev->driver->master_destroy(dev, master); + + if (master->unique) { + drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER); + master->unique = NULL; + master->unique_len = 0; + } + + list_for_each_entry_safe(pt, next, &master->magicfree, head) { + list_del(&pt->head); + drm_ht_remove_item(&master->magiclist, &pt->hash_item); + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + + drm_ht_remove(&master->magiclist); + + if (master->lock.hw_lock) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; + master->lock.file_priv = NULL; + wake_up_interruptible(&master->lock.lock_queue); + } + + drm_free(master, sizeof(*master), DRM_MEM_DRIVER); +} + +void drm_master_put(struct drm_master **master) +{ + kref_put(&(*master)->refcount, drm_master_destroy); + *master = NULL; +} + +int drm_setmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + if (file_priv->minor->master && file_priv->minor->master != file_priv->master) + return -EINVAL; + + if (!file_priv->master) + return -EINVAL; + + 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); + mutex_lock(&dev->struct_mutex); + } + + return 0; +} + +int drm_dropmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + if (!file_priv->master) + return -EINVAL; + mutex_lock(&dev->struct_mutex); + drm_master_put(&file_priv->minor->master); + mutex_unlock(&dev->struct_mutex); + return 0; +} + static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -92,7 +198,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); - spin_lock_init(&dev->lock.spinlock); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); @@ -140,9 +245,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, } } - if (dev->driver->load) - if ((retcode = dev->driver->load(dev, ent->driver_data))) - goto error_out_unreg; retcode = drm_ctxbitmap_init(dev); if (retcode) { @@ -200,6 +302,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t new_minor->device = MKDEV(DRM_MAJOR, minor_id); new_minor->dev = dev; new_minor->index = minor_id; + INIT_LIST_HEAD(&new_minor->master_list); idr_replace(&drm_minors_idr, new_minor, minor_id); @@ -267,8 +370,30 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); goto err_g2; } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret) + goto err_g2; + } + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) - goto err_g2; + goto err_g3; + + if (dev->driver->load) { + ret = dev->driver->load(dev, ent->driver_data); + if (ret) + goto err_g3; + } + + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); + if (ret) + goto err_g3; + } + + list_add_tail(&dev->driver_item, &driver->device_list); DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, @@ -276,6 +401,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, return 0; +err_g3: + drm_put_minor(&dev->primary); err_g2: pci_disable_device(pdev); err_g1: @@ -297,11 +424,6 @@ int drm_put_dev(struct drm_device * dev) { DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); - if (dev->unique) { - drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); - dev->unique = NULL; - dev->unique_len = 0; - } if (dev->devname) { drm_free(dev->devname, strlen(dev->devname) + 1, DRM_MEM_DRIVER); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 1611b9bcbe7f..65d72d094c81 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -20,6 +20,7 @@ #include "drmP.h" #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) +#define to_drm_connector(d) container_of(d, struct drm_connector, kdev) /** * drm_sysfs_suspend - DRM class suspend hook @@ -34,7 +35,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_device *drm_dev = drm_minor->dev; - if (drm_dev->driver->suspend) + if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->suspend) return drm_dev->driver->suspend(drm_dev, state); return 0; @@ -52,7 +53,7 @@ static int drm_sysfs_resume(struct device *dev) struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_device *drm_dev = drm_minor->dev; - if (drm_dev->driver->resume) + if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->resume) return drm_dev->driver->resume(drm_dev); return 0; @@ -144,6 +145,323 @@ static void drm_sysfs_device_release(struct device *dev) return; } +/* + * Connector properties + */ +static ssize_t status_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + enum drm_connector_status status; + + status = connector->funcs->detect(connector); + return snprintf(buf, PAGE_SIZE, "%s", + drm_get_connector_status_name(status)); +} + +static ssize_t dpms_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + struct drm_device *dev = connector->dev; + uint64_t dpms_status; + int ret; + + ret = drm_connector_property_get_value(connector, + dev->mode_config.dpms_property, + &dpms_status); + if (ret) + return 0; + + return snprintf(buf, PAGE_SIZE, "%s", + drm_get_dpms_name((int)dpms_status)); +} + +static ssize_t enabled_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + + return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" : + "disabled"); +} + +static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct device *connector_dev = container_of(kobj, struct device, kobj); + struct drm_connector *connector = to_drm_connector(connector_dev); + unsigned char *edid; + size_t size; + + if (!connector->edid_blob_ptr) + return 0; + + edid = connector->edid_blob_ptr->data; + size = connector->edid_blob_ptr->length; + if (!edid) + return 0; + + if (off >= size) + return 0; + + if (off + count > size) + count = size - off; + memcpy(buf, edid + off, count); + + return count; +} + +static ssize_t modes_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + struct drm_display_mode *mode; + int written = 0; + + list_for_each_entry(mode, &connector->modes, head) { + written += snprintf(buf + written, PAGE_SIZE - written, "%s\n", + mode->name); + } + + return written; +} + +static ssize_t subconnector_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + struct drm_device *dev = connector->dev; + struct drm_property *prop = NULL; + uint64_t subconnector; + int is_tv = 0; + int ret; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + prop = dev->mode_config.dvi_i_subconnector_property; + break; + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Component: + prop = dev->mode_config.tv_subconnector_property; + is_tv = 1; + break; + default: + DRM_ERROR("Wrong connector type for this property\n"); + return 0; + } + + if (!prop) { + DRM_ERROR("Unable to find subconnector property\n"); + return 0; + } + + ret = drm_connector_property_get_value(connector, prop, &subconnector); + if (ret) + return 0; + + return snprintf(buf, PAGE_SIZE, "%s", is_tv ? + drm_get_tv_subconnector_name((int)subconnector) : + drm_get_dvi_i_subconnector_name((int)subconnector)); +} + +static ssize_t select_subconnector_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + struct drm_device *dev = connector->dev; + struct drm_property *prop = NULL; + uint64_t subconnector; + int is_tv = 0; + int ret; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + prop = dev->mode_config.dvi_i_select_subconnector_property; + break; + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Component: + prop = dev->mode_config.tv_select_subconnector_property; + is_tv = 1; + break; + default: + DRM_ERROR("Wrong connector type for this property\n"); + return 0; + } + + if (!prop) { + DRM_ERROR("Unable to find select subconnector property\n"); + return 0; + } + + ret = drm_connector_property_get_value(connector, prop, &subconnector); + if (ret) + return 0; + + return snprintf(buf, PAGE_SIZE, "%s", is_tv ? + drm_get_tv_select_name((int)subconnector) : + drm_get_dvi_i_select_name((int)subconnector)); +} + +static struct device_attribute connector_attrs[] = { + __ATTR_RO(status), + __ATTR_RO(enabled), + __ATTR_RO(dpms), + __ATTR_RO(modes), +}; + +/* These attributes are for both DVI-I connectors and all types of tv-out. */ +static struct device_attribute connector_attrs_opt1[] = { + __ATTR_RO(subconnector), + __ATTR_RO(select_subconnector), +}; + +static struct bin_attribute edid_attr = { + .attr.name = "edid", + .size = 128, + .read = edid_show, +}; + +/** + * drm_sysfs_connector_add - add an connector to sysfs + * @connector: connector to add + * + * Create an connector device in sysfs, along with its associated connector + * properties (so far, connection status, dpms, mode list & edid) and + * generate a hotplug event so userspace knows there's a new connector + * available. + * + * Note: + * This routine should only be called *once* for each DRM minor registered. + * A second call for an already registered device will trigger the BUG_ON + * below. + */ +int drm_sysfs_connector_add(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + int ret = 0, i, j; + + /* We shouldn't get called more than once for the same connector */ + BUG_ON(device_is_registered(&connector->kdev)); + + connector->kdev.parent = &dev->primary->kdev; + connector->kdev.class = drm_class; + connector->kdev.release = drm_sysfs_device_release; + + DRM_DEBUG("adding \"%s\" to sysfs\n", + drm_get_connector_name(connector)); + + snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s", + dev->primary->index, drm_get_connector_name(connector)); + ret = device_register(&connector->kdev); + + if (ret) { + DRM_ERROR("failed to register connector device: %d\n", ret); + goto out; + } + + /* Standard attributes */ + + for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) { + ret = device_create_file(&connector->kdev, &connector_attrs[i]); + if (ret) + goto err_out_files; + } + + /* Optional attributes */ + /* + * In the long run it maybe a good idea to make one set of + * optionals per connector type. + */ + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Component: + for (i = 0; i < ARRAY_SIZE(connector_attrs_opt1); i++) { + ret = device_create_file(&connector->kdev, &connector_attrs_opt1[i]); + if (ret) + goto err_out_files; + } + break; + default: + break; + } + + ret = sysfs_create_bin_file(&connector->kdev.kobj, &edid_attr); + if (ret) + goto err_out_files; + + /* Let userspace know we have a new connector */ + drm_sysfs_hotplug_event(dev); + + return 0; + +err_out_files: + if (i > 0) + for (j = 0; j < i; j++) + device_remove_file(&connector->kdev, + &connector_attrs[i]); + device_unregister(&connector->kdev); + +out: + return ret; +} +EXPORT_SYMBOL(drm_sysfs_connector_add); + +/** + * drm_sysfs_connector_remove - remove an connector device from sysfs + * @connector: connector to remove + * + * Remove @connector and its associated attributes from sysfs. Note that + * the device model core will take care of sending the "remove" uevent + * at this time, so we don't need to do it. + * + * Note: + * This routine should only be called if the connector was previously + * successfully registered. If @connector hasn't been registered yet, + * you'll likely see a panic somewhere deep in sysfs code when called. + */ +void drm_sysfs_connector_remove(struct drm_connector *connector) +{ + int i; + + DRM_DEBUG("removing \"%s\" from sysfs\n", + drm_get_connector_name(connector)); + + for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) + device_remove_file(&connector->kdev, &connector_attrs[i]); + sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr); + device_unregister(&connector->kdev); +} +EXPORT_SYMBOL(drm_sysfs_connector_remove); + +/** + * drm_sysfs_hotplug_event - generate a DRM uevent + * @dev: DRM device + * + * Send a uevent for the DRM device specified by @dev. Currently we only + * set HOTPLUG=1 in the uevent environment, but this could be expanded to + * deal with other types of events. + */ +void drm_sysfs_hotplug_event(struct drm_device *dev) +{ + char *event_string = "HOTPLUG=1"; + char *envp[] = { event_string, NULL }; + + DRM_DEBUG("generating hotplug event\n"); + + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp); +} + /** * drm_sysfs_device_add - adds a class device to sysfs for a character driver * @dev: DRM device to be added @@ -163,7 +481,12 @@ int drm_sysfs_device_add(struct drm_minor *minor) minor->kdev.class = drm_class; minor->kdev.release = drm_sysfs_device_release; minor->kdev.devt = minor->device; - minor_str = "card%d"; + if (minor->type == DRM_MINOR_CONTROL) + minor_str = "controlD%d"; + else if (minor->type == DRM_MINOR_RENDER) + minor_str = "renderD%d"; + else + minor_str = "card%d"; snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index c234c6f24a8d..3ffae021d280 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -267,6 +267,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) dmah.size = map->size; __drm_pci_free(dev, &dmah); break; + case _DRM_GEM: + DRM_ERROR("tried to rmmap GEM object\n"); + break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); } @@ -399,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { * Create a new drm_vma_entry structure as the \p vma private data entry and * add it to drm_device::vmalist. */ -static void drm_vm_open_locked(struct vm_area_struct *vma) +void drm_vm_open_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -540,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); * according to the mapping type and remaps the pages. Finally sets the file * pointer and calls vm_open(). */ -static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) +int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index d8fb5d8ee7ea..dd57a5bd4572 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -8,7 +8,22 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ i915_gem.o \ i915_gem_debug.o \ i915_gem_proc.o \ - i915_gem_tiling.o + i915_gem_tiling.o \ + intel_display.o \ + intel_crt.o \ + intel_lvds.o \ + intel_bios.o \ + intel_sdvo.o \ + intel_modes.o \ + intel_i2c.o \ + intel_fb.o \ + intel_tv.o \ + intel_dvo.o \ + dvo_ch7xxx.o \ + dvo_ch7017.o \ + dvo_ivch.o \ + dvo_tfp410.o \ + dvo_sil164.o i915-$(CONFIG_ACPI) += i915_opregion.o i915-$(CONFIG_COMPAT) += i915_ioc32.o diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h new file mode 100644 index 000000000000..e747ac42fe3a --- /dev/null +++ b/drivers/gpu/drm/i915/dvo.h @@ -0,0 +1,157 @@ +/* + * Copyright © 2006 Eric Anholt + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _INTEL_DVO_H +#define _INTEL_DVO_H + +#include <linux/i2c.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" + +struct intel_dvo_device { + char *name; + int type; + /* DVOA/B/C output register */ + u32 dvo_reg; + /* GPIO register used for i2c bus to control this device */ + u32 gpio; + int slave_addr; + struct intel_i2c_chan *i2c_bus; + + const struct intel_dvo_dev_ops *dev_ops; + void *dev_priv; + + struct drm_display_mode *panel_fixed_mode; + bool panel_wants_dither; +}; + +struct intel_dvo_dev_ops { + /* + * Initialize the device at startup time. + * Returns NULL if the device does not exist. + */ + bool (*init)(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus); + + /* + * Called to allow the output a chance to create properties after the + * RandR objects have been created. + */ + void (*create_resources)(struct intel_dvo_device *dvo); + + /* + * Turn on/off output or set intermediate power levels if available. + * + * Unsupported intermediate modes drop to the lower power setting. + * If the mode is DPMSModeOff, the output must be disabled, + * as the DPLL may be disabled afterwards. + */ + void (*dpms)(struct intel_dvo_device *dvo, int mode); + + /* + * Saves the output's state for restoration on VT switch. + */ + void (*save)(struct intel_dvo_device *dvo); + + /* + * Restore's the output's state at VT switch. + */ + void (*restore)(struct intel_dvo_device *dvo); + + /* + * Callback for testing a video mode for a given output. + * + * This function should only check for cases where a mode can't + * be supported on the output specifically, and not represent + * generic CRTC limitations. + * + * \return MODE_OK if the mode is valid, or another MODE_* otherwise. + */ + int (*mode_valid)(struct intel_dvo_device *dvo, + struct drm_display_mode *mode); + + /* + * Callback to adjust the mode to be set in the CRTC. + * + * This allows an output to adjust the clock or even the entire set of + * timings, which is used for panels with fixed timings or for + * buses with clock limitations. + */ + bool (*mode_fixup)(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + + /* + * Callback for preparing mode changes on an output + */ + void (*prepare)(struct intel_dvo_device *dvo); + + /* + * Callback for committing mode changes on an output + */ + void (*commit)(struct intel_dvo_device *dvo); + + /* + * Callback for setting up a video mode after fixups have been made. + * + * This is only called while the output is disabled. The dpms callback + * must be all that's necessary for the output, to turn the output on + * after this function is called. + */ + void (*mode_set)(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + + /* + * Probe for a connected output, and return detect_status. + */ + enum drm_connector_status (*detect)(struct intel_dvo_device *dvo); + + /** + * Query the device for the modes it provides. + * + * This function may also update MonInfo, mm_width, and mm_height. + * + * \return singly-linked list of modes or NULL if no modes found. + */ + struct drm_display_mode *(*get_modes)(struct intel_dvo_device *dvo); + + /** + * Clean up driver-specific bits of the output + */ + void (*destroy) (struct intel_dvo_device *dvo); + + /** + * Debugging hook to dump device registers to log file + */ + void (*dump_regs)(struct intel_dvo_device *dvo); +}; + +extern struct intel_dvo_dev_ops sil164_ops; +extern struct intel_dvo_dev_ops ch7xxx_ops; +extern struct intel_dvo_dev_ops ivch_ops; +extern struct intel_dvo_dev_ops tfp410_ops; +extern struct intel_dvo_dev_ops ch7017_ops; + +#endif /* _INTEL_DVO_H */ diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c new file mode 100644 index 000000000000..03d4b4973b02 --- /dev/null +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -0,0 +1,454 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include "dvo.h" + +#define CH7017_TV_DISPLAY_MODE 0x00 +#define CH7017_FLICKER_FILTER 0x01 +#define CH7017_VIDEO_BANDWIDTH 0x02 +#define CH7017_TEXT_ENHANCEMENT 0x03 +#define CH7017_START_ACTIVE_VIDEO 0x04 +#define CH7017_HORIZONTAL_POSITION 0x05 +#define CH7017_VERTICAL_POSITION 0x06 +#define CH7017_BLACK_LEVEL 0x07 +#define CH7017_CONTRAST_ENHANCEMENT 0x08 +#define CH7017_TV_PLL 0x09 +#define CH7017_TV_PLL_M 0x0a +#define CH7017_TV_PLL_N 0x0b +#define CH7017_SUB_CARRIER_0 0x0c +#define CH7017_CIV_CONTROL 0x10 +#define CH7017_CIV_0 0x11 +#define CH7017_CHROMA_BOOST 0x14 +#define CH7017_CLOCK_MODE 0x1c +#define CH7017_INPUT_CLOCK 0x1d +#define CH7017_GPIO_CONTROL 0x1e +#define CH7017_INPUT_DATA_FORMAT 0x1f +#define CH7017_CONNECTION_DETECT 0x20 +#define CH7017_DAC_CONTROL 0x21 +#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22 +#define CH7017_DEFEAT_VSYNC 0x47 +#define CH7017_TEST_PATTERN 0x48 + +#define CH7017_POWER_MANAGEMENT 0x49 +/** Enables the TV output path. */ +#define CH7017_TV_EN (1 << 0) +#define CH7017_DAC0_POWER_DOWN (1 << 1) +#define CH7017_DAC1_POWER_DOWN (1 << 2) +#define CH7017_DAC2_POWER_DOWN (1 << 3) +#define CH7017_DAC3_POWER_DOWN (1 << 4) +/** Powers down the TV out block, and DAC0-3 */ +#define CH7017_TV_POWER_DOWN_EN (1 << 5) + +#define CH7017_VERSION_ID 0x4a + +#define CH7017_DEVICE_ID 0x4b +#define CH7017_DEVICE_ID_VALUE 0x1b +#define CH7018_DEVICE_ID_VALUE 0x1a +#define CH7019_DEVICE_ID_VALUE 0x19 + +#define CH7017_XCLK_D2_ADJUST 0x53 +#define CH7017_UP_SCALER_COEFF_0 0x55 +#define CH7017_UP_SCALER_COEFF_1 0x56 +#define CH7017_UP_SCALER_COEFF_2 0x57 +#define CH7017_UP_SCALER_COEFF_3 0x58 +#define CH7017_UP_SCALER_COEFF_4 0x59 +#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a +#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b +#define CH7017_GPIO_INVERT 0x5c +#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d +#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f +/**< Low bits of horizontal active pixel input */ + +#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60 +/** High bits of horizontal active pixel input */ +#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0) +/** High bits of vertical active line output */ +#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3) + +#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61 +/**< Low bits of vertical active line output */ + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62 +/**< Low bits of horizontal active pixel output */ + +#define CH7017_LVDS_POWER_DOWN 0x63 +/** High bits of horizontal active pixel output */ +#define CH7017_LVDS_HAP_HIGH_MASK (0x7 << 0) +/** Enables the LVDS power down state transition */ +#define CH7017_LVDS_POWER_DOWN_EN (1 << 6) +/** Enables the LVDS upscaler */ +#define CH7017_LVDS_UPSCALER_EN (1 << 7) +#define CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED 0x08 + +#define CH7017_LVDS_ENCODING 0x64 +#define CH7017_LVDS_DITHER_2D (1 << 2) +#define CH7017_LVDS_DITHER_DIS (1 << 3) +#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4) +#define CH7017_LVDS_24_BIT (1 << 5) + +#define CH7017_LVDS_ENCODING_2 0x65 + +#define CH7017_LVDS_PLL_CONTROL 0x66 +/** Enables the LVDS panel output path */ +#define CH7017_LVDS_PANEN (1 << 0) +/** Enables the LVDS panel backlight */ +#define CH7017_LVDS_BKLEN (1 << 3) + +#define CH7017_POWER_SEQUENCING_T1 0x67 +#define CH7017_POWER_SEQUENCING_T2 0x68 +#define CH7017_POWER_SEQUENCING_T3 0x69 +#define CH7017_POWER_SEQUENCING_T4 0x6a +#define CH7017_POWER_SEQUENCING_T5 0x6b +#define CH7017_GPIO_DRIVER_TYPE 0x6c +#define CH7017_GPIO_DATA 0x6d +#define CH7017_GPIO_DIRECTION_CONTROL 0x6e + +#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71 +# define CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT 4 +# define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0 +# define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80 + +#define CH7017_LVDS_PLL_VCO_CONTROL 0x72 +# define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80 +# define CH7017_LVDS_PLL_VCO_SHIFT 4 +# define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0 + +#define CH7017_OUTPUTS_ENABLE 0x73 +# define CH7017_CHARGE_PUMP_LOW 0x0 +# define CH7017_CHARGE_PUMP_HIGH 0x3 +# define CH7017_LVDS_CHANNEL_A (1 << 3) +# define CH7017_LVDS_CHANNEL_B (1 << 4) +# define CH7017_TV_DAC_A (1 << 5) +# define CH7017_TV_DAC_B (1 << 6) +# define CH7017_DDC_SELECT_DC2 (1 << 7) + +#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74 +#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75 +#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76 + +#define CH7017_LVDS_CONTROL_2 0x78 +# define CH7017_LOOP_FILTER_SHIFT 5 +# define CH7017_PHASE_DETECTOR_SHIFT 0 + +#define CH7017_BANG_LIMIT_CONTROL 0x7f + +struct ch7017_priv { + uint8_t save_hapi; + uint8_t save_vali; + uint8_t save_valo; + uint8_t save_ailo; + uint8_t save_lvds_pll_vco; + uint8_t save_feedback_div; + uint8_t save_lvds_control_2; + uint8_t save_outputs_enable; + uint8_t save_lvds_power_down; + uint8_t save_power_management; +}; + +static void ch7017_dump_regs(struct intel_dvo_device *dvo); +static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); + +static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) +{ + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[2]; + u8 in_buf[2]; + + struct i2c_msg msgs[] = { + { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { + *val= in_buf[0]; + return true; + }; + + return false; +} + +static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) +{ + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + uint8_t out_buf[2]; + struct i2c_msg msg = { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = val; + + if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) + return true; + + return false; +} + +/** Probes for a CH7017 on the given bus and slave address. */ +static bool ch7017_init(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus) +{ + struct ch7017_priv *priv; + uint8_t val; + + priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); + if (priv == NULL) + return false; + + dvo->i2c_bus = i2cbus; + dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->dev_priv = priv; + + if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) + goto fail; + + if (val != CH7017_DEVICE_ID_VALUE && + val != CH7018_DEVICE_ID_VALUE && + val != CH7019_DEVICE_ID_VALUE) { + DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", + val, i2cbus->adapter.name,i2cbus->slave_addr); + goto fail; + } + + return true; +fail: + kfree(priv); + return false; +} + +static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo) +{ + return connector_status_unknown; +} + +static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo, + struct drm_display_mode *mode) +{ + if (mode->clock > 160000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void ch7017_mode_set(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + uint8_t lvds_pll_feedback_div, lvds_pll_vco_control; + uint8_t outputs_enable, lvds_control_2, lvds_power_down; + uint8_t horizontal_active_pixel_input; + uint8_t horizontal_active_pixel_output, vertical_active_line_output; + uint8_t active_input_line_output; + + DRM_DEBUG("Registers before mode setting\n"); + ch7017_dump_regs(dvo); + + /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/ + if (mode->clock < 100000) { + outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW; + lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED | + (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) | + (13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT); + lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED | + (2 << CH7017_LVDS_PLL_VCO_SHIFT) | + (3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT); + lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + } else { + outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH; + lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED | + (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) | + (3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT); + lvds_pll_feedback_div = 35; + lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + if (1) { /* XXX: dual channel panel detection. Assume yes for now. */ + outputs_enable |= CH7017_LVDS_CHANNEL_B; + lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED | + (2 << CH7017_LVDS_PLL_VCO_SHIFT) | + (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT); + } else { + lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED | + (1 << CH7017_LVDS_PLL_VCO_SHIFT) | + (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT); + } + } + + horizontal_active_pixel_input = mode->hdisplay & 0x00ff; + + vertical_active_line_output = mode->vdisplay & 0x00ff; + horizontal_active_pixel_output = mode->hdisplay & 0x00ff; + + active_input_line_output = ((mode->hdisplay & 0x0700) >> 8) | + (((mode->vdisplay & 0x0700) >> 8) << 3); + + lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED | + (mode->hdisplay & 0x0700) >> 8; + + ch7017_dpms(dvo, DRM_MODE_DPMS_OFF); + ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, + horizontal_active_pixel_input); + ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT, + horizontal_active_pixel_output); + ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, + vertical_active_line_output); + ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT, + active_input_line_output); + ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control); + ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div); + ch7017_write(dvo, CH7017_LVDS_CONTROL_2, lvds_control_2); + ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, outputs_enable); + + /* Turn the LVDS back on with new settings. */ + ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down); + + DRM_DEBUG("Registers after mode setting\n"); + ch7017_dump_regs(dvo); +} + +/* set the CH7017 power state */ +static void ch7017_dpms(struct intel_dvo_device *dvo, int mode) +{ + uint8_t val; + + ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val); + + /* Turn off TV/VGA, and never turn it on since we don't support it. */ + ch7017_write(dvo, CH7017_POWER_MANAGEMENT, + CH7017_DAC0_POWER_DOWN | + CH7017_DAC1_POWER_DOWN | + CH7017_DAC2_POWER_DOWN | + CH7017_DAC3_POWER_DOWN | + CH7017_TV_POWER_DOWN_EN); + + if (mode == DRM_MODE_DPMS_ON) { + /* Turn on the LVDS */ + ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, + val & ~CH7017_LVDS_POWER_DOWN_EN); + } else { + /* Turn off the LVDS */ + ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, + val | CH7017_LVDS_POWER_DOWN_EN); + } + + /* XXX: Should actually wait for update power status somehow */ + udelay(20000); +} + +static void ch7017_dump_regs(struct intel_dvo_device *dvo) +{ + uint8_t val; + +#define DUMP(reg) \ +do { \ + ch7017_read(dvo, reg, &val); \ + DRM_DEBUG(#reg ": %02x\n", val); \ +} while (0) + + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT); + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT); + DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT); + DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT); + DUMP(CH7017_LVDS_PLL_VCO_CONTROL); + DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV); + DUMP(CH7017_LVDS_CONTROL_2); + DUMP(CH7017_OUTPUTS_ENABLE); + DUMP(CH7017_LVDS_POWER_DOWN); +} + +static void ch7017_save(struct intel_dvo_device *dvo) +{ + struct ch7017_priv *priv = dvo->dev_priv; + + ch7017_read(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi); + ch7017_read(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo); + ch7017_read(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT, &priv->save_ailo); + ch7017_read(dvo, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco); + ch7017_read(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div); + ch7017_read(dvo, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2); + ch7017_read(dvo, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable); + ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down); + ch7017_read(dvo, CH7017_POWER_MANAGEMENT, &priv->save_power_management); +} + +static void ch7017_restore(struct intel_dvo_device *dvo) +{ + struct ch7017_priv *priv = dvo->dev_priv; + + /* Power down before changing mode */ + ch7017_dpms(dvo, DRM_MODE_DPMS_OFF); + + ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi); + ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo); + ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT, priv->save_ailo); + ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco); + ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div); + ch7017_write(dvo, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2); + ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable); + ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down); + ch7017_write(dvo, CH7017_POWER_MANAGEMENT, priv->save_power_management); +} + +static void ch7017_destroy(struct intel_dvo_device *dvo) +{ + struct ch7017_priv *priv = dvo->dev_priv; + + if (priv) { + kfree(priv); + dvo->dev_priv = NULL; + } +} + +struct intel_dvo_dev_ops ch7017_ops = { + .init = ch7017_init, + .detect = ch7017_detect, + .mode_valid = ch7017_mode_valid, + .mode_set = ch7017_mode_set, + .dpms = ch7017_dpms, + .dump_regs = ch7017_dump_regs, + .save = ch7017_save, + .restore = ch7017_restore, + .destroy = ch7017_destroy, +}; diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c new file mode 100644 index 000000000000..d2fd95dbd034 --- /dev/null +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -0,0 +1,368 @@ +/************************************************************************** + +Copyright © 2006 Dave Airlie + +All Rights Reserved. + +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, sub license, 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 NON-INFRINGEMENT. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "dvo.h" + +#define CH7xxx_REG_VID 0x4a +#define CH7xxx_REG_DID 0x4b + +#define CH7011_VID 0x83 /* 7010 as well */ +#define CH7009A_VID 0x84 +#define CH7009B_VID 0x85 +#define CH7301_VID 0x95 + +#define CH7xxx_VID 0x84 +#define CH7xxx_DID 0x17 + +#define CH7xxx_NUM_REGS 0x4c + +#define CH7xxx_CM 0x1c +#define CH7xxx_CM_XCM (1<<0) +#define CH7xxx_CM_MCP (1<<2) +#define CH7xxx_INPUT_CLOCK 0x1d +#define CH7xxx_GPIO 0x1e +#define CH7xxx_GPIO_HPIR (1<<3) +#define CH7xxx_IDF 0x1f + +#define CH7xxx_IDF_HSP (1<<3) +#define CH7xxx_IDF_VSP (1<<4) + +#define CH7xxx_CONNECTION_DETECT 0x20 +#define CH7xxx_CDET_DVI (1<<5) + +#define CH7301_DAC_CNTL 0x21 +#define CH7301_HOTPLUG 0x23 +#define CH7xxx_TCTL 0x31 +#define CH7xxx_TVCO 0x32 +#define CH7xxx_TPCP 0x33 +#define CH7xxx_TPD 0x34 +#define CH7xxx_TPVT 0x35 +#define CH7xxx_TLPF 0x36 +#define CH7xxx_TCT 0x37 +#define CH7301_TEST_PATTERN 0x48 + +#define CH7xxx_PM 0x49 +#define CH7xxx_PM_FPD (1<<0) +#define CH7301_PM_DACPD0 (1<<1) +#define CH7301_PM_DACPD1 (1<<2) +#define CH7301_PM_DACPD2 (1<<3) +#define CH7xxx_PM_DVIL (1<<6) +#define CH7xxx_PM_DVIP (1<<7) + +#define CH7301_SYNC_POLARITY 0x56 +#define CH7301_SYNC_RGB_YUV (1<<0) +#define CH7301_SYNC_POL_DVI (1<<5) + +/** @file + * driver for the Chrontel 7xxx DVI chip over DVO. + */ + +static struct ch7xxx_id_struct { + uint8_t vid; + char *name; +} ch7xxx_ids[] = { + { CH7011_VID, "CH7011" }, + { CH7009A_VID, "CH7009A" }, + { CH7009B_VID, "CH7009B" }, + { CH7301_VID, "CH7301" }, +}; + +struct ch7xxx_reg_state { + uint8_t regs[CH7xxx_NUM_REGS]; +}; + +struct ch7xxx_priv { + bool quiet; + + struct ch7xxx_reg_state save_reg; + struct ch7xxx_reg_state mode_reg; + uint8_t save_TCTL, save_TPCP, save_TPD, save_TPVT; + uint8_t save_TLPF, save_TCT, save_PM, save_IDF; +}; + +static void ch7xxx_save(struct intel_dvo_device *dvo); + +static char *ch7xxx_get_id(uint8_t vid) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ch7xxx_ids); i++) { + if (ch7xxx_ids[i].vid == vid) + return ch7xxx_ids[i].name; + } + + return NULL; +} + +/** Reads an 8 bit register */ +static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) +{ + struct ch7xxx_priv *ch7xxx= dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[2]; + u8 in_buf[2]; + + struct i2c_msg msgs[] = { + { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { + *ch = in_buf[0]; + return true; + }; + + if (!ch7xxx->quiet) { + DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + return false; +} + +/** Writes an 8 bit register */ +static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) +{ + struct ch7xxx_priv *ch7xxx = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + uint8_t out_buf[2]; + struct i2c_msg msg = { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = ch; + + if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) + return true; + + if (!ch7xxx->quiet) { + DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + + return false; +} + +static bool ch7xxx_init(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus) +{ + /* this will detect the CH7xxx chip on the specified i2c bus */ + struct ch7xxx_priv *ch7xxx; + uint8_t vendor, device; + char *name; + + ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL); + if (ch7xxx == NULL) + return false; + + dvo->i2c_bus = i2cbus; + dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->dev_priv = ch7xxx; + ch7xxx->quiet = true; + + if (!ch7xxx_readb(dvo, CH7xxx_REG_VID, &vendor)) + goto out; + + name = ch7xxx_get_id(vendor); + if (!name) { + DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", + vendor, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + + + if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device)) + goto out; + + if (device != CH7xxx_DID) { + DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", + vendor, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + + ch7xxx->quiet = false; + DRM_DEBUG("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n", + name, vendor, device); + return true; +out: + kfree(ch7xxx); + return false; +} + +static enum drm_connector_status ch7xxx_detect(struct intel_dvo_device *dvo) +{ + uint8_t cdet, orig_pm, pm; + + ch7xxx_readb(dvo, CH7xxx_PM, &orig_pm); + + pm = orig_pm; + pm &= ~CH7xxx_PM_FPD; + pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP; + + ch7xxx_writeb(dvo, CH7xxx_PM, pm); + + ch7xxx_readb(dvo, CH7xxx_CONNECTION_DETECT, &cdet); + + ch7xxx_writeb(dvo, CH7xxx_PM, orig_pm); + + if (cdet & CH7xxx_CDET_DVI) + return connector_status_connected; + return connector_status_disconnected; +} + +static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo, + struct drm_display_mode *mode) +{ + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void ch7xxx_mode_set(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + uint8_t tvco, tpcp, tpd, tlpf, idf; + + if (mode->clock <= 65000) { + tvco = 0x23; + tpcp = 0x08; + tpd = 0x16; + tlpf = 0x60; + } else { + tvco = 0x2d; + tpcp = 0x06; + tpd = 0x26; + tlpf = 0xa0; + } + + ch7xxx_writeb(dvo, CH7xxx_TCTL, 0x00); + ch7xxx_writeb(dvo, CH7xxx_TVCO, tvco); + ch7xxx_writeb(dvo, CH7xxx_TPCP, tpcp); + ch7xxx_writeb(dvo, CH7xxx_TPD, tpd); + ch7xxx_writeb(dvo, CH7xxx_TPVT, 0x30); + ch7xxx_writeb(dvo, CH7xxx_TLPF, tlpf); + ch7xxx_writeb(dvo, CH7xxx_TCT, 0x00); + + ch7xxx_readb(dvo, CH7xxx_IDF, &idf); + + idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP); + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + idf |= CH7xxx_IDF_HSP; + + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + idf |= CH7xxx_IDF_HSP; + + ch7xxx_writeb(dvo, CH7xxx_IDF, idf); +} + +/* set the CH7xxx power state */ +static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode) +{ + if (mode == DRM_MODE_DPMS_ON) + ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP); + else + ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD); +} + +static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) +{ + struct ch7xxx_priv *ch7xxx = dvo->dev_priv; + int i; + + for (i = 0; i < CH7xxx_NUM_REGS; i++) { + if ((i % 8) == 0 ) + DRM_DEBUG("\n %02X: ", i); + DRM_DEBUG("%02X ", ch7xxx->mode_reg.regs[i]); + } +} + +static void ch7xxx_save(struct intel_dvo_device *dvo) +{ + struct ch7xxx_priv *ch7xxx= dvo->dev_priv; + + ch7xxx_readb(dvo, CH7xxx_TCTL, &ch7xxx->save_TCTL); + ch7xxx_readb(dvo, CH7xxx_TPCP, &ch7xxx->save_TPCP); + ch7xxx_readb(dvo, CH7xxx_TPD, &ch7xxx->save_TPD); + ch7xxx_readb(dvo, CH7xxx_TPVT, &ch7xxx->save_TPVT); + ch7xxx_readb(dvo, CH7xxx_TLPF, &ch7xxx->save_TLPF); + ch7xxx_readb(dvo, CH7xxx_PM, &ch7xxx->save_PM); + ch7xxx_readb(dvo, CH7xxx_IDF, &ch7xxx->save_IDF); +} + +static void ch7xxx_restore(struct intel_dvo_device *dvo) +{ + struct ch7xxx_priv *ch7xxx = dvo->dev_priv; + + ch7xxx_writeb(dvo, CH7xxx_TCTL, ch7xxx->save_TCTL); + ch7xxx_writeb(dvo, CH7xxx_TPCP, ch7xxx->save_TPCP); + ch7xxx_writeb(dvo, CH7xxx_TPD, ch7xxx->save_TPD); + ch7xxx_writeb(dvo, CH7xxx_TPVT, ch7xxx->save_TPVT); + ch7xxx_writeb(dvo, CH7xxx_TLPF, ch7xxx->save_TLPF); + ch7xxx_writeb(dvo, CH7xxx_IDF, ch7xxx->save_IDF); + ch7xxx_writeb(dvo, CH7xxx_PM, ch7xxx->save_PM); +} + +static void ch7xxx_destroy(struct intel_dvo_device *dvo) +{ + struct ch7xxx_priv *ch7xxx = dvo->dev_priv; + + if (ch7xxx) { + kfree(ch7xxx); + dvo->dev_priv = NULL; + } +} + +struct intel_dvo_dev_ops ch7xxx_ops = { + .init = ch7xxx_init, + .detect = ch7xxx_detect, + .mode_valid = ch7xxx_mode_valid, + .mode_set = ch7xxx_mode_set, + .dpms = ch7xxx_dpms, + .dump_regs = ch7xxx_dump_regs, + .save = ch7xxx_save, + .restore = ch7xxx_restore, + .destroy = ch7xxx_destroy, +}; diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c new file mode 100644 index 000000000000..0c8d375e8e37 --- /dev/null +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -0,0 +1,442 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include "dvo.h" + +/* + * register definitions for the i82807aa. + * + * Documentation on this chipset can be found in datasheet #29069001 at + * intel.com. + */ + +/* + * VCH Revision & GMBus Base Addr + */ +#define VR00 0x00 +# define VR00_BASE_ADDRESS_MASK 0x007f + +/* + * Functionality Enable + */ +#define VR01 0x01 + +/* + * Enable the panel fitter + */ +# define VR01_PANEL_FIT_ENABLE (1 << 3) +/* + * Enables the LCD display. + * + * This must not be set while VR01_DVO_BYPASS_ENABLE is set. + */ +# define VR01_LCD_ENABLE (1 << 2) +/** Enables the DVO repeater. */ +# define VR01_DVO_BYPASS_ENABLE (1 << 1) +/** Enables the DVO clock */ +# define VR01_DVO_ENABLE (1 << 0) + +/* + * LCD Interface Format + */ +#define VR10 0x10 +/** Enables LVDS output instead of CMOS */ +# define VR10_LVDS_ENABLE (1 << 4) +/** Enables 18-bit LVDS output. */ +# define VR10_INTERFACE_1X18 (0 << 2) +/** Enables 24-bit LVDS or CMOS output */ +# define VR10_INTERFACE_1X24 (1 << 2) +/** Enables 2x18-bit LVDS or CMOS output. */ +# define VR10_INTERFACE_2X18 (2 << 2) +/** Enables 2x24-bit LVDS output */ +# define VR10_INTERFACE_2X24 (3 << 2) + +/* + * VR20 LCD Horizontal Display Size + */ +#define VR20 0x20 + +/* + * LCD Vertical Display Size + */ +#define VR21 0x20 + +/* + * Panel power down status + */ +#define VR30 0x30 +/** Read only bit indicating that the panel is not in a safe poweroff state. */ +# define VR30_PANEL_ON (1 << 15) + +#define VR40 0x40 +# define VR40_STALL_ENABLE (1 << 13) +# define VR40_VERTICAL_INTERP_ENABLE (1 << 12) +# define VR40_ENHANCED_PANEL_FITTING (1 << 11) +# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10) +# define VR40_AUTO_RATIO_ENABLE (1 << 9) +# define VR40_CLOCK_GATING_ENABLE (1 << 8) + +/* + * Panel Fitting Vertical Ratio + * (((image_height - 1) << 16) / ((panel_height - 1))) >> 2 + */ +#define VR41 0x41 + +/* + * Panel Fitting Horizontal Ratio + * (((image_width - 1) << 16) / ((panel_width - 1))) >> 2 + */ +#define VR42 0x42 + +/* + * Horizontal Image Size + */ +#define VR43 0x43 + +/* VR80 GPIO 0 + */ +#define VR80 0x80 +#define VR81 0x81 +#define VR82 0x82 +#define VR83 0x83 +#define VR84 0x84 +#define VR85 0x85 +#define VR86 0x86 +#define VR87 0x87 + +/* VR88 GPIO 8 + */ +#define VR88 0x88 + +/* Graphics BIOS scratch 0 + */ +#define VR8E 0x8E +# define VR8E_PANEL_TYPE_MASK (0xf << 0) +# define VR8E_PANEL_INTERFACE_CMOS (0 << 4) +# define VR8E_PANEL_INTERFACE_LVDS (1 << 4) +# define VR8E_FORCE_DEFAULT_PANEL (1 << 5) + +/* Graphics BIOS scratch 1 + */ +#define VR8F 0x8F +# define VR8F_VCH_PRESENT (1 << 0) +# define VR8F_DISPLAY_CONN (1 << 1) +# define VR8F_POWER_MASK (0x3c) +# define VR8F_POWER_POS (2) + + +struct ivch_priv { + bool quiet; + + uint16_t width, height; + + uint16_t save_VR01; + uint16_t save_VR40; +}; + + +static void ivch_dump_regs(struct intel_dvo_device *dvo); + +/** + * Reads a register on the ivch. + * + * Each of the 256 registers are 16 bits long. + */ +static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) +{ + struct ivch_priv *priv = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[1]; + u8 in_buf[2]; + + struct i2c_msg msgs[] = { + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD, + .len = 0, + }, + { + .addr = 0, + .flags = I2C_M_NOSTART, + .len = 1, + .buf = out_buf, + }, + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD | I2C_M_NOSTART, + .len = 2, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + + if (i2c_transfer(&i2cbus->adapter, msgs, 3) == 3) { + *data = (in_buf[1] << 8) | in_buf[0]; + return true; + }; + + if (!priv->quiet) { + DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + return false; +} + +/** Writes a 16-bit register on the ivch */ +static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) +{ + struct ivch_priv *priv = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[3]; + struct i2c_msg msg = { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 3, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = data & 0xff; + out_buf[2] = data >> 8; + + if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) + return true; + + if (!priv->quiet) { + DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + + return false; +} + +/** Probes the given bus and slave address for an ivch */ +static bool ivch_init(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus) +{ + struct ivch_priv *priv; + uint16_t temp; + + priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL); + if (priv == NULL) + return false; + + dvo->i2c_bus = i2cbus; + dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->dev_priv = priv; + priv->quiet = true; + + if (!ivch_read(dvo, VR00, &temp)) + goto out; + priv->quiet = false; + + /* Since the identification bits are probably zeroes, which doesn't seem + * very unique, check that the value in the base address field matches + * the address it's responding on. + */ + if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) { + DRM_DEBUG("ivch detect failed due to address mismatch " + "(%d vs %d)\n", + (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr); + goto out; + } + + ivch_read(dvo, VR20, &priv->width); + ivch_read(dvo, VR21, &priv->height); + + return true; + +out: + kfree(priv); + return false; +} + +static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo) +{ + return connector_status_connected; +} + +static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo, + struct drm_display_mode *mode) +{ + if (mode->clock > 112000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/** Sets the power state of the panel connected to the ivch */ +static void ivch_dpms(struct intel_dvo_device *dvo, int mode) +{ + int i; + uint16_t vr01, vr30, backlight; + + /* Set the new power state of the panel. */ + if (!ivch_read(dvo, VR01, &vr01)) + return; + + if (mode == DRM_MODE_DPMS_ON) + backlight = 1; + else + backlight = 0; + ivch_write(dvo, VR80, backlight); + + if (mode == DRM_MODE_DPMS_ON) + vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE; + else + vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE); + + ivch_write(dvo, VR01, vr01); + + /* Wait for the panel to make its state transition */ + for (i = 0; i < 100; i++) { + if (!ivch_read(dvo, VR30, &vr30)) + break; + + if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DRM_MODE_DPMS_ON)) + break; + udelay(1000); + } + /* wait some more; vch may fail to resync sometimes without this */ + udelay(16 * 1000); +} + +static void ivch_mode_set(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + uint16_t vr40 = 0; + uint16_t vr01; + + vr01 = 0; + vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE | + VR40_HORIZONTAL_INTERP_ENABLE); + + if (mode->hdisplay != adjusted_mode->hdisplay || + mode->vdisplay != adjusted_mode->vdisplay) { + uint16_t x_ratio, y_ratio; + + vr01 |= VR01_PANEL_FIT_ENABLE; + vr40 |= VR40_CLOCK_GATING_ENABLE; + x_ratio = (((mode->hdisplay - 1) << 16) / + (adjusted_mode->hdisplay - 1)) >> 2; + y_ratio = (((mode->vdisplay - 1) << 16) / + (adjusted_mode->vdisplay - 1)) >> 2; + ivch_write (dvo, VR42, x_ratio); + ivch_write (dvo, VR41, y_ratio); + } else { + vr01 &= ~VR01_PANEL_FIT_ENABLE; + vr40 &= ~VR40_CLOCK_GATING_ENABLE; + } + vr40 &= ~VR40_AUTO_RATIO_ENABLE; + + ivch_write(dvo, VR01, vr01); + ivch_write(dvo, VR40, vr40); + + ivch_dump_regs(dvo); +} + +static void ivch_dump_regs(struct intel_dvo_device *dvo) +{ + uint16_t val; + + ivch_read(dvo, VR00, &val); + DRM_DEBUG("VR00: 0x%04x\n", val); + ivch_read(dvo, VR01, &val); + DRM_DEBUG("VR01: 0x%04x\n", val); + ivch_read(dvo, VR30, &val); + DRM_DEBUG("VR30: 0x%04x\n", val); + ivch_read(dvo, VR40, &val); + DRM_DEBUG("VR40: 0x%04x\n", val); + + /* GPIO registers */ + ivch_read(dvo, VR80, &val); + DRM_DEBUG("VR80: 0x%04x\n", val); + ivch_read(dvo, VR81, &val); + DRM_DEBUG("VR81: 0x%04x\n", val); + ivch_read(dvo, VR82, &val); + DRM_DEBUG("VR82: 0x%04x\n", val); + ivch_read(dvo, VR83, &val); + DRM_DEBUG("VR83: 0x%04x\n", val); + ivch_read(dvo, VR84, &val); + DRM_DEBUG("VR84: 0x%04x\n", val); + ivch_read(dvo, VR85, &val); + DRM_DEBUG("VR85: 0x%04x\n", val); + ivch_read(dvo, VR86, &val); + DRM_DEBUG("VR86: 0x%04x\n", val); + ivch_read(dvo, VR87, &val); + DRM_DEBUG("VR87: 0x%04x\n", val); + ivch_read(dvo, VR88, &val); + DRM_DEBUG("VR88: 0x%04x\n", val); + + /* Scratch register 0 - AIM Panel type */ + ivch_read(dvo, VR8E, &val); + DRM_DEBUG("VR8E: 0x%04x\n", val); + + /* Scratch register 1 - Status register */ + ivch_read(dvo, VR8F, &val); + DRM_DEBUG("VR8F: 0x%04x\n", val); +} + +static void ivch_save(struct intel_dvo_device *dvo) +{ + struct ivch_priv *priv = dvo->dev_priv; + + ivch_read(dvo, VR01, &priv->save_VR01); + ivch_read(dvo, VR40, &priv->save_VR40); +} + +static void ivch_restore(struct intel_dvo_device *dvo) +{ + struct ivch_priv *priv = dvo->dev_priv; + + ivch_write(dvo, VR01, priv->save_VR01); + ivch_write(dvo, VR40, priv->save_VR40); +} + +static void ivch_destroy(struct intel_dvo_device *dvo) +{ + struct ivch_priv *priv = dvo->dev_priv; + + if (priv) { + kfree(priv); + dvo->dev_priv = NULL; + } +} + +struct intel_dvo_dev_ops ivch_ops= { + .init = ivch_init, + .dpms = ivch_dpms, + .save = ivch_save, + .restore = ivch_restore, + .mode_valid = ivch_mode_valid, + .mode_set = ivch_mode_set, + .detect = ivch_detect, + .dump_regs = ivch_dump_regs, + .destroy = ivch_destroy, +}; diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c new file mode 100644 index 000000000000..033a4bb070b2 --- /dev/null +++ b/drivers/gpu/drm/i915/dvo_sil164.c @@ -0,0 +1,302 @@ +/************************************************************************** + +Copyright © 2006 Dave Airlie + +All Rights Reserved. + +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, sub license, 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 NON-INFRINGEMENT. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "dvo.h" + +#define SIL164_VID 0x0001 +#define SIL164_DID 0x0006 + +#define SIL164_VID_LO 0x00 +#define SIL164_VID_HI 0x01 +#define SIL164_DID_LO 0x02 +#define SIL164_DID_HI 0x03 +#define SIL164_REV 0x04 +#define SIL164_RSVD 0x05 +#define SIL164_FREQ_LO 0x06 +#define SIL164_FREQ_HI 0x07 + +#define SIL164_REG8 0x08 +#define SIL164_8_VEN (1<<5) +#define SIL164_8_HEN (1<<4) +#define SIL164_8_DSEL (1<<3) +#define SIL164_8_BSEL (1<<2) +#define SIL164_8_EDGE (1<<1) +#define SIL164_8_PD (1<<0) + +#define SIL164_REG9 0x09 +#define SIL164_9_VLOW (1<<7) +#define SIL164_9_MSEL_MASK (0x7<<4) +#define SIL164_9_TSEL (1<<3) +#define SIL164_9_RSEN (1<<2) +#define SIL164_9_HTPLG (1<<1) +#define SIL164_9_MDI (1<<0) + +#define SIL164_REGC 0x0c + +struct sil164_save_rec { + uint8_t reg8; + uint8_t reg9; + uint8_t regc; +}; + +struct sil164_priv { + //I2CDevRec d; + bool quiet; + struct sil164_save_rec save_regs; + struct sil164_save_rec mode_regs; +}; + +#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr)) + +static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) +{ + struct sil164_priv *sil = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[2]; + u8 in_buf[2]; + + struct i2c_msg msgs[] = { + { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { + *ch = in_buf[0]; + return true; + }; + + if (!sil->quiet) { + DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + return false; +} + +static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) +{ + struct sil164_priv *sil= dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + uint8_t out_buf[2]; + struct i2c_msg msg = { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = ch; + + if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) + return true; + + if (!sil->quiet) { + DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + + return false; +} + +/* Silicon Image 164 driver for chip on i2c bus */ +static bool sil164_init(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus) +{ + /* this will detect the SIL164 chip on the specified i2c bus */ + struct sil164_priv *sil; + unsigned char ch; + + sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL); + if (sil == NULL) + return false; + + dvo->i2c_bus = i2cbus; + dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->dev_priv = sil; + sil->quiet = true; + + if (!sil164_readb(dvo, SIL164_VID_LO, &ch)) + goto out; + + if (ch != (SIL164_VID & 0xff)) { + DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", + ch, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + + if (!sil164_readb(dvo, SIL164_DID_LO, &ch)) + goto out; + + if (ch != (SIL164_DID & 0xff)) { + DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", + ch, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + sil->quiet = false; + + DRM_DEBUG("init sil164 dvo controller successfully!\n"); + return true; + +out: + kfree(sil); + return false; +} + +static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo) +{ + uint8_t reg9; + + sil164_readb(dvo, SIL164_REG9, ®9); + + if (reg9 & SIL164_9_HTPLG) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo, + struct drm_display_mode *mode) +{ + return MODE_OK; +} + +static void sil164_mode_set(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* As long as the basics are set up, since we don't have clock + * dependencies in the mode setup, we can just leave the + * registers alone and everything will work fine. + */ + /* recommended programming sequence from doc */ + /*sil164_writeb(sil, 0x08, 0x30); + sil164_writeb(sil, 0x09, 0x00); + sil164_writeb(sil, 0x0a, 0x90); + sil164_writeb(sil, 0x0c, 0x89); + sil164_writeb(sil, 0x08, 0x31);*/ + /* don't do much */ + return; +} + +/* set the SIL164 power state */ +static void sil164_dpms(struct intel_dvo_device *dvo, int mode) +{ + int ret; + unsigned char ch; + + ret = sil164_readb(dvo, SIL164_REG8, &ch); + if (ret == false) + return; + + if (mode == DRM_MODE_DPMS_ON) + ch |= SIL164_8_PD; + else + ch &= ~SIL164_8_PD; + + sil164_writeb(dvo, SIL164_REG8, ch); + return; +} + +static void sil164_dump_regs(struct intel_dvo_device *dvo) +{ + uint8_t val; + + sil164_readb(dvo, SIL164_FREQ_LO, &val); + DRM_DEBUG("SIL164_FREQ_LO: 0x%02x\n", val); + sil164_readb(dvo, SIL164_FREQ_HI, &val); + DRM_DEBUG("SIL164_FREQ_HI: 0x%02x\n", val); + sil164_readb(dvo, SIL164_REG8, &val); + DRM_DEBUG("SIL164_REG8: 0x%02x\n", val); + sil164_readb(dvo, SIL164_REG9, &val); + DRM_DEBUG("SIL164_REG9: 0x%02x\n", val); + sil164_readb(dvo, SIL164_REGC, &val); + DRM_DEBUG("SIL164_REGC: 0x%02x\n", val); +} + +static void sil164_save(struct intel_dvo_device *dvo) +{ + struct sil164_priv *sil= dvo->dev_priv; + + if (!sil164_readb(dvo, SIL164_REG8, &sil->save_regs.reg8)) + return; + + if (!sil164_readb(dvo, SIL164_REG9, &sil->save_regs.reg9)) + return; + + if (!sil164_readb(dvo, SIL164_REGC, &sil->save_regs.regc)) + return; + + return; +} + +static void sil164_restore(struct intel_dvo_device *dvo) +{ + struct sil164_priv *sil = dvo->dev_priv; + + /* Restore it powered down initially */ + sil164_writeb(dvo, SIL164_REG8, sil->save_regs.reg8 & ~0x1); + + sil164_writeb(dvo, SIL164_REG9, sil->save_regs.reg9); + sil164_writeb(dvo, SIL164_REGC, sil->save_regs.regc); + sil164_writeb(dvo, SIL164_REG8, sil->save_regs.reg8); +} + +static void sil164_destroy(struct intel_dvo_device *dvo) +{ + struct sil164_priv *sil = dvo->dev_priv; + + if (sil) { + kfree(sil); + dvo->dev_priv = NULL; + } +} + +struct intel_dvo_dev_ops sil164_ops = { + .init = sil164_init, + .detect = sil164_detect, + .mode_valid = sil164_mode_valid, + .mode_set = sil164_mode_set, + .dpms = sil164_dpms, + .dump_regs = sil164_dump_regs, + .save = sil164_save, + .restore = sil164_restore, + .destroy = sil164_destroy, +}; diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c new file mode 100644 index 000000000000..207fda806ebf --- /dev/null +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -0,0 +1,335 @@ +/* + * Copyright © 2007 Dave Mueller + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Dave Mueller <dave.mueller@gmx.ch> + * + */ + +#include "dvo.h" + +/* register definitions according to the TFP410 data sheet */ +#define TFP410_VID 0x014C +#define TFP410_DID 0x0410 + +#define TFP410_VID_LO 0x00 +#define TFP410_VID_HI 0x01 +#define TFP410_DID_LO 0x02 +#define TFP410_DID_HI 0x03 +#define TFP410_REV 0x04 + +#define TFP410_CTL_1 0x08 +#define TFP410_CTL_1_TDIS (1<<6) +#define TFP410_CTL_1_VEN (1<<5) +#define TFP410_CTL_1_HEN (1<<4) +#define TFP410_CTL_1_DSEL (1<<3) +#define TFP410_CTL_1_BSEL (1<<2) +#define TFP410_CTL_1_EDGE (1<<1) +#define TFP410_CTL_1_PD (1<<0) + +#define TFP410_CTL_2 0x09 +#define TFP410_CTL_2_VLOW (1<<7) +#define TFP410_CTL_2_MSEL_MASK (0x7<<4) +#define TFP410_CTL_2_MSEL (1<<4) +#define TFP410_CTL_2_TSEL (1<<3) +#define TFP410_CTL_2_RSEN (1<<2) +#define TFP410_CTL_2_HTPLG (1<<1) +#define TFP410_CTL_2_MDI (1<<0) + +#define TFP410_CTL_3 0x0A +#define TFP410_CTL_3_DK_MASK (0x7<<5) +#define TFP410_CTL_3_DK (1<<5) +#define TFP410_CTL_3_DKEN (1<<4) +#define TFP410_CTL_3_CTL_MASK (0x7<<1) +#define TFP410_CTL_3_CTL (1<<1) + +#define TFP410_USERCFG 0x0B + +#define TFP410_DE_DLY 0x32 + +#define TFP410_DE_CTL 0x33 +#define TFP410_DE_CTL_DEGEN (1<<6) +#define TFP410_DE_CTL_VSPOL (1<<5) +#define TFP410_DE_CTL_HSPOL (1<<4) +#define TFP410_DE_CTL_DEDLY8 (1<<0) + +#define TFP410_DE_TOP 0x34 + +#define TFP410_DE_CNT_LO 0x36 +#define TFP410_DE_CNT_HI 0x37 + +#define TFP410_DE_LIN_LO 0x38 +#define TFP410_DE_LIN_HI 0x39 + +#define TFP410_H_RES_LO 0x3A +#define TFP410_H_RES_HI 0x3B + +#define TFP410_V_RES_LO 0x3C +#define TFP410_V_RES_HI 0x3D + +struct tfp410_save_rec { + uint8_t ctl1; + uint8_t ctl2; +}; + +struct tfp410_priv { + bool quiet; + + struct tfp410_save_rec saved_reg; + struct tfp410_save_rec mode_reg; +}; + +static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) +{ + struct tfp410_priv *tfp = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + u8 out_buf[2]; + u8 in_buf[2]; + + struct i2c_msg msgs[] = { + { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = i2cbus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = in_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { + *ch = in_buf[0]; + return true; + }; + + if (!tfp->quiet) { + DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + return false; +} + +static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) +{ + struct tfp410_priv *tfp = dvo->dev_priv; + struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + uint8_t out_buf[2]; + struct i2c_msg msg = { + .addr = i2cbus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + }; + + out_buf[0] = addr; + out_buf[1] = ch; + + if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) + return true; + + if (!tfp->quiet) { + DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", + addr, i2cbus->adapter.name, i2cbus->slave_addr); + } + + return false; +} + +static int tfp410_getid(struct intel_dvo_device *dvo, int addr) +{ + uint8_t ch1, ch2; + + if (tfp410_readb(dvo, addr+0, &ch1) && + tfp410_readb(dvo, addr+1, &ch2)) + return ((ch2 << 8) & 0xFF00) | (ch1 & 0x00FF); + + return -1; +} + +/* Ti TFP410 driver for chip on i2c bus */ +static bool tfp410_init(struct intel_dvo_device *dvo, + struct intel_i2c_chan *i2cbus) +{ + /* this will detect the tfp410 chip on the specified i2c bus */ + struct tfp410_priv *tfp; + int id; + + tfp = kzalloc(sizeof(struct tfp410_priv), GFP_KERNEL); + if (tfp == NULL) + return false; + + dvo->i2c_bus = i2cbus; + dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->dev_priv = tfp; + tfp->quiet = true; + + if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { + DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", + id, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + + if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { + DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", + id, i2cbus->adapter.name, i2cbus->slave_addr); + goto out; + } + tfp->quiet = false; + return true; +out: + kfree(tfp); + return false; +} + +static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo) +{ + enum drm_connector_status ret = connector_status_disconnected; + uint8_t ctl2; + + if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) { + if (ctl2 & TFP410_CTL_2_HTPLG) + ret = connector_status_connected; + else + ret = connector_status_disconnected; + } + + return ret; +} + +static enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo, + struct drm_display_mode *mode) +{ + return MODE_OK; +} + +static void tfp410_mode_set(struct intel_dvo_device *dvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* As long as the basics are set up, since we don't have clock dependencies + * in the mode setup, we can just leave the registers alone and everything + * will work fine. + */ + /* don't do much */ + return; +} + +/* set the tfp410 power state */ +static void tfp410_dpms(struct intel_dvo_device *dvo, int mode) +{ + uint8_t ctl1; + + if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1)) + return; + + if (mode == DRM_MODE_DPMS_ON) + ctl1 |= TFP410_CTL_1_PD; + else + ctl1 &= ~TFP410_CTL_1_PD; + + tfp410_writeb(dvo, TFP410_CTL_1, ctl1); +} + +static void tfp410_dump_regs(struct intel_dvo_device *dvo) +{ + uint8_t val, val2; + + tfp410_readb(dvo, TFP410_REV, &val); + DRM_DEBUG("TFP410_REV: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_CTL_1, &val); + DRM_DEBUG("TFP410_CTL1: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_CTL_2, &val); + DRM_DEBUG("TFP410_CTL2: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_CTL_3, &val); + DRM_DEBUG("TFP410_CTL3: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_USERCFG, &val); + DRM_DEBUG("TFP410_USERCFG: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_DE_DLY, &val); + DRM_DEBUG("TFP410_DE_DLY: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_DE_CTL, &val); + DRM_DEBUG("TFP410_DE_CTL: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_DE_TOP, &val); + DRM_DEBUG("TFP410_DE_TOP: 0x%02X\n", val); + tfp410_readb(dvo, TFP410_DE_CNT_LO, &val); + tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2); + DRM_DEBUG("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); + tfp410_readb(dvo, TFP410_DE_LIN_LO, &val); + tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2); + DRM_DEBUG("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); + tfp410_readb(dvo, TFP410_H_RES_LO, &val); + tfp410_readb(dvo, TFP410_H_RES_HI, &val2); + DRM_DEBUG("TFP410_H_RES: 0x%02X%02X\n", val2, val); + tfp410_readb(dvo, TFP410_V_RES_LO, &val); + tfp410_readb(dvo, TFP410_V_RES_HI, &val2); + DRM_DEBUG("TFP410_V_RES: 0x%02X%02X\n", val2, val); +} + +static void tfp410_save(struct intel_dvo_device *dvo) +{ + struct tfp410_priv *tfp = dvo->dev_priv; + + if (!tfp410_readb(dvo, TFP410_CTL_1, &tfp->saved_reg.ctl1)) + return; + + if (!tfp410_readb(dvo, TFP410_CTL_2, &tfp->saved_reg.ctl2)) + return; +} + +static void tfp410_restore(struct intel_dvo_device *dvo) +{ + struct tfp410_priv *tfp = dvo->dev_priv; + + /* Restore it powered down initially */ + tfp410_writeb(dvo, TFP410_CTL_1, tfp->saved_reg.ctl1 & ~0x1); + + tfp410_writeb(dvo, TFP410_CTL_2, tfp->saved_reg.ctl2); + tfp410_writeb(dvo, TFP410_CTL_1, tfp->saved_reg.ctl1); +} + +static void tfp410_destroy(struct intel_dvo_device *dvo) +{ + struct tfp410_priv *tfp = dvo->dev_priv; + + if (tfp) { + kfree(tfp); + dvo->dev_priv = NULL; + } +} + +struct intel_dvo_dev_ops tfp410_ops = { + .init = tfp410_init, + .detect = tfp410_detect, + .mode_valid = tfp410_mode_valid, + .mode_set = tfp410_mode_set, + .dpms = tfp410_dpms, + .dump_regs = tfp410_dump_regs, + .save = tfp410_save, + .restore = tfp410_restore, + .destroy = tfp410_destroy, +}; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index afa8a12cd009..3d7082af5b72 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -28,6 +28,8 @@ #include "drmP.h" #include "drm.h" +#include "drm_crtc_helper.h" +#include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -39,6 +41,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; u32 last_acthd = I915_READ(acthd_reg); @@ -55,8 +58,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) if (ring->space >= n) return 0; - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + if (master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; if (ring->head != last_head) i = 0; @@ -121,16 +124,28 @@ static void i915_free_hws(struct drm_device *dev) void i915_kernel_lost_context(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); + /* + * We should never lose context on the ring with modesetting + * as we don't expose it to userspace + */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; - if (ring->head == ring->tail && dev_priv->sarea_priv) - dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; + if (!dev->primary->master) + return; + + master_priv = dev->primary->master->driver_priv; + if (ring->head == ring->tail && master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } static int i915_dma_cleanup(struct drm_device * dev) @@ -154,25 +169,13 @@ static int i915_dma_cleanup(struct drm_device * dev) if (I915_NEED_GFX_HWS(dev)) i915_free_hws(dev); - dev_priv->sarea = NULL; - dev_priv->sarea_priv = NULL; - return 0; } static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) { drm_i915_private_t *dev_priv = dev->dev_private; - - dev_priv->sarea = drm_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("can not find sarea!\n"); - i915_dma_cleanup(dev); - return -EINVAL; - } - - dev_priv->sarea_priv = (drm_i915_sarea_t *) - ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; if (init->ring_size != 0) { if (dev_priv->ring.ring_obj != NULL) { @@ -207,7 +210,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) dev_priv->back_offset = init->back_offset; dev_priv->front_offset = init->front_offset; dev_priv->current_page = 0; - dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; + if (master_priv->sarea_priv) + master_priv->sarea_priv->pf_current_page = 0; /* Allow hardware batchbuffers unless told otherwise. */ @@ -222,11 +226,6 @@ static int i915_dma_resume(struct drm_device * dev) DRM_DEBUG("%s\n", __func__); - if (!dev_priv->sarea) { - DRM_ERROR("can not find sarea!\n"); - return -EINVAL; - } - if (dev_priv->ring.map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); @@ -435,13 +434,14 @@ i915_emit_box(struct drm_device *dev, static void i915_emit_breadcrumb(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; RING_LOCALS; dev_priv->counter++; if (dev_priv->counter > 0x7FFFFFFFUL) dev_priv->counter = 0; - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_enqueue = dev_priv->counter; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_enqueue = dev_priv->counter; BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); @@ -537,15 +537,17 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, static int i915_dispatch_flip(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv = + dev->primary->master->driver_priv; RING_LOCALS; - if (!dev_priv->sarea_priv) + if (!master_priv->sarea_priv) return -EINVAL; DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", __func__, dev_priv->current_page, - dev_priv->sarea_priv->pf_current_page); + master_priv->sarea_priv->pf_current_page); i915_kernel_lost_context(dev); @@ -572,7 +574,7 @@ static int i915_dispatch_flip(struct drm_device * dev) OUT_RING(0); ADVANCE_LP_RING(); - dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; + master_priv->sarea_priv->last_enqueue = dev_priv->counter++; BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); @@ -581,7 +583,7 @@ static int i915_dispatch_flip(struct drm_device * dev) OUT_RING(0); ADVANCE_LP_RING(); - dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; + master_priv->sarea_priv->pf_current_page = dev_priv->current_page; return 0; } @@ -611,8 +613,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) - dev_priv->sarea_priv; + master_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; int ret; @@ -644,8 +647,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) - dev_priv->sarea_priv; + master_priv->sarea_priv; drm_i915_cmdbuffer_t *cmdbuf = data; int ret; @@ -774,6 +778,11 @@ static int i915_set_status_page(struct drm_device *dev, void *data, return -EINVAL; } + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + WARN(1, "tried to set status page when mode setting active\n"); + return 0; + } + printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); @@ -802,6 +811,214 @@ static int i915_set_status_page(struct drm_device *dev, void *data, return 0; } +/** + * i915_probe_agp - get AGP bootup configuration + * @pdev: PCI device + * @aperture_size: returns AGP aperture configured size + * @preallocated_size: returns size of BIOS preallocated AGP space + * + * Since Intel integrated graphics are UMA, the BIOS has to set aside + * some RAM for the framebuffer at early boot. This code figures out + * how much was set aside so we can use it for our own purposes. + */ +static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, + unsigned long *preallocated_size) +{ + struct pci_dev *bridge_dev; + u16 tmp = 0; + unsigned long overhead; + + bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); + if (!bridge_dev) { + DRM_ERROR("bridge device not found\n"); + return -1; + } + + /* Get the fb aperture size and "stolen" memory amount. */ + pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); + pci_dev_put(bridge_dev); + + *aperture_size = 1024 * 1024; + *preallocated_size = 1024 * 1024; + + switch (dev->pdev->device) { + case PCI_DEVICE_ID_INTEL_82830_CGC: + case PCI_DEVICE_ID_INTEL_82845G_IG: + case PCI_DEVICE_ID_INTEL_82855GM_IG: + case PCI_DEVICE_ID_INTEL_82865_IG: + if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) + *aperture_size *= 64; + else + *aperture_size *= 128; + break; + default: + /* 9xx supports large sizes, just look at the length */ + *aperture_size = pci_resource_len(dev->pdev, 2); + break; + } + + /* + * Some of the preallocated space is taken by the GTT + * and popup. GTT is 1K per MB of aperture size, and popup is 4K. + */ + if (IS_G4X(dev)) + overhead = 4096; + else + overhead = (*aperture_size / 1024) + 4096; + + switch (tmp & INTEL_855_GMCH_GMS_MASK) { + case INTEL_855_GMCH_GMS_STOLEN_1M: + break; /* 1M already */ + case INTEL_855_GMCH_GMS_STOLEN_4M: + *preallocated_size *= 4; + break; + case INTEL_855_GMCH_GMS_STOLEN_8M: + *preallocated_size *= 8; + break; + case INTEL_855_GMCH_GMS_STOLEN_16M: + *preallocated_size *= 16; + break; + case INTEL_855_GMCH_GMS_STOLEN_32M: + *preallocated_size *= 32; + break; + case INTEL_915G_GMCH_GMS_STOLEN_48M: + *preallocated_size *= 48; + break; + case INTEL_915G_GMCH_GMS_STOLEN_64M: + *preallocated_size *= 64; + break; + case INTEL_855_GMCH_GMS_DISABLED: + DRM_ERROR("video memory is disabled\n"); + return -1; + default: + DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", + tmp & INTEL_855_GMCH_GMS_MASK); + return -1; + } + *preallocated_size -= overhead; + + return 0; +} + +static int i915_load_modeset_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long agp_size, prealloc_size; + int fb_bar = IS_I9XX(dev) ? 2 : 0; + int ret = 0; + + dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL); + if (!dev->devname) { + ret = -ENOMEM; + goto out; + } + + dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & + 0xff000000; + + DRM_DEBUG("*** fb base 0x%08lx\n", dev->mode_config.fb_base); + + if (IS_MOBILE(dev) || (IS_I9XX(dev) && !IS_I965G(dev) && !IS_G33(dev))) + dev_priv->cursor_needs_physical = true; + else + dev_priv->cursor_needs_physical = false; + + ret = i915_probe_agp(dev, &agp_size, &prealloc_size); + if (ret) + goto kfree_devname; + + /* Basic memrange allocator for stolen space (aka vram) */ + drm_mm_init(&dev_priv->vram, 0, prealloc_size); + + /* Let GEM Manage from end of prealloc space to end of aperture */ + i915_gem_do_init(dev, prealloc_size, agp_size); + + ret = i915_gem_init_ringbuffer(dev); + if (ret) + goto kfree_devname; + + dev_priv->mm.gtt_mapping = + io_mapping_create_wc(dev->agp->base, + dev->agp->agp_info.aper_size * 1024*1024); + + /* Allow hardware batchbuffers unless told otherwise. + */ + dev_priv->allow_batchbuffer = 1; + + ret = intel_init_bios(dev); + if (ret) + DRM_INFO("failed to find VBIOS tables\n"); + + ret = drm_irq_install(dev); + if (ret) + goto destroy_ringbuffer; + + /* FIXME: re-add hotplug support */ +#if 0 + ret = drm_hotplug_init(dev); + if (ret) + goto destroy_ringbuffer; +#endif + + /* Always safe in the mode setting case. */ + /* FIXME: do pre/post-mode set stuff in core KMS code */ + dev->vblank_disable_allowed = 1; + + /* + * Initialize the hardware status page IRQ location. + */ + + I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); + + intel_modeset_init(dev); + + drm_helper_initial_config(dev, false); + + return 0; + +destroy_ringbuffer: + i915_gem_cleanup_ringbuffer(dev); +kfree_devname: + kfree(dev->devname); +out: + return ret; +} + +int i915_master_create(struct drm_device *dev, struct drm_master *master) +{ + struct drm_i915_master_private *master_priv; + + master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); + if (!master_priv) + return -ENOMEM; + + master->driver_priv = master_priv; + return 0; +} + +void i915_master_destroy(struct drm_device *dev, struct drm_master *master) +{ + struct drm_i915_master_private *master_priv = master->driver_priv; + + if (!master_priv) + return; + + drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); + + master->driver_priv = NULL; +} + +/** + * i915_driver_load - setup chip and create an initial config + * @dev: DRM device + * @flags: startup flags + * + * The driver load routine has to do several things: + * - drive output discovery via intel_modeset_init() + * - initialize the memory manager + * - allocate initial config memory + * - setup the DRM framebuffer with the allocated memory + */ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -829,6 +1046,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) size = drm_get_resource_len(dev, mmio_bar); dev_priv->regs = ioremap(base, size); + if (!dev_priv->regs) { + DRM_ERROR("failed to map registers\n"); + ret = -EIO; + goto free_priv; + } #ifdef CONFIG_HIGHMEM64G /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ @@ -844,7 +1066,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!I915_NEED_GFX_HWS(dev)) { ret = i915_init_phys_hws(dev); if (ret != 0) - return ret; + goto out_rmmap; } /* On the 945G/GM, the chipset reports the MSI capability on the @@ -864,6 +1086,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_opregion_init(dev); spin_lock_init(&dev_priv->user_irq_lock); + dev_priv->user_irq_refcount = 0; ret = drm_vblank_init(dev, I915_NUM_PIPE); @@ -872,6 +1095,20 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return ret; } + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = i915_load_modeset_init(dev); + if (ret < 0) { + DRM_ERROR("failed to init modeset\n"); + goto out_rmmap; + } + } + + return 0; + +out_rmmap: + iounmap(dev_priv->regs); +free_priv: + drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER); return ret; } @@ -879,16 +1116,29 @@ int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + io_mapping_free(dev_priv->mm.gtt_mapping); + drm_irq_uninstall(dev); + } + if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); - i915_free_hws(dev); - if (dev_priv->regs != NULL) iounmap(dev_priv->regs); intel_opregion_free(dev); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + intel_modeset_cleanup(dev); + + mutex_lock(&dev->struct_mutex); + i915_gem_cleanup_ringbuffer(dev); + mutex_unlock(&dev->struct_mutex); + drm_mm_takedown(&dev_priv->vram); + i915_gem_lastclose(dev); + } + drm_free(dev->dev_private, sizeof(drm_i915_private_t), DRM_MEM_DRIVER); @@ -914,12 +1164,26 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) return 0; } +/** + * i915_driver_lastclose - clean up after all DRM clients have exited + * @dev: DRM device + * + * Take care of cleaning up after all DRM clients have exited. In the + * mode setting case, we want to restore the kernel's initial mode (just + * in case the last client left us in a bad state). + * + * Additionally, in the non-mode setting case, we'll tear down the AGP + * and DMA structures, since the kernel won't be using them, and clea + * up any GEM state. + */ void i915_driver_lastclose(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - if (!dev_priv) + if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { + intelfb_restore(); return; + } i915_gem_lastclose(dev); @@ -932,7 +1196,8 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, file_priv, dev_priv->agp_heap); + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + i915_mem_release(dev, file_priv, dev_priv->agp_heap); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) @@ -972,6 +1237,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a80ead215282..f8b3df0926c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -33,11 +33,22 @@ #include "i915_drv.h" #include "drm_pciids.h" +#include <linux/console.h> + +static unsigned int i915_modeset = -1; +module_param_named(modeset, i915_modeset, int, 0400); + +unsigned int i915_fbpercrtc = 0; +module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); static struct pci_device_id pciidlist[] = { i915_PCI_IDS }; +#if defined(CONFIG_DRM_I915_KMS) +MODULE_DEVICE_TABLE(pci, pciidlist); +#endif + static int i915_suspend(struct drm_device *dev, pm_message_t state) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -81,6 +92,10 @@ static int i915_resume(struct drm_device *dev) return 0; } +static struct vm_operations_struct i915_gem_vm_ops = { + .fault = i915_gem_fault, +}; + static struct drm_driver driver = { /* don't use mtrr's here, the Xserver or user space app should * deal with them for intel hardware. @@ -107,17 +122,20 @@ static struct drm_driver driver = { .reclaim_buffers = drm_core_reclaim_buffers, .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, + .master_create = i915_master_create, + .master_destroy = i915_master_destroy, .proc_init = i915_gem_proc_init, .proc_cleanup = i915_gem_proc_cleanup, .gem_init_object = i915_gem_init_object, .gem_free_object = i915_gem_free_object, + .gem_vm_ops = &i915_gem_vm_ops, .ioctls = i915_ioctls, .fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, .ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .fasync = drm_fasync, #ifdef CONFIG_COMPAT @@ -141,6 +159,28 @@ static struct drm_driver driver = { static int __init i915_init(void) { driver.num_ioctls = i915_max_ioctl; + + /* + * If CONFIG_DRM_I915_KMS is set, default to KMS unless + * explicitly disabled with the module pararmeter. + * + * Otherwise, just follow the parameter (defaulting to off). + * + * Allow optional vga_text_mode_force boot option to override + * the default behavior. + */ +#if defined(CONFIG_DRM_I915_KMS) + if (i915_modeset != 0) + driver.driver_features |= DRIVER_MODESET; +#endif + if (i915_modeset == 1) + driver.driver_features |= DRIVER_MODESET; + +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force() && i915_modeset == -1) + driver.driver_features &= ~DRIVER_MODESET; +#endif + return drm_init(&driver); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b3cc4731aa7c..4756e5cd6b5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -31,6 +31,7 @@ #define _I915_DRV_H_ #include "i915_reg.h" +#include "intel_bios.h" #include <linux/io-mapping.h> /* General customization: @@ -103,15 +104,23 @@ struct intel_opregion { int enabled; }; +struct drm_i915_master_private { + drm_local_map_t *sarea; + struct _drm_i915_sarea *sarea_priv; +}; +#define I915_FENCE_REG_NONE -1 + +struct drm_i915_fence_reg { + struct drm_gem_object *obj; +}; + typedef struct drm_i915_private { struct drm_device *dev; int has_gem; void __iomem *regs; - drm_local_map_t *sarea; - drm_i915_sarea_t *sarea_priv; drm_i915_ring_buffer_t ring; drm_dma_handle_t *status_page_dmah; @@ -144,8 +153,30 @@ typedef struct drm_i915_private { unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + bool cursor_needs_physical; + + struct drm_mm vram; + + int irq_enabled; + struct intel_opregion opregion; + /* LVDS info */ + int backlight_duty_cycle; /* restore backlight to this value */ + bool panel_wants_dither; + struct drm_display_mode *panel_fixed_mode; + struct drm_display_mode *vbt_mode; /* if any */ + + /* Feature bits from the VBIOS */ + unsigned int int_tv_support:1; + unsigned int lvds_dither:1; + unsigned int lvds_vbt:1; + unsigned int int_crt_support:1; + + struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ + int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ + int num_fence_regs; /* 8 on pre-965, 16 otherwise */ + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; @@ -364,6 +395,21 @@ struct drm_i915_gem_object { * This is the same as gtt_space->start */ uint32_t gtt_offset; + /** + * Required alignment for the object + */ + uint32_t gtt_alignment; + /** + * Fake offset for use by mmap(2) + */ + uint64_t mmap_offset; + + /** + * Fence register bits (if any) for this object. Will be set + * as needed when mapped into the GTT. + * Protected by dev->struct_mutex. + */ + int fence_reg; /** Boolean whether this object has a valid gtt offset. */ int gtt_bound; @@ -376,6 +422,7 @@ struct drm_i915_gem_object { /** Current tiling mode for the object. */ uint32_t tiling_mode; + uint32_t stride; /** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */ uint32_t agp_type; @@ -385,6 +432,10 @@ struct drm_i915_gem_object { * flags which individual pages are valid. */ uint8_t *page_cpu_valid; + + /** User space pin count and filp owning the pin */ + uint32_t user_pin_count; + struct drm_file *pin_filp; }; /** @@ -414,8 +465,19 @@ struct drm_i915_file_private { } mm; }; +enum intel_chip_family { + CHIP_I8XX = 0x01, + CHIP_I9XX = 0x02, + CHIP_I915 = 0x04, + CHIP_I965 = 0x08, +}; + extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; +extern unsigned int i915_fbpercrtc; + +extern int i915_master_create(struct drm_device *dev, struct drm_master *master); +extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); /* i915_dma.c */ extern void i915_kernel_lost_context(struct drm_device * dev); @@ -441,6 +503,7 @@ extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); void i915_user_irq_get(struct drm_device *dev); void i915_user_irq_put(struct drm_device *dev); +extern void i915_enable_interrupt (struct drm_device *dev); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); @@ -487,6 +550,8 @@ int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, @@ -523,6 +588,16 @@ uint32_t i915_get_gem_seqno(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_work_handler(struct work_struct *work); void i915_gem_clflush_object(struct drm_gem_object *obj); +int i915_gem_object_set_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); +int i915_gem_init_ringbuffer(struct drm_device *dev); +void i915_gem_cleanup_ringbuffer(struct drm_device *dev); +int i915_gem_do_init(struct drm_device *dev, unsigned long start, + unsigned long end); +int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, + int write); /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); @@ -561,6 +636,10 @@ static inline void opregion_asle_intr(struct drm_device *dev) { return; } static inline void opregion_enable_asle(struct drm_device *dev) { return; } #endif +/* modesetting */ +extern void intel_modeset_init(struct drm_device *dev); +extern void intel_modeset_cleanup(struct drm_device *dev); + /** * Lock test for when it's just for synchronization of ring access. * @@ -578,6 +657,13 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; } #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) #define I915_READ8(reg) readb(dev_priv->regs + (reg)) #define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg)) +#ifdef writeq +#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg)) +#else +#define I915_WRITE64(reg, val) (writel(val, dev_priv->regs + (reg)), \ + writel(upper_32_bits(val), dev_priv->regs + \ + (reg) + 4)) +#endif #define I915_VERBOSE 0 @@ -660,7 +746,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \ (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22) + (dev)->pci_device == 0x2E22 || \ + IS_GM45(dev)) #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ (dev)->pci_device == 0x29B2 || \ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 24fe8c10b4b2..cc2ca5561feb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -30,6 +30,7 @@ #include "i915_drm.h" #include "i915_drv.h" #include <linux/swap.h> +#include <linux/pci.h> #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) @@ -40,8 +41,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); -static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, - int write); static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write); static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, @@ -51,34 +50,43 @@ static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *o static int i915_gem_object_get_page_list(struct drm_gem_object *obj); static void i915_gem_object_free_page_list(struct drm_gem_object *obj); static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); +static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, + unsigned alignment); +static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj); +static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); +static int i915_gem_evict_something(struct drm_device *dev); + +int i915_gem_do_init(struct drm_device *dev, unsigned long start, + unsigned long end) +{ + drm_i915_private_t *dev_priv = dev->dev_private; -static void -i915_gem_cleanup_ringbuffer(struct drm_device *dev); + if (start >= end || + (start & (PAGE_SIZE - 1)) != 0 || + (end & (PAGE_SIZE - 1)) != 0) { + return -EINVAL; + } + + drm_mm_init(&dev_priv->mm.gtt_space, start, + end - start); + + dev->gtt_total = (uint32_t) (end - start); + + return 0; +} int i915_gem_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_init *args = data; + int ret; mutex_lock(&dev->struct_mutex); - - if (args->gtt_start >= args->gtt_end || - (args->gtt_start & (PAGE_SIZE - 1)) != 0 || - (args->gtt_end & (PAGE_SIZE - 1)) != 0) { - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start, - args->gtt_end - args->gtt_start); - - dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start); - + ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end); mutex_unlock(&dev->struct_mutex); - return 0; + return ret; } int @@ -529,6 +537,252 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, return 0; } +/** + * i915_gem_fault - fault a page into the GTT + * vma: VMA in question + * vmf: fault info + * + * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped + * from userspace. The fault handler takes care of binding the object to + * the GTT (if needed), allocating and programming a fence register (again, + * only if needed based on whether the old reg is still valid or the object + * is tiled) and inserting a new PTE into the faulting process. + * + * Note that the faulting process may involve evicting existing objects + * from the GTT and/or fence registers to make room. So performance may + * suffer if the GTT working set is large or there are few fence registers + * left. + */ +int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct drm_device *dev = obj->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + pgoff_t page_offset; + unsigned long pfn; + int ret = 0; + + /* We don't use vmf->pgoff since that has the fake offset */ + page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> + PAGE_SHIFT; + + /* Now bind it into the GTT if needed */ + mutex_lock(&dev->struct_mutex); + if (!obj_priv->gtt_space) { + ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment); + if (ret) { + mutex_unlock(&dev->struct_mutex); + return VM_FAULT_SIGBUS; + } + list_add(&obj_priv->list, &dev_priv->mm.inactive_list); + } + + /* Need a new fence register? */ + if (obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) + i915_gem_object_get_fence_reg(obj); + + pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + + page_offset; + + /* Finally, remap it using the new GTT offset */ + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); + + mutex_unlock(&dev->struct_mutex); + + switch (ret) { + case -ENOMEM: + case -EAGAIN: + return VM_FAULT_OOM; + case -EFAULT: + case -EBUSY: + DRM_ERROR("can't insert pfn?? fault or busy...\n"); + return VM_FAULT_SIGBUS; + default: + return VM_FAULT_NOPAGE; + } +} + +/** + * i915_gem_create_mmap_offset - create a fake mmap offset for an object + * @obj: obj in question + * + * GEM memory mapping works by handing back to userspace a fake mmap offset + * it can use in a subsequent mmap(2) call. The DRM core code then looks + * up the object based on the offset and sets up the various memory mapping + * structures. + * + * This routine allocates and attaches a fake offset for @obj. + */ +static int +i915_gem_create_mmap_offset(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + struct drm_map_list *list; + struct drm_map *map; + int ret = 0; + + /* Set the object up for mmap'ing */ + list = &obj->map_list; + list->map = drm_calloc(1, sizeof(struct drm_map_list), + DRM_MEM_DRIVER); + if (!list->map) + return -ENOMEM; + + map = list->map; + map->type = _DRM_GEM; + map->size = obj->size; + map->handle = obj; + + /* Get a DRM GEM mmap offset allocated... */ + list->file_offset_node = drm_mm_search_free(&mm->offset_manager, + obj->size / PAGE_SIZE, 0, 0); + if (!list->file_offset_node) { + DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); + ret = -ENOMEM; + goto out_free_list; + } + + list->file_offset_node = drm_mm_get_block(list->file_offset_node, + obj->size / PAGE_SIZE, 0); + if (!list->file_offset_node) { + ret = -ENOMEM; + goto out_free_list; + } + + list->hash.key = list->file_offset_node->start; + if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { + DRM_ERROR("failed to add to map hash\n"); + goto out_free_mm; + } + + /* By now we should be all set, any drm_mmap request on the offset + * below will get to our mmap & fault handler */ + obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT; + + return 0; + +out_free_mm: + drm_mm_put_block(list->file_offset_node); +out_free_list: + drm_free(list->map, sizeof(struct drm_map_list), DRM_MEM_DRIVER); + + return ret; +} + +/** + * i915_gem_get_gtt_alignment - return required GTT alignment for an object + * @obj: object to check + * + * Return the required GTT alignment for an object, taking into account + * potential fence register mapping if needed. + */ +static uint32_t +i915_gem_get_gtt_alignment(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + int start, i; + + /* + * Minimum alignment is 4k (GTT page size), but might be greater + * if a fence register is needed for the object. + */ + if (IS_I965G(dev) || obj_priv->tiling_mode == I915_TILING_NONE) + return 4096; + + /* + * Previous chips need to be aligned to the size of the smallest + * fence register that can contain the object. + */ + if (IS_I9XX(dev)) + start = 1024*1024; + else + start = 512*1024; + + for (i = start; i < obj->size; i <<= 1) + ; + + return i; +} + +/** + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing + * @dev: DRM device + * @data: GTT mapping ioctl data + * @file_priv: GEM object info + * + * Simply returns the fake offset to userspace so it can mmap it. + * The mmap call will end up in drm_gem_mmap(), which will set things + * up so we can get faults in the handler above. + * + * The fault handler will take care of binding the object into the GTT + * (since it may have been evicted to make room for something), allocating + * a fence register, and mapping the appropriate aperture address into + * userspace. + */ +int +i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_mmap_gtt *args = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_gem_object *obj; + struct drm_i915_gem_object *obj_priv; + int ret; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EBADF; + + mutex_lock(&dev->struct_mutex); + + obj_priv = obj->driver_private; + + if (!obj_priv->mmap_offset) { + ret = i915_gem_create_mmap_offset(obj); + if (ret) + return ret; + } + + args->offset = obj_priv->mmap_offset; + + obj_priv->gtt_alignment = i915_gem_get_gtt_alignment(obj); + + /* Make sure the alignment is correct for fence regs etc */ + if (obj_priv->agp_mem && + (obj_priv->gtt_offset & (obj_priv->gtt_alignment - 1))) { + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + /* + * Pull it into the GTT so that we have a page list (makes the + * initial fault faster and any subsequent flushing possible). + */ + if (!obj_priv->agp_mem) { + ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment); + if (ret) { + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; + } + list_add(&obj_priv->list, &dev_priv->mm.inactive_list); + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + static void i915_gem_object_free_page_list(struct drm_gem_object *obj) { @@ -726,6 +980,7 @@ i915_gem_retire_request(struct drm_device *dev, */ if (obj_priv->last_rendering_seqno != request->seqno) return; + #if WATCH_LRU DRM_INFO("%s: retire %d moves to inactive list %p\n", __func__, request->seqno, obj); @@ -956,6 +1211,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; + loff_t offset; int ret = 0; #if WATCH_BUF @@ -991,6 +1247,14 @@ i915_gem_object_unbind(struct drm_gem_object *obj) BUG_ON(obj_priv->active); + /* blow away mappings if mapped through GTT */ + offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; + if (dev->dev_mapping) + unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); + + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) + i915_gem_clear_fence_reg(obj); + i915_gem_object_free_page_list(obj); if (obj_priv->gtt_space) { @@ -1149,6 +1413,204 @@ i915_gem_object_get_page_list(struct drm_gem_object *obj) return 0; } +static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) +{ + struct drm_gem_object *obj = reg->obj; + struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + int regnum = obj_priv->fence_reg; + uint64_t val; + + val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) & + 0xfffff000) << 32; + val |= obj_priv->gtt_offset & 0xfffff000; + val |= ((obj_priv->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT; + if (obj_priv->tiling_mode == I915_TILING_Y) + val |= 1 << I965_FENCE_TILING_Y_SHIFT; + val |= I965_FENCE_REG_VALID; + + I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val); +} + +static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) +{ + struct drm_gem_object *obj = reg->obj; + struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + int regnum = obj_priv->fence_reg; + uint32_t val; + uint32_t pitch_val; + + if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || + (obj_priv->gtt_offset & (obj->size - 1))) { + WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__); + return; + } + + if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) || + IS_I945GM(dev) || + IS_G33(dev))) + pitch_val = (obj_priv->stride / 128) - 1; + else + pitch_val = (obj_priv->stride / 512) - 1; + + val = obj_priv->gtt_offset; + if (obj_priv->tiling_mode == I915_TILING_Y) + val |= 1 << I830_FENCE_TILING_Y_SHIFT; + val |= I915_FENCE_SIZE_BITS(obj->size); + val |= pitch_val << I830_FENCE_PITCH_SHIFT; + val |= I830_FENCE_REG_VALID; + + I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); +} + +static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) +{ + struct drm_gem_object *obj = reg->obj; + struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + int regnum = obj_priv->fence_reg; + uint32_t val; + uint32_t pitch_val; + + if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || + (obj_priv->gtt_offset & (obj->size - 1))) { + WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__); + return; + } + + pitch_val = (obj_priv->stride / 128) - 1; + + val = obj_priv->gtt_offset; + if (obj_priv->tiling_mode == I915_TILING_Y) + val |= 1 << I830_FENCE_TILING_Y_SHIFT; + val |= I830_FENCE_SIZE_BITS(obj->size); + val |= pitch_val << I830_FENCE_PITCH_SHIFT; + val |= I830_FENCE_REG_VALID; + + I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); + +} + +/** + * i915_gem_object_get_fence_reg - set up a fence reg for an object + * @obj: object to map through a fence reg + * + * When mapping objects through the GTT, userspace wants to be able to write + * to them without having to worry about swizzling if the object is tiled. + * + * This function walks the fence regs looking for a free one for @obj, + * stealing one if it can't find any. + * + * It then sets up the reg based on the object's properties: address, pitch + * and tiling format. + */ +static void +i915_gem_object_get_fence_reg(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + struct drm_i915_fence_reg *reg = NULL; + int i, ret; + + switch (obj_priv->tiling_mode) { + case I915_TILING_NONE: + WARN(1, "allocating a fence for non-tiled object?\n"); + break; + case I915_TILING_X: + WARN(obj_priv->stride & (512 - 1), + "object is X tiled but has non-512B pitch\n"); + break; + case I915_TILING_Y: + WARN(obj_priv->stride & (128 - 1), + "object is Y tiled but has non-128B pitch\n"); + break; + } + + /* First try to find a free reg */ + for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { + reg = &dev_priv->fence_regs[i]; + if (!reg->obj) + break; + } + + /* None available, try to steal one or wait for a user to finish */ + if (i == dev_priv->num_fence_regs) { + struct drm_i915_gem_object *old_obj_priv = NULL; + loff_t offset; + +try_again: + /* Could try to use LRU here instead... */ + for (i = dev_priv->fence_reg_start; + i < dev_priv->num_fence_regs; i++) { + reg = &dev_priv->fence_regs[i]; + old_obj_priv = reg->obj->driver_private; + if (!old_obj_priv->pin_count) + break; + } + + /* + * Now things get ugly... we have to wait for one of the + * objects to finish before trying again. + */ + if (i == dev_priv->num_fence_regs) { + ret = i915_gem_object_wait_rendering(reg->obj); + if (ret) { + WARN(ret, "wait_rendering failed: %d\n", ret); + return; + } + goto try_again; + } + + /* + * Zap this virtual mapping so we can set up a fence again + * for this object next time we need it. + */ + offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; + if (dev->dev_mapping) + unmap_mapping_range(dev->dev_mapping, offset, + reg->obj->size, 1); + old_obj_priv->fence_reg = I915_FENCE_REG_NONE; + } + + obj_priv->fence_reg = i; + reg->obj = obj; + + if (IS_I965G(dev)) + i965_write_fence_reg(reg); + else if (IS_I9XX(dev)) + i915_write_fence_reg(reg); + else + i830_write_fence_reg(reg); +} + +/** + * i915_gem_clear_fence_reg - clear out fence register info + * @obj: object to clear + * + * Zeroes out the fence register itself and clears out the associated + * data structures in dev_priv and obj_priv. + */ +static void +i915_gem_clear_fence_reg(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + + if (IS_I965G(dev)) + I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); + else + I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); + + dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; + obj_priv->fence_reg = I915_FENCE_REG_NONE; +} + /** * Finds free space in the GTT aperture and binds the object there. */ @@ -1307,7 +1769,7 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) * This function returns when the move is complete, including waiting on * flushes to occur. */ -static int +int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) { struct drm_i915_gem_object *obj_priv = obj->driver_private; @@ -2029,13 +2491,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, /* error other than GTT full, or we've already tried again */ if (ret != -ENOMEM || pin_tries >= 1) { - DRM_ERROR("Failed to pin buffers %d\n", ret); + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to pin buffers %d\n", ret); goto err; } /* unpin all of our buffers */ for (i = 0; i < pinned; i++) i915_gem_object_unpin(object_list[i]); + pinned = 0; /* evict everyone we can from the aperture */ ret = i915_gem_evict_everything(dev); @@ -2149,13 +2613,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, "back to user (%d)\n", args->buffer_count, ret); err: - if (object_list != NULL) { - for (i = 0; i < pinned; i++) - i915_gem_object_unpin(object_list[i]); + for (i = 0; i < pinned; i++) + i915_gem_object_unpin(object_list[i]); + + for (i = 0; i < args->buffer_count; i++) + drm_gem_object_unreference(object_list[i]); - for (i = 0; i < args->buffer_count; i++) - drm_gem_object_unreference(object_list[i]); - } mutex_unlock(&dev->struct_mutex); pre_mutex_err: @@ -2178,7 +2641,8 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) if (obj_priv->gtt_space == NULL) { ret = i915_gem_object_bind_to_gtt(obj, alignment); if (ret != 0) { - DRM_ERROR("Failure to bind: %d", ret); + if (ret != -ERESTARTSYS) + DRM_ERROR("Failure to bind: %d", ret); return ret; } } @@ -2249,11 +2713,22 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, } obj_priv = obj->driver_private; - ret = i915_gem_object_pin(obj, args->alignment); - if (ret != 0) { - drm_gem_object_unreference(obj); + if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { + DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", + args->handle); mutex_unlock(&dev->struct_mutex); - return ret; + return -EINVAL; + } + + obj_priv->user_pin_count++; + obj_priv->pin_filp = file_priv; + if (obj_priv->user_pin_count == 1) { + ret = i915_gem_object_pin(obj, args->alignment); + if (ret != 0) { + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; + } } /* XXX - flush the CPU caches for pinned objects @@ -2273,6 +2748,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_pin *args = data; struct drm_gem_object *obj; + struct drm_i915_gem_object *obj_priv; mutex_lock(&dev->struct_mutex); @@ -2284,7 +2760,19 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, return -EBADF; } - i915_gem_object_unpin(obj); + obj_priv = obj->driver_private; + if (obj_priv->pin_filp != file_priv) { + DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", + args->handle); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + obj_priv->user_pin_count--; + if (obj_priv->user_pin_count == 0) { + obj_priv->pin_filp = NULL; + i915_gem_object_unpin(obj); + } drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -2351,12 +2839,18 @@ int i915_gem_init_object(struct drm_gem_object *obj) obj->driver_private = obj_priv; obj_priv->obj = obj; + obj_priv->fence_reg = I915_FENCE_REG_NONE; INIT_LIST_HEAD(&obj_priv->list); + return 0; } void i915_gem_free_object(struct drm_gem_object *obj) { + struct drm_device *dev = obj->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_map_list *list; + struct drm_map *map; struct drm_i915_gem_object *obj_priv = obj->driver_private; while (obj_priv->pin_count > 0) @@ -2364,6 +2858,20 @@ void i915_gem_free_object(struct drm_gem_object *obj) i915_gem_object_unbind(obj); + list = &obj->map_list; + drm_ht_remove_item(&mm->offset_hash, &list->hash); + + if (list->file_offset_node) { + drm_mm_put_block(list->file_offset_node); + list->file_offset_node = NULL; + } + + map = list->map; + if (map) { + drm_free(map, sizeof(*map), DRM_MEM_DRIVER); + list->map = NULL; + } + drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); } @@ -2432,8 +2940,7 @@ i915_gem_idle(struct drm_device *dev) */ i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT), ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)); - seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU | - I915_GEM_DOMAIN_GTT)); + seqno = i915_add_request(dev, ~I915_GEM_DOMAIN_CPU); if (seqno == 0) { mutex_unlock(&dev->struct_mutex); @@ -2560,12 +3067,13 @@ i915_gem_init_hws(struct drm_device *dev) return 0; } -static int +int i915_gem_init_ringbuffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; + drm_i915_ring_buffer_t *ring = &dev_priv->ring; int ret; u32 head; @@ -2587,24 +3095,24 @@ i915_gem_init_ringbuffer(struct drm_device *dev) } /* Set up the kernel mapping for the ring. */ - dev_priv->ring.Size = obj->size; - dev_priv->ring.tail_mask = obj->size - 1; + ring->Size = obj->size; + ring->tail_mask = obj->size - 1; - dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset; - dev_priv->ring.map.size = obj->size; - dev_priv->ring.map.type = 0; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; + ring->map.offset = dev->agp->base + obj_priv->gtt_offset; + ring->map.size = obj->size; + ring->map.type = 0; + ring->map.flags = 0; + ring->map.mtrr = 0; - drm_core_ioremap_wc(&dev_priv->ring.map, dev); - if (dev_priv->ring.map.handle == NULL) { + drm_core_ioremap_wc(&ring->map, dev); + if (ring->map.handle == NULL) { DRM_ERROR("Failed to map ringbuffer.\n"); memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); drm_gem_object_unreference(obj); return -EINVAL; } - dev_priv->ring.ring_obj = obj; - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + ring->ring_obj = obj; + ring->virtual_start = ring->map.handle; /* Stop the ring if it's running. */ I915_WRITE(PRB0_CTL, 0); @@ -2652,12 +3160,20 @@ i915_gem_init_ringbuffer(struct drm_device *dev) } /* Update our cache of the ring state */ - i915_kernel_lost_context(dev); + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + i915_kernel_lost_context(dev); + else { + ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; + ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; + ring->space = ring->head - (ring->tail + 8); + if (ring->space < 0) + ring->space += ring->Size; + } return 0; } -static void +void i915_gem_cleanup_ringbuffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -2695,6 +3211,9 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; int ret; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + if (dev_priv->mm.wedged) { DRM_ERROR("Reenabling wedged hardware, good luck\n"); dev_priv->mm.wedged = 0; @@ -2728,6 +3247,9 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; int ret; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + ret = i915_gem_idle(dev); drm_irq_uninstall(dev); @@ -2758,5 +3280,13 @@ i915_gem_load(struct drm_device *dev) i915_gem_retire_work_handler); dev_priv->mm.next_gem_seqno = 1; + /* Old X drivers will take 0-2 for front, back, depth buffers */ + dev_priv->fence_reg_start = 3; + + if (IS_I965G(dev)) + dev_priv->num_fence_regs = 16; + else + dev_priv->num_fence_regs = 8; + i915_gem_detect_bit_6_swizzle(dev); } diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c index e8d5abe1250e..4d1b9de0cd8b 100644 --- a/drivers/gpu/drm/i915/i915_gem_proc.c +++ b/drivers/gpu/drm/i915/i915_gem_proc.c @@ -250,6 +250,39 @@ static int i915_interrupt_info(char *buf, char **start, off_t offset, return len - offset; } +static int i915_hws_info(char *buf, char **start, off_t offset, + int request, int *eof, void *data) +{ + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int len = 0, i; + volatile u32 *hws; + + if (offset > DRM_PROC_LIMIT) { + *eof = 1; + return 0; + } + + hws = (volatile u32 *)dev_priv->hw_status_page; + if (hws == NULL) { + *eof = 1; + return 0; + } + + *start = &buf[offset]; + *eof = 0; + for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) { + DRM_PROC_PRINT("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + i * 4, + hws[i], hws[i + 1], hws[i + 2], hws[i + 3]); + } + if (len > request + offset) + return request; + *eof = 1; + return len - offset; +} + static struct drm_proc_list { /** file name */ const char *name; @@ -262,6 +295,7 @@ static struct drm_proc_list { {"i915_gem_request", i915_gem_request_info}, {"i915_gem_seqno", i915_gem_seqno_info}, {"i915_gem_interrupt", i915_interrupt_info}, + {"i915_gem_hws", i915_hws_info}, }; #define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index a8cb69469c64..241f39b7f460 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -208,6 +208,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, } } obj_priv->tiling_mode = args->tiling_mode; + obj_priv->stride = args->stride; mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 69b9a42da95e..0cadafbef411 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -30,6 +30,7 @@ #include "drm.h" #include "i915_drm.h" #include "i915_drv.h" +#include "intel_drv.h" #define MAX_NOPID ((u32)~0) @@ -51,6 +52,15 @@ #define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \ I915_INTERRUPT_ENABLE_VAR) +#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\ + PIPE_VBLANK_INTERRUPT_STATUS) + +#define I915_PIPE_VBLANK_ENABLE (PIPE_START_VBLANK_INTERRUPT_ENABLE |\ + PIPE_VBLANK_INTERRUPT_ENABLE) + +#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \ + DRM_I915_VBLANK_PIPE_B) + void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) { @@ -168,6 +178,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_master_private *master_priv; u32 iir, new_iir; u32 pipea_stats, pipeb_stats; u32 vblank_status; @@ -200,6 +211,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); pipea_stats = I915_READ(PIPEASTAT); pipeb_stats = I915_READ(PIPEBSTAT); + /* * Clear the PIPE(A|B)STAT regs before the IIR */ @@ -222,9 +234,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE(IIR, iir); new_iir = I915_READ(IIR); /* Flush posted writes */ - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); + if (dev->primary->master) { + master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); + } if (iir & I915_USER_INTERRUPT) { dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); @@ -269,6 +284,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) static int i915_emit_irq(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; RING_LOCALS; i915_kernel_lost_context(dev); @@ -278,8 +294,8 @@ static int i915_emit_irq(struct drm_device * dev) dev_priv->counter++; if (dev_priv->counter > 0x7FFFFFFFUL) dev_priv->counter = 1; - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_enqueue = dev_priv->counter; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_enqueue = dev_priv->counter; BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); @@ -317,21 +333,20 @@ void i915_user_irq_put(struct drm_device *dev) static int i915_wait_irq(struct drm_device * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; int ret = 0; DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); if (READ_BREADCRUMB(dev_priv) >= irq_nr) { - if (dev_priv->sarea_priv) { - dev_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - } + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return 0; } - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + if (master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; i915_user_irq_get(dev); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, @@ -343,10 +358,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - return ret; } @@ -427,6 +438,14 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); } +void i915_enable_interrupt (struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + opregion_enable_asle(dev); + dev_priv->irq_enabled = 1; +} + + /* Set the vblank monitor pipe */ int i915_vblank_pipe_set(struct drm_device *dev, void *data, @@ -487,6 +506,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + atomic_set(&dev_priv->irq_received, 0); + I915_WRITE(HWSTAM, 0xeffe); I915_WRITE(PIPEASTAT, 0); I915_WRITE(PIPEBSTAT, 0); diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c index 6126a60dc9cb..96e271986d2a 100644 --- a/drivers/gpu/drm/i915/i915_mem.c +++ b/drivers/gpu/drm/i915/i915_mem.c @@ -46,7 +46,8 @@ static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) { drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv; struct drm_tex_region *list; unsigned shift, nr; unsigned start; diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 13ae731a33db..ff012835a386 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -257,8 +257,8 @@ void opregion_enable_asle(struct drm_device *dev) static struct intel_opregion *system_opregion; -int intel_opregion_video_event(struct notifier_block *nb, unsigned long val, - void *data) +static int intel_opregion_video_event(struct notifier_block *nb, + unsigned long val, void *data) { /* The only video events relevant to opregion are 0x80. These indicate either a docking event, lid switch or display switch request. In diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d24aaeb8a45..47e6bafeb743 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -175,9 +175,26 @@ #define DISPLAY_PLANE_B (1<<20) /* - * Instruction and interrupt control regs + * Fence registers */ +#define FENCE_REG_830_0 0x2000 +#define I830_FENCE_START_MASK 0x07f80000 +#define I830_FENCE_TILING_Y_SHIFT 12 +#define I830_FENCE_SIZE_BITS(size) ((get_order(size >> 19) - 1) << 8) +#define I830_FENCE_PITCH_SHIFT 4 +#define I830_FENCE_REG_VALID (1<<0) + +#define I915_FENCE_START_MASK 0x0ff00000 +#define I915_FENCE_SIZE_BITS(size) ((get_order(size >> 20) - 1) << 8) +#define FENCE_REG_965_0 0x03000 +#define I965_FENCE_PITCH_SHIFT 2 +#define I965_FENCE_TILING_Y_SHIFT 1 +#define I965_FENCE_REG_VALID (1<<0) + +/* + * Instruction and interrupt control regs + */ #define PRB0_TAIL 0x02030 #define PRB0_HEAD 0x02034 #define PRB0_START 0x02038 @@ -245,6 +262,7 @@ #define CM0_RC_OP_FLUSH_DISABLE (1<<0) #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ + /* * Framebuffer compression (915+ only) */ diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c new file mode 100644 index 000000000000..4ca82a025525 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -0,0 +1,193 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "intel_bios.h" + + +static void * +find_section(struct bdb_header *bdb, int section_id) +{ + u8 *base = (u8 *)bdb; + int index = 0; + u16 total, current_size; + u8 current_id; + + /* skip to first section */ + index += bdb->header_size; + total = bdb->bdb_size; + + /* walk the sections looking for section_id */ + while (index < total) { + current_id = *(base + index); + index++; + current_size = *((u16 *)(base + index)); + index += 2; + if (current_id == section_id) + return base + index; + index += current_size; + } + + return NULL; +} + +/* Try to find panel data */ +static void +parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_lvds_options *lvds_options; + struct bdb_lvds_lfp_data *lvds_lfp_data; + struct bdb_lvds_lfp_data_entry *entry; + struct lvds_dvo_timing *dvo_timing; + struct drm_display_mode *panel_fixed_mode; + + /* Defaults if we can't find VBT info */ + dev_priv->lvds_dither = 0; + dev_priv->lvds_vbt = 0; + + lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); + if (!lvds_options) + return; + + dev_priv->lvds_dither = lvds_options->pixel_dither; + if (lvds_options->panel_type == 0xff) + return; + + lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); + if (!lvds_lfp_data) + return; + + dev_priv->lvds_vbt = 1; + + entry = &lvds_lfp_data->data[lvds_options->panel_type]; + dvo_timing = &entry->dvo_timing; + + panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), + DRM_MEM_DRIVER); + + panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | + dvo_timing->hactive_lo; + panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + + ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); + panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + + dvo_timing->hsync_pulse_width; + panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + + ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); + + panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | + dvo_timing->vactive_lo; + panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + + dvo_timing->vsync_off; + panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + + dvo_timing->vsync_pulse_width; + panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + + ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); + panel_fixed_mode->clock = dvo_timing->clock * 10; + panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; + + drm_mode_set_name(panel_fixed_mode); + + dev_priv->vbt_mode = panel_fixed_mode; + + DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); + drm_mode_debug_printmodeline(panel_fixed_mode); + + return; +} + +static void +parse_general_features(struct drm_i915_private *dev_priv, + struct bdb_header *bdb) +{ + struct bdb_general_features *general; + + /* Set sensible defaults in case we can't find the general block */ + dev_priv->int_tv_support = 1; + dev_priv->int_crt_support = 1; + + general = find_section(bdb, BDB_GENERAL_FEATURES); + if (general) { + dev_priv->int_tv_support = general->int_tv_support; + dev_priv->int_crt_support = general->int_crt_support; + } +} + +/** + * intel_init_bios - initialize VBIOS settings & find VBT + * @dev: DRM device + * + * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers + * to appropriate values. + * + * VBT existence is a sanity check that is relied on by other i830_bios.c code. + * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may + * feed an updated VBT back through that, compared to what we'll fetch using + * this method of groping around in the BIOS data. + * + * Returns 0 on success, nonzero on failure. + */ +bool +intel_init_bios(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct pci_dev *pdev = dev->pdev; + struct vbt_header *vbt = NULL; + struct bdb_header *bdb; + u8 __iomem *bios; + size_t size; + int i; + + bios = pci_map_rom(pdev, &size); + if (!bios) + return -1; + + /* Scour memory looking for the VBT signature */ + for (i = 0; i + 4 < size; i++) { + if (!memcmp(bios + i, "$VBT", 4)) { + vbt = (struct vbt_header *)(bios + i); + break; + } + } + + if (!vbt) { + DRM_ERROR("VBT signature missing\n"); + pci_unmap_rom(pdev, bios); + return -1; + } + + bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); + + /* Grab useful general definitions */ + parse_general_features(dev_priv, bdb); + parse_panel_data(dev_priv, bdb); + + pci_unmap_rom(pdev, bios); + + return 0; +} diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h new file mode 100644 index 000000000000..5ea715ace3a0 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -0,0 +1,405 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#ifndef _I830_BIOS_H_ +#define _I830_BIOS_H_ + +#include "drmP.h" + +struct vbt_header { + u8 signature[20]; /**< Always starts with 'VBT$' */ + u16 version; /**< decimal */ + u16 header_size; /**< in bytes */ + u16 vbt_size; /**< in bytes */ + u8 vbt_checksum; + u8 reserved0; + u32 bdb_offset; /**< from beginning of VBT */ + u32 aim_offset[4]; /**< from beginning of VBT */ +} __attribute__((packed)); + +struct bdb_header { + u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ + u16 version; /**< decimal */ + u16 header_size; /**< in bytes */ + u16 bdb_size; /**< in bytes */ +}; + +/* strictly speaking, this is a "skip" block, but it has interesting info */ +struct vbios_data { + u8 type; /* 0 == desktop, 1 == mobile */ + u8 relstage; + u8 chipset; + u8 lvds_present:1; + u8 tv_present:1; + u8 rsvd2:6; /* finish byte */ + u8 rsvd3[4]; + u8 signon[155]; + u8 copyright[61]; + u16 code_segment; + u8 dos_boot_mode; + u8 bandwidth_percent; + u8 rsvd4; /* popup memory size */ + u8 resize_pci_bios; + u8 rsvd5; /* is crt already on ddc2 */ +} __attribute__((packed)); + +/* + * There are several types of BIOS data blocks (BDBs), each block has + * an ID and size in the first 3 bytes (ID in first, size in next 2). + * Known types are listed below. + */ +#define BDB_GENERAL_FEATURES 1 +#define BDB_GENERAL_DEFINITIONS 2 +#define BDB_OLD_TOGGLE_LIST 3 +#define BDB_MODE_SUPPORT_LIST 4 +#define BDB_GENERIC_MODE_TABLE 5 +#define BDB_EXT_MMIO_REGS 6 +#define BDB_SWF_IO 7 +#define BDB_SWF_MMIO 8 +#define BDB_DOT_CLOCK_TABLE 9 +#define BDB_MODE_REMOVAL_TABLE 10 +#define BDB_CHILD_DEVICE_TABLE 11 +#define BDB_DRIVER_FEATURES 12 +#define BDB_DRIVER_PERSISTENCE 13 +#define BDB_EXT_TABLE_PTRS 14 +#define BDB_DOT_CLOCK_OVERRIDE 15 +#define BDB_DISPLAY_SELECT 16 +/* 17 rsvd */ +#define BDB_DRIVER_ROTATION 18 +#define BDB_DISPLAY_REMOVE 19 +#define BDB_OEM_CUSTOM 20 +#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ +#define BDB_SDVO_LVDS_OPTIONS 22 +#define BDB_SDVO_PANEL_DTDS 23 +#define BDB_SDVO_LVDS_PNP_IDS 24 +#define BDB_SDVO_LVDS_POWER_SEQ 25 +#define BDB_TV_OPTIONS 26 +#define BDB_LVDS_OPTIONS 40 +#define BDB_LVDS_LFP_DATA_PTRS 41 +#define BDB_LVDS_LFP_DATA 42 +#define BDB_LVDS_BACKLIGHT 43 +#define BDB_LVDS_POWER 44 +#define BDB_SKIP 254 /* VBIOS private block, ignore */ + +struct bdb_general_features { + /* bits 1 */ + u8 panel_fitting:2; + u8 flexaim:1; + u8 msg_enable:1; + u8 clear_screen:3; + u8 color_flip:1; + + /* bits 2 */ + u8 download_ext_vbt:1; + u8 enable_ssc:1; + u8 ssc_freq:1; + u8 enable_lfp_on_override:1; + u8 disable_ssc_ddt:1; + u8 rsvd8:3; /* finish byte */ + + /* bits 3 */ + u8 disable_smooth_vision:1; + u8 single_dvi:1; + u8 rsvd9:6; /* finish byte */ + + /* bits 4 */ + u8 legacy_monitor_detect; + + /* bits 5 */ + u8 int_crt_support:1; + u8 int_tv_support:1; + u8 rsvd11:6; /* finish byte */ +} __attribute__((packed)); + +struct bdb_general_definitions { + /* DDC GPIO */ + u8 crt_ddc_gmbus_pin; + + /* DPMS bits */ + u8 dpms_acpi:1; + u8 skip_boot_crt_detect:1; + u8 dpms_aim:1; + u8 rsvd1:5; /* finish byte */ + + /* boot device bits */ + u8 boot_display[2]; + u8 child_dev_size; + + /* device info */ + u8 tv_or_lvds_info[33]; + u8 dev1[33]; + u8 dev2[33]; + u8 dev3[33]; + u8 dev4[33]; + /* may be another device block here on some platforms */ +}; + +struct bdb_lvds_options { + u8 panel_type; + u8 rsvd1; + /* LVDS capabilities, stored in a dword */ + u8 rsvd2:1; + u8 lvds_edid:1; + u8 pixel_dither:1; + u8 pfit_ratio_auto:1; + u8 pfit_gfx_mode_enhanced:1; + u8 pfit_text_mode_enhanced:1; + u8 pfit_mode:2; + u8 rsvd4; +} __attribute__((packed)); + +/* LFP pointer table contains entries to the struct below */ +struct bdb_lvds_lfp_data_ptr { + u16 fp_timing_offset; /* offsets are from start of bdb */ + u8 fp_table_size; + u16 dvo_timing_offset; + u8 dvo_table_size; + u16 panel_pnp_id_offset; + u8 pnp_table_size; +} __attribute__((packed)); + +struct bdb_lvds_lfp_data_ptrs { + u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ + struct bdb_lvds_lfp_data_ptr ptr[16]; +} __attribute__((packed)); + +/* LFP data has 3 blocks per entry */ +struct lvds_fp_timing { + u16 x_res; + u16 y_res; + u32 lvds_reg; + u32 lvds_reg_val; + u32 pp_on_reg; + u32 pp_on_reg_val; + u32 pp_off_reg; + u32 pp_off_reg_val; + u32 pp_cycle_reg; + u32 pp_cycle_reg_val; + u32 pfit_reg; + u32 pfit_reg_val; + u16 terminator; +} __attribute__((packed)); + +struct lvds_dvo_timing { + u16 clock; /**< In 10khz */ + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_off_lo; + u8 hsync_pulse_width; + u8 vsync_pulse_width:4; + u8 vsync_off:4; + u8 rsvd0:6; + u8 hsync_off_hi:2; + u8 h_image; + u8 v_image; + u8 max_hv; + u8 h_border; + u8 v_border; + u8 rsvd1:3; + u8 digital:2; + u8 vsync_positive:1; + u8 hsync_positive:1; + u8 rsvd2:1; +} __attribute__((packed)); + +struct lvds_pnp_id { + u16 mfg_name; + u16 product_code; + u32 serial; + u8 mfg_week; + u8 mfg_year; +} __attribute__((packed)); + +struct bdb_lvds_lfp_data_entry { + struct lvds_fp_timing fp_timing; + struct lvds_dvo_timing dvo_timing; + struct lvds_pnp_id pnp_id; +} __attribute__((packed)); + +struct bdb_lvds_lfp_data { + struct bdb_lvds_lfp_data_entry data[16]; +} __attribute__((packed)); + +struct aimdb_header { + char signature[16]; + char oem_device[20]; + u16 aimdb_version; + u16 aimdb_header_size; + u16 aimdb_size; +} __attribute__((packed)); + +struct aimdb_block { + u8 aimdb_id; + u16 aimdb_size; +} __attribute__((packed)); + +struct vch_panel_data { + u16 fp_timing_offset; + u8 fp_timing_size; + u16 dvo_timing_offset; + u8 dvo_timing_size; + u16 text_fitting_offset; + u8 text_fitting_size; + u16 graphics_fitting_offset; + u8 graphics_fitting_size; +} __attribute__((packed)); + +struct vch_bdb_22 { + struct aimdb_block aimdb_block; + struct vch_panel_data panels[16]; +} __attribute__((packed)); + +bool intel_init_bios(struct drm_device *dev); + +/* + * Driver<->VBIOS interaction occurs through scratch bits in + * GR18 & SWF*. + */ + +/* GR18 bits are set on display switch and hotkey events */ +#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ +#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ +#define GR18_HK_NONE (0x0<<3) +#define GR18_HK_LFP_STRETCH (0x1<<3) +#define GR18_HK_TOGGLE_DISP (0x2<<3) +#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ +#define GR18_HK_POPUP_DISABLED (0x6<<3) +#define GR18_HK_POPUP_ENABLED (0x7<<3) +#define GR18_HK_PFIT (0x8<<3) +#define GR18_HK_APM_CHANGE (0xa<<3) +#define GR18_HK_MULTIPLE (0xc<<3) +#define GR18_USER_INT_EN (1<<2) +#define GR18_A0000_FLUSH_EN (1<<1) +#define GR18_SMM_EN (1<<0) + +/* Set by driver, cleared by VBIOS */ +#define SWF00_YRES_SHIFT 16 +#define SWF00_XRES_SHIFT 0 +#define SWF00_RES_MASK 0xffff + +/* Set by VBIOS at boot time and driver at runtime */ +#define SWF01_TV2_FORMAT_SHIFT 8 +#define SWF01_TV1_FORMAT_SHIFT 0 +#define SWF01_TV_FORMAT_MASK 0xffff + +#define SWF10_VBIOS_BLC_I2C_EN (1<<29) +#define SWF10_GTT_OVERRIDE_EN (1<<28) +#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ +#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) +#define SWF10_OLD_TOGGLE 0x0 +#define SWF10_TOGGLE_LIST_1 0x1 +#define SWF10_TOGGLE_LIST_2 0x2 +#define SWF10_TOGGLE_LIST_3 0x3 +#define SWF10_TOGGLE_LIST_4 0x4 +#define SWF10_PANNING_EN (1<<23) +#define SWF10_DRIVER_LOADED (1<<22) +#define SWF10_EXTENDED_DESKTOP (1<<21) +#define SWF10_EXCLUSIVE_MODE (1<<20) +#define SWF10_OVERLAY_EN (1<<19) +#define SWF10_PLANEB_HOLDOFF (1<<18) +#define SWF10_PLANEA_HOLDOFF (1<<17) +#define SWF10_VGA_HOLDOFF (1<<16) +#define SWF10_ACTIVE_DISP_MASK 0xffff +#define SWF10_PIPEB_LFP2 (1<<15) +#define SWF10_PIPEB_EFP2 (1<<14) +#define SWF10_PIPEB_TV2 (1<<13) +#define SWF10_PIPEB_CRT2 (1<<12) +#define SWF10_PIPEB_LFP (1<<11) +#define SWF10_PIPEB_EFP (1<<10) +#define SWF10_PIPEB_TV (1<<9) +#define SWF10_PIPEB_CRT (1<<8) +#define SWF10_PIPEA_LFP2 (1<<7) +#define SWF10_PIPEA_EFP2 (1<<6) +#define SWF10_PIPEA_TV2 (1<<5) +#define SWF10_PIPEA_CRT2 (1<<4) +#define SWF10_PIPEA_LFP (1<<3) +#define SWF10_PIPEA_EFP (1<<2) +#define SWF10_PIPEA_TV (1<<1) +#define SWF10_PIPEA_CRT (1<<0) + +#define SWF11_MEMORY_SIZE_SHIFT 16 +#define SWF11_SV_TEST_EN (1<<15) +#define SWF11_IS_AGP (1<<14) +#define SWF11_DISPLAY_HOLDOFF (1<<13) +#define SWF11_DPMS_REDUCED (1<<12) +#define SWF11_IS_VBE_MODE (1<<11) +#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ +#define SWF11_DPMS_MASK 0x07 +#define SWF11_DPMS_OFF (1<<2) +#define SWF11_DPMS_SUSPEND (1<<1) +#define SWF11_DPMS_STANDBY (1<<0) +#define SWF11_DPMS_ON 0 + +#define SWF14_GFX_PFIT_EN (1<<31) +#define SWF14_TEXT_PFIT_EN (1<<30) +#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ +#define SWF14_POPUP_EN (1<<28) +#define SWF14_DISPLAY_HOLDOFF (1<<27) +#define SWF14_DISP_DETECT_EN (1<<26) +#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ +#define SWF14_DRIVER_STATUS (1<<24) +#define SWF14_OS_TYPE_WIN9X (1<<23) +#define SWF14_OS_TYPE_WINNT (1<<22) +/* 21:19 rsvd */ +#define SWF14_PM_TYPE_MASK 0x00070000 +#define SWF14_PM_ACPI_VIDEO (0x4 << 16) +#define SWF14_PM_ACPI (0x3 << 16) +#define SWF14_PM_APM_12 (0x2 << 16) +#define SWF14_PM_APM_11 (0x1 << 16) +#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ + /* if GR18 indicates a display switch */ +#define SWF14_DS_PIPEB_LFP2_EN (1<<15) +#define SWF14_DS_PIPEB_EFP2_EN (1<<14) +#define SWF14_DS_PIPEB_TV2_EN (1<<13) +#define SWF14_DS_PIPEB_CRT2_EN (1<<12) +#define SWF14_DS_PIPEB_LFP_EN (1<<11) +#define SWF14_DS_PIPEB_EFP_EN (1<<10) +#define SWF14_DS_PIPEB_TV_EN (1<<9) +#define SWF14_DS_PIPEB_CRT_EN (1<<8) +#define SWF14_DS_PIPEA_LFP2_EN (1<<7) +#define SWF14_DS_PIPEA_EFP2_EN (1<<6) +#define SWF14_DS_PIPEA_TV2_EN (1<<5) +#define SWF14_DS_PIPEA_CRT2_EN (1<<4) +#define SWF14_DS_PIPEA_LFP_EN (1<<3) +#define SWF14_DS_PIPEA_EFP_EN (1<<2) +#define SWF14_DS_PIPEA_TV_EN (1<<1) +#define SWF14_DS_PIPEA_CRT_EN (1<<0) + /* if GR18 indicates a panel fitting request */ +#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ + /* if GR18 indicates an APM change request */ +#define SWF14_APM_HIBERNATE 0x4 +#define SWF14_APM_SUSPEND 0x3 +#define SWF14_APM_STANDBY 0x1 +#define SWF14_APM_RESTORE 0x0 + +#endif /* _I830_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c new file mode 100644 index 000000000000..dcaed3466e83 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -0,0 +1,284 @@ +/* + * Copyright © 2006-2007 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ + +#include <linux/i2c.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +static void intel_crt_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 temp; + + temp = I915_READ(ADPA); + temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); + temp &= ~ADPA_DAC_ENABLE; + + switch(mode) { + case DRM_MODE_DPMS_ON: + temp |= ADPA_DAC_ENABLE; + break; + case DRM_MODE_DPMS_STANDBY: + temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; + break; + case DRM_MODE_DPMS_SUSPEND: + temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; + break; + case DRM_MODE_DPMS_OFF: + temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; + break; + } + + I915_WRITE(ADPA, temp); +} + +static int intel_crt_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (mode->clock > 400000 || mode->clock < 25000) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + +static bool intel_crt_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void intel_crt_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc = encoder->crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_i915_private *dev_priv = dev->dev_private; + int dpll_md_reg; + u32 adpa, dpll_md; + + if (intel_crtc->pipe == 0) + dpll_md_reg = DPLL_A_MD; + else + dpll_md_reg = DPLL_B_MD; + + /* + * Disable separate mode multiplier used when cloning SDVO to CRT + * XXX this needs to be adjusted when we really are cloning + */ + if (IS_I965G(dev)) { + dpll_md = I915_READ(dpll_md_reg); + I915_WRITE(dpll_md_reg, + dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); + } + + adpa = 0; + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + adpa |= ADPA_HSYNC_ACTIVE_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + adpa |= ADPA_VSYNC_ACTIVE_HIGH; + + if (intel_crtc->pipe == 0) + adpa |= ADPA_PIPE_A_SELECT; + else + adpa |= ADPA_PIPE_B_SELECT; + + I915_WRITE(ADPA, adpa); +} + +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. + * + * Not for i915G/i915GM + * + * \return true if CRT is connected. + * \return false if CRT is disconnected. + */ +static bool intel_crt_detect_hotplug(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 temp; + + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + temp = I915_READ(PORT_HOTPLUG_EN); + + I915_WRITE(PORT_HOTPLUG_EN, + temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5)); + + do { + if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT)) + break; + msleep(1); + } while (time_after(timeout, jiffies)); + + if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == + CRT_HOTPLUG_MONITOR_COLOR) + return true; + + return false; +} + +static bool intel_crt_detect_ddc(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + /* CRT should always be at 0, but check anyway */ + if (intel_output->type != INTEL_OUTPUT_ANALOG) + return false; + + return intel_ddc_probe(intel_output); +} + +static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { + if (intel_crt_detect_hotplug(connector)) + return connector_status_connected; + else + return connector_status_disconnected; + } + + if (intel_crt_detect_ddc(connector)) + return connector_status_connected; + + /* TODO use load detect */ + return connector_status_unknown; +} + +static void intel_crt_destroy(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + intel_i2c_destroy(intel_output->ddc_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +static int intel_crt_get_modes(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + return intel_ddc_get_modes(intel_output); +} + +static int intel_crt_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t value) +{ + struct drm_device *dev = connector->dev; + + if (property == dev->mode_config.dpms_property && connector->encoder) + intel_crt_dpms(connector->encoder, (uint32_t)(value & 0xf)); + + return 0; +} + +/* + * Routines for controlling stuff on the analog port + */ + +static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = { + .dpms = intel_crt_dpms, + .mode_fixup = intel_crt_mode_fixup, + .prepare = intel_encoder_prepare, + .commit = intel_encoder_commit, + .mode_set = intel_crt_mode_set, +}; + +static const struct drm_connector_funcs intel_crt_connector_funcs = { + .detect = intel_crt_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = intel_crt_destroy, + .set_property = intel_crt_set_property, +}; + +static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { + .mode_valid = intel_crt_mode_valid, + .get_modes = intel_crt_get_modes, + .best_encoder = intel_best_encoder, +}; + +static void intel_crt_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_crt_enc_funcs = { + .destroy = intel_crt_enc_destroy, +}; + +void intel_crt_init(struct drm_device *dev) +{ + struct drm_connector *connector; + struct intel_output *intel_output; + + intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); + if (!intel_output) + return; + + connector = &intel_output->base; + drm_connector_init(dev, &intel_output->base, + &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); + + drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs, + DRM_MODE_ENCODER_DAC); + + drm_mode_connector_attach_encoder(&intel_output->base, + &intel_output->enc); + + /* Set up the DDC bus. */ + intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A"); + if (!intel_output->ddc_bus) { + dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " + "failed.\n"); + return; + } + + intel_output->type = INTEL_OUTPUT_ANALOG; + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); + drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); + + drm_sysfs_connector_add(connector); +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c new file mode 100644 index 000000000000..e5c1c80d1f90 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_display.c @@ -0,0 +1,1618 @@ +/* + * Copyright © 2006-2007 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ + +#include <linux/i2c.h> +#include "drmP.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +#include "drm_crtc_helper.h" + +bool intel_pipe_has_type (struct drm_crtc *crtc, int type); + +typedef struct { + /* given values */ + int n; + int m1, m2; + int p1, p2; + /* derived values */ + int dot; + int vco; + int m; + int p; +} intel_clock_t; + +typedef struct { + int min, max; +} intel_range_t; + +typedef struct { + int dot_limit; + int p2_slow, p2_fast; +} intel_p2_t; + +#define INTEL_P2_NUM 2 + +typedef struct { + intel_range_t dot, vco, n, m, m1, m2, p, p1; + intel_p2_t p2; +} intel_limit_t; + +#define I8XX_DOT_MIN 25000 +#define I8XX_DOT_MAX 350000 +#define I8XX_VCO_MIN 930000 +#define I8XX_VCO_MAX 1400000 +#define I8XX_N_MIN 3 +#define I8XX_N_MAX 16 +#define I8XX_M_MIN 96 +#define I8XX_M_MAX 140 +#define I8XX_M1_MIN 18 +#define I8XX_M1_MAX 26 +#define I8XX_M2_MIN 6 +#define I8XX_M2_MAX 16 +#define I8XX_P_MIN 4 +#define I8XX_P_MAX 128 +#define I8XX_P1_MIN 2 +#define I8XX_P1_MAX 33 +#define I8XX_P1_LVDS_MIN 1 +#define I8XX_P1_LVDS_MAX 6 +#define I8XX_P2_SLOW 4 +#define I8XX_P2_FAST 2 +#define I8XX_P2_LVDS_SLOW 14 +#define I8XX_P2_LVDS_FAST 14 /* No fast option */ +#define I8XX_P2_SLOW_LIMIT 165000 + +#define I9XX_DOT_MIN 20000 +#define I9XX_DOT_MAX 400000 +#define I9XX_VCO_MIN 1400000 +#define I9XX_VCO_MAX 2800000 +#define I9XX_N_MIN 3 +#define I9XX_N_MAX 8 +#define I9XX_M_MIN 70 +#define I9XX_M_MAX 120 +#define I9XX_M1_MIN 10 +#define I9XX_M1_MAX 20 +#define I9XX_M2_MIN 5 +#define I9XX_M2_MAX 9 +#define I9XX_P_SDVO_DAC_MIN 5 +#define I9XX_P_SDVO_DAC_MAX 80 +#define I9XX_P_LVDS_MIN 7 +#define I9XX_P_LVDS_MAX 98 +#define I9XX_P1_MIN 1 +#define I9XX_P1_MAX 8 +#define I9XX_P2_SDVO_DAC_SLOW 10 +#define I9XX_P2_SDVO_DAC_FAST 5 +#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 +#define I9XX_P2_LVDS_SLOW 14 +#define I9XX_P2_LVDS_FAST 7 +#define I9XX_P2_LVDS_SLOW_LIMIT 112000 + +#define INTEL_LIMIT_I8XX_DVO_DAC 0 +#define INTEL_LIMIT_I8XX_LVDS 1 +#define INTEL_LIMIT_I9XX_SDVO_DAC 2 +#define INTEL_LIMIT_I9XX_LVDS 3 + +static const intel_limit_t intel_limits[] = { + { /* INTEL_LIMIT_I8XX_DVO_DAC */ + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, + .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, + .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, + }, + { /* INTEL_LIMIT_I8XX_LVDS */ + .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, + .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, + .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, + .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, + .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, + .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, + .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, + .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, + .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, + .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, + }, + { /* INTEL_LIMIT_I9XX_SDVO_DAC */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + }, + { /* INTEL_LIMIT_I9XX_LVDS */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, + .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, + .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, + .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, + .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, + .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + /* The single-channel range is 25-112Mhz, and dual-channel + * is 80-224Mhz. Prefer single channel as much as possible. + */ + .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, + }, +}; + +static const intel_limit_t *intel_limit(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + const intel_limit_t *limit; + + if (IS_I9XX(dev)) { + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + } else { + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; + } + return limit; +} + +/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ + +static void i8xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ + +static void i9xx_clock(int refclk, intel_clock_t *clock) +{ + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +static void intel_clock(struct drm_device *dev, int refclk, + intel_clock_t *clock) +{ + if (IS_I9XX(dev)) + i9xx_clock (refclk, clock); + else + i8xx_clock (refclk, clock); +} + +/** + * Returns whether any output on the specified pipe is of the specified type + */ +bool intel_pipe_has_type (struct drm_crtc *crtc, int type) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *l_entry; + + list_for_each_entry(l_entry, &mode_config->connector_list, head) { + if (l_entry->encoder && + l_entry->encoder->crtc == crtc) { + struct intel_output *intel_output = to_intel_output(l_entry); + if (intel_output->type == type) + return true; + } + } + return false; +} + +#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } +/** + * Returns whether the given set of divisors are valid for a given refclk with + * the given connectors. + */ + +static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) +{ + const intel_limit_t *limit = intel_limit (crtc); + + if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) + INTELPllInvalid ("p1 out of range\n"); + if (clock->p < limit->p.min || limit->p.max < clock->p) + INTELPllInvalid ("p out of range\n"); + if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) + INTELPllInvalid ("m2 out of range\n"); + if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) + INTELPllInvalid ("m1 out of range\n"); + if (clock->m1 <= clock->m2) + INTELPllInvalid ("m1 <= m2\n"); + if (clock->m < limit->m.min || limit->m.max < clock->m) + INTELPllInvalid ("m out of range\n"); + if (clock->n < limit->n.min || limit->n.max < clock->n) + INTELPllInvalid ("n out of range\n"); + if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) + INTELPllInvalid ("vco out of range\n"); + /* XXX: We may need to be checking "Dot clock" depending on the multiplier, + * connector, etc., rather than just a single range. + */ + if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) + INTELPllInvalid ("dot out of range\n"); + + return true; +} + +/** + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ +static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, + int refclk, intel_clock_t *best_clock) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + intel_clock_t clock; + const intel_limit_t *limit = intel_limit(crtc); + int err = target; + + if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + (I915_READ(LVDS) & LVDS_PORT_EN) != 0) { + /* + * For LVDS, if the panel is on, just rely on its current + * settings for dual-channel. We haven't figured out how to + * reliably set up different single/dual channel state, if we + * even can. + */ + if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + LVDS_CLKB_POWER_UP) + clock.p2 = limit->p2.p2_fast; + else + clock.p2 = limit->p2.p2_slow; + } else { + if (target < limit->p2.dot_limit) + clock.p2 = limit->p2.p2_slow; + else + clock.p2 = limit->p2.p2_fast; + } + + memset (best_clock, 0, sizeof (*best_clock)); + + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { + for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && + clock.m2 <= limit->m2.max; clock.m2++) { + for (clock.n = limit->n.min; clock.n <= limit->n.max; + clock.n++) { + for (clock.p1 = limit->p1.min; + clock.p1 <= limit->p1.max; clock.p1++) { + int this_err; + + intel_clock(dev, refclk, &clock); + + if (!intel_PLL_is_valid(crtc, &clock)) + continue; + + this_err = abs(clock.dot - target); + if (this_err < err) { + *best_clock = clock; + err = this_err; + } + } + } + } + } + + return (err != target); +} + +void +intel_wait_for_vblank(struct drm_device *dev) +{ + /* Wait for 20ms, i.e. one cycle at 50hz. */ + udelay(20000); +} + +static void +intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_master_private *master_priv; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj_priv; + struct drm_gem_object *obj; + int pipe = intel_crtc->pipe; + unsigned long Start, Offset; + int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); + int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + u32 dspcntr, alignment; + + /* no fb bound */ + if (!crtc->fb) { + DRM_DEBUG("No FB bound\n"); + return; + } + + intel_fb = to_intel_framebuffer(crtc->fb); + obj = intel_fb->obj; + obj_priv = obj->driver_private; + + switch (obj_priv->tiling_mode) { + case I915_TILING_NONE: + alignment = 64 * 1024; + break; + case I915_TILING_X: + if (IS_I9XX(dev)) + alignment = 1024 * 1024; + else + alignment = 512 * 1024; + break; + case I915_TILING_Y: + /* FIXME: Is this true? */ + DRM_ERROR("Y tiled not allowed for scan out buffers\n"); + return; + default: + BUG(); + } + + if (i915_gem_object_pin(intel_fb->obj, alignment)) + return; + + i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); + + Start = obj_priv->gtt_offset; + Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); + + I915_WRITE(dspstride, crtc->fb->pitch); + + dspcntr = I915_READ(dspcntr_reg); + switch (crtc->fb->bits_per_pixel) { + case 8: + dspcntr |= DISPPLANE_8BPP; + break; + case 16: + if (crtc->fb->depth == 15) + dspcntr |= DISPPLANE_15_16BPP; + else + dspcntr |= DISPPLANE_16BPP; + break; + case 24: + case 32: + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + break; + default: + DRM_ERROR("Unknown color depth\n"); + return; + } + I915_WRITE(dspcntr_reg, dspcntr); + + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); + if (IS_I965G(dev)) { + I915_WRITE(dspbase, Offset); + I915_READ(dspbase); + I915_WRITE(dspsurf, Start); + I915_READ(dspsurf); + } else { + I915_WRITE(dspbase, Start + Offset); + I915_READ(dspbase); + } + + intel_wait_for_vblank(dev); + + if (old_fb) { + intel_fb = to_intel_framebuffer(old_fb); + i915_gem_object_unpin(intel_fb->obj); + } + + if (!dev->primary->master) + return; + + master_priv = dev->primary->master->driver_priv; + if (!master_priv->sarea_priv) + return; + + switch (pipe) { + case 0: + master_priv->sarea_priv->pipeA_x = x; + master_priv->sarea_priv->pipeA_y = y; + break; + case 1: + master_priv->sarea_priv->pipeB_x = x; + master_priv->sarea_priv->pipeB_y = y; + break; + default: + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); + break; + } +} + + + +/** + * Sets the power management mode of the pipe and plane. + * + * This code should probably grow support for turning the cursor off and back + * on appropriately at the same time as we're turning the pipe off/on. + */ +static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_master_private *master_priv; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + u32 temp; + bool enabled; + + /* XXX: When our outputs are all unaware of DPMS modes other than off + * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. + */ + switch (mode) { + case DRM_MODE_DPMS_ON: + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + /* Enable the DPLL */ + temp = I915_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) == 0) { + I915_WRITE(dpll_reg, temp); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + } + + /* Enable the pipe */ + temp = I915_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) == 0) + I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); + + /* Enable the plane */ + temp = I915_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { + I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + } + + intel_crtc_load_lut(crtc); + + /* Give the overlay scaler a chance to enable if it's on this pipe */ + //intel_crtc_dpms_video(crtc, true); TODO + break; + case DRM_MODE_DPMS_OFF: + /* Give the overlay scaler a chance to disable if it's on this pipe */ + //intel_crtc_dpms_video(crtc, FALSE); TODO + + /* Disable the VGA plane that we never use */ + I915_WRITE(VGACNTRL, VGA_DISP_DISABLE); + + /* Disable display plane */ + temp = I915_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { + I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + I915_READ(dspbase_reg); + } + + if (!IS_I9XX(dev)) { + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank(dev); + } + + /* Next, disable display pipes */ + temp = I915_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) != 0) { + I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + I915_READ(pipeconf_reg); + } + + /* Wait for vblank for the disable to take effect. */ + intel_wait_for_vblank(dev); + + temp = I915_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) != 0) { + I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + } + + /* Wait for the clocks to turn off. */ + udelay(150); + break; + } + + if (!dev->primary->master) + return; + + master_priv = dev->primary->master->driver_priv; + if (!master_priv->sarea_priv) + return; + + enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; + + switch (pipe) { + case 0: + master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; + master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; + break; + case 1: + master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; + master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; + break; + default: + DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); + break; + } + + intel_crtc->dpms_mode = mode; +} + +static void intel_crtc_prepare (struct drm_crtc *crtc) +{ + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +} + +static void intel_crtc_commit (struct drm_crtc *crtc) +{ + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +} + +void intel_encoder_prepare (struct drm_encoder *encoder) +{ + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + /* lvds has its own version of prepare see intel_lvds_prepare */ + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); +} + +void intel_encoder_commit (struct drm_encoder *encoder) +{ + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + /* lvds has its own version of commit see intel_lvds_commit */ + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); +} + +static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + + +/** Returns the core display clock speed for i830 - i945 */ +static int intel_get_core_clock_speed(struct drm_device *dev) +{ + + /* Core clock values taken from the published datasheets. + * The 830 may go up to 166 Mhz, which we should check. + */ + if (IS_I945G(dev)) + return 400000; + else if (IS_I915G(dev)) + return 333000; + else if (IS_I945GM(dev) || IS_845G(dev)) + return 200000; + else if (IS_I915GM(dev)) { + u16 gcfgc = 0; + + pci_read_config_word(dev->pdev, GCFGC, &gcfgc); + + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) + return 133000; + else { + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { + case GC_DISPLAY_CLOCK_333_MHZ: + return 333000; + default: + case GC_DISPLAY_CLOCK_190_200_MHZ: + return 190000; + } + } + } else if (IS_I865G(dev)) + return 266000; + else if (IS_I855(dev)) { + u16 hpllcc = 0; + /* Assume that the hardware is in the high speed state. This + * should be the default. + */ + switch (hpllcc & GC_CLOCK_CONTROL_MASK) { + case GC_CLOCK_133_200: + case GC_CLOCK_100_200: + return 200000; + case GC_CLOCK_166_250: + return 250000; + case GC_CLOCK_100_133: + return 133000; + } + } else /* 852, 830 */ + return 133000; + + return 0; /* Silence gcc warning */ +} + + +/** + * Return the pipe currently connected to the panel fitter, + * or -1 if the panel fitter is not present or not in use + */ +static int intel_panel_fitter_pipe (struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 pfit_control; + + /* i830 doesn't have a panel fitter */ + if (IS_I830(dev)) + return -1; + + pfit_control = I915_READ(PFIT_CONTROL); + + /* See if the panel fitter is in use */ + if ((pfit_control & PFIT_ENABLE) == 0) + return -1; + + /* 965 can place panel fitter on either pipe */ + if (IS_I965G(dev)) + return (pfit_control >> 29) & 0x3; + + /* older chips can only use pipe 1 */ + return 1; +} + +static void intel_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + int fp_reg = (pipe == 0) ? FPA0 : FPB0; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; + int refclk; + intel_clock_t clock; + u32 dpll = 0, fp = 0, dspcntr, pipeconf; + bool ok, is_sdvo = false, is_dvo = false; + bool is_crt = false, is_lvds = false, is_tv = false; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + drm_vblank_pre_modeset(dev, pipe); + + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); + + if (!connector->encoder || connector->encoder->crtc != crtc) + continue; + + switch (intel_output->type) { + case INTEL_OUTPUT_LVDS: + is_lvds = true; + break; + case INTEL_OUTPUT_SDVO: + is_sdvo = true; + break; + case INTEL_OUTPUT_DVO: + is_dvo = true; + break; + case INTEL_OUTPUT_TVOUT: + is_tv = true; + break; + case INTEL_OUTPUT_ANALOG: + is_crt = true; + break; + } + } + + if (IS_I9XX(dev)) { + refclk = 96000; + } else { + refclk = 48000; + } + + ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); + if (!ok) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return; + } + + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; + + dpll = DPLL_VGA_MODE_DIS; + if (IS_I9XX(dev)) { + if (is_lvds) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + if (is_sdvo) { + dpll |= DPLL_DVO_HIGH_SPEED; + if (IS_I945G(dev) || IS_I945GM(dev)) { + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + } + } + + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 1)) << 16; + switch (clock.p2) { + case 5: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; + } + if (IS_I965G(dev)) + dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); + } else { + if (is_lvds) { + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + } else { + if (clock.p1 == 2) + dpll |= PLL_P1_DIVIDE_BY_TWO; + else + dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; + if (clock.p2 == 4) + dpll |= PLL_P2_DIVIDE_BY_4; + } + } + + if (is_tv) { + /* XXX: just matching BIOS for now */ +/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ + dpll |= 3; + } + else + dpll |= PLL_REF_INPUT_DREFCLK; + + /* setup pipeconf */ + pipeconf = I915_READ(pipeconf_reg); + + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + + if (pipe == 0) + dspcntr |= DISPPLANE_SEL_PIPE_A; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; + + if (pipe == 0 && !IS_I965G(dev)) { + /* Enable pixel doubling when the dot clock is > 90% of the (display) + * core speed. + * + * XXX: No double-wide on 915GM pipe B. Is that the only reason for the + * pipe == 0 check? + */ + if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10) + pipeconf |= PIPEACONF_DOUBLE_WIDE; + else + pipeconf &= ~PIPEACONF_DOUBLE_WIDE; + } + + dspcntr |= DISPLAY_PLANE_ENABLE; + pipeconf |= PIPEACONF_ENABLE; + dpll |= DPLL_VCO_ENABLE; + + + /* Disable the panel fitter if it was on our pipe */ + if (intel_panel_fitter_pipe(dev) == pipe) + I915_WRITE(PFIT_CONTROL, 0); + + DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(mode); + + + if (dpll & DPLL_VCO_ENABLE) { + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_READ(dpll_reg); + udelay(150); + } + + /* The LVDS pin pair needs to be on before the DPLLs are enabled. + * This is an exception to the general rule that mode_set doesn't turn + * things on. + */ + if (is_lvds) { + u32 lvds = I915_READ(LVDS); + + lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; + /* Set the B0-B3 data pairs corresponding to whether we're going to + * set the DPLLs for dual-channel mode or not. + */ + if (clock.p2 == 7) + lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; + else + lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); + + /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) + * appropriately here, but we need to look more thoroughly into how + * panels behave in the two modes. + */ + + I915_WRITE(LVDS, lvds); + I915_READ(LVDS); + } + + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll); + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + if (IS_I965G(dev)) { + int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; + I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + } else { + /* write it again -- the BIOS does, after all */ + I915_WRITE(dpll_reg, dpll); + } + I915_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); + I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); + I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); + I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); + /* pipesrc and dspsize control the size that is scaled from, which should + * always be the user's requested size. + */ + I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); + I915_WRITE(dsppos_reg, 0); + I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); + I915_WRITE(pipeconf_reg, pipeconf); + I915_READ(pipeconf_reg); + + intel_wait_for_vblank(dev); + + I915_WRITE(dspcntr_reg, dspcntr); + + /* Flush the plane changes */ + intel_pipe_set_base(crtc, x, y, old_fb); + + drm_vblank_post_modeset(dev, pipe); +} + +/** Loads the palette/gamma unit for the CRTC with the prepared values */ +void intel_crtc_load_lut(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; + int i; + + /* The clocks have to be on to load the palette. */ + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + I915_WRITE(palreg + 4 * i, + (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]); + } +} + +static int intel_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, uint32_t height) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_gem_object *bo; + struct drm_i915_gem_object *obj_priv; + int pipe = intel_crtc->pipe; + uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; + uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; + uint32_t temp; + size_t addr; + + DRM_DEBUG("\n"); + + /* if we want to turn off the cursor ignore width and height */ + if (!handle) { + DRM_DEBUG("cursor off\n"); + /* turn of the cursor */ + temp = 0; + temp |= CURSOR_MODE_DISABLE; + + I915_WRITE(control, temp); + I915_WRITE(base, 0); + return 0; + } + + /* Currently we only support 64x64 cursors */ + if (width != 64 || height != 64) { + DRM_ERROR("we currently only support 64x64 cursors\n"); + return -EINVAL; + } + + bo = drm_gem_object_lookup(dev, file_priv, handle); + if (!bo) + return -ENOENT; + + obj_priv = bo->driver_private; + + if (bo->size < width * height * 4) { + DRM_ERROR("buffer is to small\n"); + drm_gem_object_unreference(bo); + return -ENOMEM; + } + + if (dev_priv->cursor_needs_physical) { + addr = dev->agp->base + obj_priv->gtt_offset; + } else { + addr = obj_priv->gtt_offset; + } + + intel_crtc->cursor_addr = addr; + temp = 0; + /* set the pipe for the cursor */ + temp |= (pipe << 28); + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; + + I915_WRITE(control, temp); + I915_WRITE(base, addr); + + return 0; +} + +static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + uint32_t temp = 0; + uint32_t adder; + + if (x < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + x = -x; + } + if (y < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + y = -y; + } + + temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + + adder = intel_crtc->cursor_addr; + I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); + I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); + + return 0; +} + +/** Sets the color ramps on behalf of RandR */ +void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + intel_crtc->lut_r[regno] = red >> 8; + intel_crtc->lut_g[regno] = green >> 8; + intel_crtc->lut_b[regno] = blue >> 8; +} + +static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t size) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int i; + + if (size != 256) + return; + + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = red[i] >> 8; + intel_crtc->lut_g[i] = green[i] >> 8; + intel_crtc->lut_b[i] = blue[i] >> 8; + } + + intel_crtc_load_lut(crtc); +} + +/** + * Get a pipe with a simple mode set on it for doing load-based monitor + * detection. + * + * It will be up to the load-detect code to adjust the pipe as appropriate for + * its requirements. The pipe will be connected to no other outputs. + * + * Currently this code will only succeed if there is a pipe with no outputs + * configured for it. In the future, it could choose to temporarily disable + * some outputs to free up a pipe for its use. + * + * \return crtc, or NULL if no pipes are available. + */ + +/* VESA 640x480x72Hz mode to set on the pipe */ +static struct drm_display_mode load_detect_mode = { + DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, + 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), +}; + +struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, + struct drm_display_mode *mode, + int *dpms_mode) +{ + struct intel_crtc *intel_crtc; + struct drm_crtc *possible_crtc; + struct drm_crtc *supported_crtc =NULL; + struct drm_encoder *encoder = &intel_output->enc; + struct drm_crtc *crtc = NULL; + struct drm_device *dev = encoder->dev; + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + struct drm_crtc_helper_funcs *crtc_funcs; + int i = -1; + + /* + * Algorithm gets a little messy: + * - if the connector already has an assigned crtc, use it (but make + * sure it's on first) + * - try to find the first unused crtc that can drive this connector, + * and use that if we find one + * - if there are no unused crtcs available, try to use the first + * one we found that supports the connector + */ + + /* See if we already have a CRTC for this connector */ + if (encoder->crtc) { + crtc = encoder->crtc; + /* Make sure the crtc and connector are running */ + intel_crtc = to_intel_crtc(crtc); + *dpms_mode = intel_crtc->dpms_mode; + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { + crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); + } + return crtc; + } + + /* Find an unused one (if possible) */ + list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { + i++; + if (!(encoder->possible_crtcs & (1 << i))) + continue; + if (!possible_crtc->enabled) { + crtc = possible_crtc; + break; + } + if (!supported_crtc) + supported_crtc = possible_crtc; + } + + /* + * If we didn't find an unused CRTC, don't use any. + */ + if (!crtc) { + return NULL; + } + + encoder->crtc = crtc; + intel_output->load_detect_temp = true; + + intel_crtc = to_intel_crtc(crtc); + *dpms_mode = intel_crtc->dpms_mode; + + if (!crtc->enabled) { + if (!mode) + mode = &load_detect_mode; + drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb); + } else { + if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { + crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); + } + + /* Add this connector to the crtc */ + encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode); + encoder_funcs->commit(encoder); + } + /* let the connector get through one full cycle before testing */ + intel_wait_for_vblank(dev); + + return crtc; +} + +void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode) +{ + struct drm_encoder *encoder = &intel_output->enc; + struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc = encoder->crtc; + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + + if (intel_output->load_detect_temp) { + encoder->crtc = NULL; + intel_output->load_detect_temp = false; + crtc->enabled = drm_helper_crtc_in_use(crtc); + drm_helper_disable_unused_functions(dev); + } + + /* Switch crtc and output back off if necessary */ + if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) { + if (encoder->crtc == crtc) + encoder_funcs->dpms(encoder, dpms_mode); + crtc_funcs->dpms(crtc, dpms_mode); + } +} + +/* Returns the clock of the currently programmed mode of the given pipe. */ +static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); + u32 fp; + intel_clock_t clock; + + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) + fp = I915_READ((pipe == 0) ? FPA0 : FPB0); + else + fp = I915_READ((pipe == 0) ? FPA1 : FPB1); + + clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; + if (IS_I9XX(dev)) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + + switch (dpll & DPLL_MODE_MASK) { + case DPLLB_MODE_DAC_SERIAL: + clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? + 5 : 10; + break; + case DPLLB_MODE_LVDS: + clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? + 7 : 14; + break; + default: + DRM_DEBUG("Unknown DPLL mode %08x in programmed " + "mode\n", (int)(dpll & DPLL_MODE_MASK)); + return 0; + } + + /* XXX: Handle the 100Mhz refclk */ + i9xx_clock(96000, &clock); + } else { + bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); + + if (is_lvds) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + clock.p2 = 14; + + if ((dpll & PLL_REF_INPUT_MASK) == + PLLB_REF_INPUT_SPREADSPECTRUMIN) { + /* XXX: might not be 66MHz */ + i8xx_clock(66000, &clock); + } else + i8xx_clock(48000, &clock); + } else { + if (dpll & PLL_P1_DIVIDE_BY_TWO) + clock.p1 = 2; + else { + clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >> + DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; + } + if (dpll & PLL_P2_DIVIDE_BY_4) + clock.p2 = 4; + else + clock.p2 = 2; + + i8xx_clock(48000, &clock); + } + } + + /* XXX: It would be nice to validate the clocks, but we can't reuse + * i830PllIsValid() because it relies on the xf86_config connector + * configuration being accurate, which it isn't necessarily. + */ + + return clock.dot; +} + +/** Returns the currently programmed mode of the given pipe. */ +struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, + struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + struct drm_display_mode *mode; + int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); + int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B); + int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); + int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B); + + mode = kzalloc(sizeof(*mode), GFP_KERNEL); + if (!mode) + return NULL; + + mode->clock = intel_crtc_clock_get(dev, crtc); + mode->hdisplay = (htot & 0xffff) + 1; + mode->htotal = ((htot & 0xffff0000) >> 16) + 1; + mode->hsync_start = (hsync & 0xffff) + 1; + mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; + mode->vdisplay = (vtot & 0xffff) + 1; + mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; + mode->vsync_start = (vsync & 0xffff) + 1; + mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; + + drm_mode_set_name(mode); + drm_mode_set_crtcinfo(mode, 0); + + return mode; +} + +static void intel_crtc_destroy(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(intel_crtc); +} + +static const struct drm_crtc_helper_funcs intel_helper_funcs = { + .dpms = intel_crtc_dpms, + .mode_fixup = intel_crtc_mode_fixup, + .mode_set = intel_crtc_mode_set, + .mode_set_base = intel_pipe_set_base, + .prepare = intel_crtc_prepare, + .commit = intel_crtc_commit, +}; + +static const struct drm_crtc_funcs intel_crtc_funcs = { + .cursor_set = intel_crtc_cursor_set, + .cursor_move = intel_crtc_cursor_move, + .gamma_set = intel_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = intel_crtc_destroy, +}; + + +static void intel_crtc_init(struct drm_device *dev, int pipe) +{ + struct intel_crtc *intel_crtc; + int i; + + intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); + if (intel_crtc == NULL) + return; + + drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); + + drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); + intel_crtc->pipe = pipe; + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = i; + intel_crtc->lut_g[i] = i; + intel_crtc->lut_b[i] = i; + } + + intel_crtc->cursor_addr = 0; + intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; + drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); + + intel_crtc->mode_set.crtc = &intel_crtc->base; + intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1); + intel_crtc->mode_set.num_connectors = 0; + + if (i915_fbpercrtc) { + + + + } +} + +struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) +{ + struct drm_crtc *crtc = NULL; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + if (intel_crtc->pipe == pipe) + break; + } + return crtc; +} + +static int intel_connector_clones(struct drm_device *dev, int type_mask) +{ + int index_mask = 0; + struct drm_connector *connector; + int entry = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); + if (type_mask & (1 << intel_output->type)) + index_mask |= (1 << entry); + entry++; + } + return index_mask; +} + + +static void intel_setup_outputs(struct drm_device *dev) +{ + struct drm_connector *connector; + + intel_crt_init(dev); + + /* Set up integrated LVDS */ + if (IS_MOBILE(dev) && !IS_I830(dev)) + intel_lvds_init(dev); + + if (IS_I9XX(dev)) { + intel_sdvo_init(dev, SDVOB); + intel_sdvo_init(dev, SDVOC); + } else + intel_dvo_init(dev); + + if (IS_I9XX(dev) && !IS_I915G(dev)) + intel_tv_init(dev); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); + struct drm_encoder *encoder = &intel_output->enc; + int crtc_mask = 0, clone_mask = 0; + + /* valid crtcs */ + switch(intel_output->type) { + case INTEL_OUTPUT_DVO: + case INTEL_OUTPUT_SDVO: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_ANALOG: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_LVDS: + crtc_mask = (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_LVDS); + break; + case INTEL_OUTPUT_TVOUT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << INTEL_OUTPUT_TVOUT); + break; + } + encoder->possible_crtcs = crtc_mask; + encoder->possible_clones = intel_connector_clones(dev, clone_mask); + } +} + +static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_device *dev = fb->dev; + + if (fb->fbdev) + intelfb_remove(dev, fb); + + drm_framebuffer_cleanup(fb); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(intel_fb->obj); + mutex_unlock(&dev->struct_mutex); + + kfree(intel_fb); +} + +static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_gem_object *object = intel_fb->obj; + + return drm_gem_handle_create(file_priv, object, handle); +} + +static const struct drm_framebuffer_funcs intel_fb_funcs = { + .destroy = intel_user_framebuffer_destroy, + .create_handle = intel_user_framebuffer_create_handle, +}; + +int intel_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd *mode_cmd, + struct drm_framebuffer **fb, + struct drm_gem_object *obj) +{ + struct intel_framebuffer *intel_fb; + int ret; + + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) + return -ENOMEM; + + ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); + if (ret) { + DRM_ERROR("framebuffer init failed %d\n", ret); + return ret; + } + + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); + + intel_fb->obj = obj; + + *fb = &intel_fb->base; + + return 0; +} + + +static struct drm_framebuffer * +intel_user_framebuffer_create(struct drm_device *dev, + struct drm_file *filp, + struct drm_mode_fb_cmd *mode_cmd) +{ + struct drm_gem_object *obj; + struct drm_framebuffer *fb; + int ret; + + obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); + if (!obj) + return NULL; + + ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); + if (ret) { + drm_gem_object_unreference(obj); + return NULL; + } + + return fb; +} + +static const struct drm_mode_config_funcs intel_mode_funcs = { + .fb_create = intel_user_framebuffer_create, + .fb_changed = intelfb_probe, +}; + +void intel_modeset_init(struct drm_device *dev) +{ + int num_pipe; + int i; + + drm_mode_config_init(dev); + + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + dev->mode_config.funcs = (void *)&intel_mode_funcs; + + if (IS_I965G(dev)) { + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192; + } else { + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + } + + /* set memory base */ + if (IS_I9XX(dev)) + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); + else + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); + + if (IS_MOBILE(dev) || IS_I9XX(dev)) + num_pipe = 2; + else + num_pipe = 1; + DRM_DEBUG("%d display pipe%s available.\n", + num_pipe, num_pipe > 1 ? "s" : ""); + + for (i = 0; i < num_pipe; i++) { + intel_crtc_init(dev, i); + } + + intel_setup_outputs(dev); +} + +void intel_modeset_cleanup(struct drm_device *dev) +{ + drm_mode_config_cleanup(dev); +} + + +/* current intel driver doesn't take advantage of encoders + always give back the encoder for the connector +*/ +struct drm_encoder *intel_best_encoder(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + return &intel_output->enc; +} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h new file mode 100644 index 000000000000..407edd5bf582 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> + * Copyright (c) 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef __INTEL_DRV_H__ +#define __INTEL_DRV_H__ + +#include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/i2c-algo-bit.h> +#include "drm_crtc.h" + +#include "drm_crtc_helper.h" +/* + * Display related stuff + */ + +/* store information about an Ixxx DVO */ +/* The i830->i865 use multiple DVOs with multiple i2cs */ +/* the i915, i945 have a single sDVO i2c bus - which is different */ +#define MAX_OUTPUTS 6 +/* maximum connectors per crtcs in the mode set */ +#define INTELFB_CONN_LIMIT 4 + +#define INTEL_I2C_BUS_DVO 1 +#define INTEL_I2C_BUS_SDVO 2 + +/* these are outputs from the chip - integrated only + external chips are via DVO or SDVO output */ +#define INTEL_OUTPUT_UNUSED 0 +#define INTEL_OUTPUT_ANALOG 1 +#define INTEL_OUTPUT_DVO 2 +#define INTEL_OUTPUT_SDVO 3 +#define INTEL_OUTPUT_LVDS 4 +#define INTEL_OUTPUT_TVOUT 5 + +#define INTEL_DVO_CHIP_NONE 0 +#define INTEL_DVO_CHIP_LVDS 1 +#define INTEL_DVO_CHIP_TMDS 2 +#define INTEL_DVO_CHIP_TVOUT 4 + +struct intel_i2c_chan { + struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */ + u32 reg; /* GPIO reg */ + struct i2c_adapter adapter; + struct i2c_algo_bit_data algo; + u8 slave_addr; +}; + +struct intel_framebuffer { + struct drm_framebuffer base; + struct drm_gem_object *obj; +}; + + +struct intel_output { + struct drm_connector base; + + struct drm_encoder enc; + int type; + struct intel_i2c_chan *i2c_bus; /* for control functions */ + struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ + bool load_detect_temp; + void *dev_priv; +}; + +struct intel_crtc { + struct drm_crtc base; + int pipe; + int plane; + uint32_t cursor_addr; + u8 lut_r[256], lut_g[256], lut_b[256]; + int dpms_mode; + struct intel_framebuffer *fbdev_fb; + /* a mode_set for fbdev users on this crtc */ + struct drm_mode_set mode_set; +}; + +#define to_intel_crtc(x) container_of(x, struct intel_crtc, base) +#define to_intel_output(x) container_of(x, struct intel_output, base) +#define enc_to_intel_output(x) container_of(x, struct intel_output, enc) +#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) + +struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, + const char *name); +void intel_i2c_destroy(struct intel_i2c_chan *chan); +int intel_ddc_get_modes(struct intel_output *intel_output); +extern bool intel_ddc_probe(struct intel_output *intel_output); + +extern void intel_crt_init(struct drm_device *dev); +extern void intel_sdvo_init(struct drm_device *dev, int output_device); +extern void intel_dvo_init(struct drm_device *dev); +extern void intel_tv_init(struct drm_device *dev); +extern void intel_lvds_init(struct drm_device *dev); + +extern void intel_crtc_load_lut(struct drm_crtc *crtc); +extern void intel_encoder_prepare (struct drm_encoder *encoder); +extern void intel_encoder_commit (struct drm_encoder *encoder); + +extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); + +extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, + struct drm_crtc *crtc); +extern void intel_wait_for_vblank(struct drm_device *dev); +extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); +extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, + struct drm_display_mode *mode, + int *dpms_mode); +extern void intel_release_load_detect_pipe(struct intel_output *intel_output, + int dpms_mode); + +extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); +extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); +extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); +extern int intelfb_probe(struct drm_device *dev); +extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); +extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc); +extern void intelfb_restore(void); +extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno); + +extern int intel_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd *mode_cmd, + struct drm_framebuffer **fb, + struct drm_gem_object *obj); +#endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c new file mode 100644 index 000000000000..8b8d6e65cd3f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -0,0 +1,495 @@ +/* + * Copyright 2006 Dave Airlie <airlied@linux.ie> + * Copyright © 2006-2007 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ +#include <linux/i2c.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "dvo.h" + +#define SIL164_ADDR 0x38 +#define CH7xxx_ADDR 0x76 +#define TFP410_ADDR 0x38 + +static struct intel_dvo_device intel_dvo_devices[] = { + { + .type = INTEL_DVO_CHIP_TMDS, + .name = "sil164", + .dvo_reg = DVOC, + .slave_addr = SIL164_ADDR, + .dev_ops = &sil164_ops, + }, + { + .type = INTEL_DVO_CHIP_TMDS, + .name = "ch7xxx", + .dvo_reg = DVOC, + .slave_addr = CH7xxx_ADDR, + .dev_ops = &ch7xxx_ops, + }, + { + .type = INTEL_DVO_CHIP_LVDS, + .name = "ivch", + .dvo_reg = DVOA, + .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ + .dev_ops = &ivch_ops, + }, + { + .type = INTEL_DVO_CHIP_TMDS, + .name = "tfp410", + .dvo_reg = DVOC, + .slave_addr = TFP410_ADDR, + .dev_ops = &tfp410_ops, + }, + { + .type = INTEL_DVO_CHIP_LVDS, + .name = "ch7017", + .dvo_reg = DVOC, + .slave_addr = 0x75, + .gpio = GPIOE, + .dev_ops = &ch7017_ops, + } +}; + +static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dvo_device *dvo = intel_output->dev_priv; + u32 dvo_reg = dvo->dvo_reg; + u32 temp = I915_READ(dvo_reg); + + if (mode == DRM_MODE_DPMS_ON) { + I915_WRITE(dvo_reg, temp | DVO_ENABLE); + I915_READ(dvo_reg); + dvo->dev_ops->dpms(dvo, mode); + } else { + dvo->dev_ops->dpms(dvo, mode); + I915_WRITE(dvo_reg, temp & ~DVO_ENABLE); + I915_READ(dvo_reg); + } +} + +static void intel_dvo_save(struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + /* Each output should probably just save the registers it touches, + * but for now, use more overkill. + */ + dev_priv->saveDVOA = I915_READ(DVOA); + dev_priv->saveDVOB = I915_READ(DVOB); + dev_priv->saveDVOC = I915_READ(DVOC); + + dvo->dev_ops->save(dvo); +} + +static void intel_dvo_restore(struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + dvo->dev_ops->restore(dvo); + + I915_WRITE(DVOA, dev_priv->saveDVOA); + I915_WRITE(DVOB, dev_priv->saveDVOB); + I915_WRITE(DVOC, dev_priv->saveDVOC); +} + +static int intel_dvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + /* XXX: Validate clock range */ + + if (dvo->panel_fixed_mode) { + if (mode->hdisplay > dvo->panel_fixed_mode->hdisplay) + return MODE_PANEL; + if (mode->vdisplay > dvo->panel_fixed_mode->vdisplay) + return MODE_PANEL; + } + + return dvo->dev_ops->mode_valid(dvo, mode); +} + +static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + /* If we have timings from the BIOS for the panel, put them in + * to the adjusted mode. The CRTC will be set up for this mode, + * with the panel scaling set up to source from the H/VDisplay + * of the original mode. + */ + if (dvo->panel_fixed_mode != NULL) { +#define C(x) adjusted_mode->x = dvo->panel_fixed_mode->x + C(hdisplay); + C(hsync_start); + C(hsync_end); + C(htotal); + C(vdisplay); + C(vsync_start); + C(vsync_end); + C(vtotal); + C(clock); + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); +#undef C + } + + if (dvo->dev_ops->mode_fixup) + return dvo->dev_ops->mode_fixup(dvo, mode, adjusted_mode); + + return true; +} + +static void intel_dvo_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dvo_device *dvo = intel_output->dev_priv; + int pipe = intel_crtc->pipe; + u32 dvo_val; + u32 dvo_reg = dvo->dvo_reg, dvo_srcdim_reg; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + + switch (dvo_reg) { + case DVOA: + default: + dvo_srcdim_reg = DVOA_SRCDIM; + break; + case DVOB: + dvo_srcdim_reg = DVOB_SRCDIM; + break; + case DVOC: + dvo_srcdim_reg = DVOC_SRCDIM; + break; + } + + dvo->dev_ops->mode_set(dvo, mode, adjusted_mode); + + /* Save the data order, since I don't know what it should be set to. */ + dvo_val = I915_READ(dvo_reg) & + (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | + DVO_BLANK_ACTIVE_HIGH; + + if (pipe == 1) + dvo_val |= DVO_PIPE_B_SELECT; + dvo_val |= DVO_PIPE_STALL; + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + dvo_val |= DVO_HSYNC_ACTIVE_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + dvo_val |= DVO_VSYNC_ACTIVE_HIGH; + + I915_WRITE(dpll_reg, I915_READ(dpll_reg) | DPLL_DVO_HIGH_SPEED); + + /*I915_WRITE(DVOB_SRCDIM, + (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ + I915_WRITE(dvo_srcdim_reg, + (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (adjusted_mode->vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); + /*I915_WRITE(DVOB, dvo_val);*/ + I915_WRITE(dvo_reg, dvo_val); +} + +/** + * Detect the output connection on our DVO device. + * + * Unimplemented. + */ +static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + return dvo->dev_ops->detect(dvo); +} + +static int intel_dvo_get_modes(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + /* We should probably have an i2c driver get_modes function for those + * devices which will have a fixed set of modes determined by the chip + * (TV-out, for example), but for now with just TMDS and LVDS, + * that's not the case. + */ + intel_ddc_get_modes(intel_output); + if (!list_empty(&connector->probed_modes)) + return 1; + + + if (dvo->panel_fixed_mode != NULL) { + struct drm_display_mode *mode; + mode = drm_mode_duplicate(connector->dev, dvo->panel_fixed_mode); + if (mode) { + drm_mode_probed_add(connector, mode); + return 1; + } + } + return 0; +} + +static void intel_dvo_destroy (struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + + if (dvo) { + if (dvo->dev_ops->destroy) + dvo->dev_ops->destroy(dvo); + if (dvo->panel_fixed_mode) + kfree(dvo->panel_fixed_mode); + /* no need, in i830_dvoices[] now */ + //kfree(dvo); + } + if (intel_output->i2c_bus) + intel_i2c_destroy(intel_output->i2c_bus); + if (intel_output->ddc_bus) + intel_i2c_destroy(intel_output->ddc_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(intel_output); +} + +#ifdef RANDR_GET_CRTC_INTERFACE +static struct drm_crtc *intel_dvo_get_crtc(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + int pipe = !!(I915_READ(dvo->dvo_reg) & SDVO_PIPE_B_SELECT); + + return intel_pipe_to_crtc(pScrn, pipe); +} +#endif + +static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = { + .dpms = intel_dvo_dpms, + .mode_fixup = intel_dvo_mode_fixup, + .prepare = intel_encoder_prepare, + .mode_set = intel_dvo_mode_set, + .commit = intel_encoder_commit, +}; + +static const struct drm_connector_funcs intel_dvo_connector_funcs = { + .save = intel_dvo_save, + .restore = intel_dvo_restore, + .detect = intel_dvo_detect, + .destroy = intel_dvo_destroy, + .fill_modes = drm_helper_probe_single_connector_modes, +}; + +static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { + .mode_valid = intel_dvo_mode_valid, + .get_modes = intel_dvo_get_modes, + .best_encoder = intel_best_encoder, +}; + +static void intel_dvo_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_dvo_enc_funcs = { + .destroy = intel_dvo_enc_destroy, +}; + + +/** + * Attempts to get a fixed panel timing for LVDS (currently only the i830). + * + * Other chips with DVO LVDS will need to extend this to deal with the LVDS + * chip being on DVOB/C and having multiple pipes. + */ +static struct drm_display_mode * +intel_dvo_get_current_mode (struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dvo_device *dvo = intel_output->dev_priv; + uint32_t dvo_reg = dvo->dvo_reg; + uint32_t dvo_val = I915_READ(dvo_reg); + struct drm_display_mode *mode = NULL; + + /* If the DVO port is active, that'll be the LVDS, so we can pull out + * its timings to get how the BIOS set up the panel. + */ + if (dvo_val & DVO_ENABLE) { + struct drm_crtc *crtc; + int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; + + crtc = intel_get_crtc_from_pipe(dev, pipe); + if (crtc) { + mode = intel_crtc_mode_get(dev, crtc); + + if (mode) { + mode->type |= DRM_MODE_TYPE_PREFERRED; + if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PHSYNC; + if (dvo_val & DVO_VSYNC_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PVSYNC; + } + } + } + return mode; +} + +void intel_dvo_init(struct drm_device *dev) +{ + struct intel_output *intel_output; + struct intel_dvo_device *dvo; + struct intel_i2c_chan *i2cbus = NULL; + int ret = 0; + int i; + int gpio_inited = 0; + int encoder_type = DRM_MODE_ENCODER_NONE; + intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); + if (!intel_output) + return; + + /* Set up the DDC bus */ + intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D"); + if (!intel_output->ddc_bus) + goto free_intel; + + /* Now, try to find a controller */ + for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { + struct drm_connector *connector = &intel_output->base; + int gpio; + + dvo = &intel_dvo_devices[i]; + + /* Allow the I2C driver info to specify the GPIO to be used in + * special cases, but otherwise default to what's defined + * in the spec. + */ + if (dvo->gpio != 0) + gpio = dvo->gpio; + else if (dvo->type == INTEL_DVO_CHIP_LVDS) + gpio = GPIOB; + else + gpio = GPIOE; + + /* Set up the I2C bus necessary for the chip we're probing. + * It appears that everything is on GPIOE except for panels + * on i830 laptops, which are on GPIOB (DVOA). + */ + if (gpio_inited != gpio) { + if (i2cbus != NULL) + intel_i2c_destroy(i2cbus); + if (!(i2cbus = intel_i2c_create(dev, gpio, + gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { + continue; + } + gpio_inited = gpio; + } + + if (dvo->dev_ops!= NULL) + ret = dvo->dev_ops->init(dvo, i2cbus); + else + ret = false; + + if (!ret) + continue; + + intel_output->type = INTEL_OUTPUT_DVO; + switch (dvo->type) { + case INTEL_DVO_CHIP_TMDS: + drm_connector_init(dev, connector, + &intel_dvo_connector_funcs, + DRM_MODE_CONNECTOR_DVII); + encoder_type = DRM_MODE_ENCODER_TMDS; + break; + case INTEL_DVO_CHIP_LVDS: + drm_connector_init(dev, connector, + &intel_dvo_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + encoder_type = DRM_MODE_ENCODER_LVDS; + break; + } + + drm_connector_helper_add(connector, + &intel_dvo_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + intel_output->dev_priv = dvo; + intel_output->i2c_bus = i2cbus; + + drm_encoder_init(dev, &intel_output->enc, + &intel_dvo_enc_funcs, encoder_type); + drm_encoder_helper_add(&intel_output->enc, + &intel_dvo_helper_funcs); + + drm_mode_connector_attach_encoder(&intel_output->base, + &intel_output->enc); + if (dvo->type == INTEL_DVO_CHIP_LVDS) { + /* For our LVDS chipsets, we should hopefully be able + * to dig the fixed panel mode out of the BIOS data. + * However, it's in a different format from the BIOS + * data on chipsets with integrated LVDS (stored in AIM + * headers, likely), so for now, just get the current + * mode being output through DVO. + */ + dvo->panel_fixed_mode = + intel_dvo_get_current_mode(connector); + dvo->panel_wants_dither = true; + } + + drm_sysfs_connector_add(connector); + return; + } + + intel_i2c_destroy(intel_output->ddc_bus); + /* Didn't find a chip, so tear down. */ + if (i2cbus != NULL) + intel_i2c_destroy(i2cbus); +free_intel: + kfree(intel_output); +} diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c new file mode 100644 index 000000000000..afd1217b8a02 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -0,0 +1,925 @@ +/* + * Copyright © 2007 David Airlie + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * David Airlie + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/sysrq.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> + +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +struct intelfb_par { + struct drm_device *dev; + struct drm_display_mode *our_mode; + struct intel_framebuffer *intel_fb; + int crtc_count; + /* crtc currently bound to this */ + uint32_t crtc_ids[2]; +}; + +static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct intelfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_crtc *crtc; + int i; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_mode_set *modeset = &intel_crtc->mode_set; + struct drm_framebuffer *fb = modeset->fb; + + for (i = 0; i < par->crtc_count; i++) + if (crtc->base.id == par->crtc_ids[i]) + break; + + if (i == par->crtc_count) + continue; + + + if (regno > 255) + return 1; + + if (fb->depth == 8) { + intel_crtc_fb_gamma_set(crtc, red, green, blue, regno); + return 0; + } + + if (regno < 16) { + switch (fb->depth) { + case 15: + fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | + ((green & 0xf800) >> 6) | + ((blue & 0xf800) >> 11); + break; + case 16: + fb->pseudo_palette[regno] = (red & 0xf800) | + ((green & 0xfc00) >> 5) | + ((blue & 0xf800) >> 11); + break; + case 24: + case 32: + fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | + (green & 0xff00) | + ((blue & 0xff00) >> 8); + break; + } + } + } + return 0; +} + +static int intelfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct intelfb_par *par = info->par; + struct intel_framebuffer *intel_fb = par->intel_fb; + struct drm_framebuffer *fb = &intel_fb->base; + int depth; + + if (var->pixclock == -1 || !var->pixclock) + return -EINVAL; + + /* Need to resize the fb object !!! */ + if (var->xres > fb->width || var->yres > fb->height) { + DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height); + DRM_ERROR("Need resizing code.\n"); + return -EINVAL; + } + + switch (var->bits_per_pixel) { + case 16: + depth = (var->green.length == 6) ? 16 : 15; + break; + case 32: + depth = (var->transp.length > 0) ? 32 : 24; + break; + default: + depth = var->bits_per_pixel; + break; + } + + switch (depth) { + case 8: + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 15: + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 1; + var->transp.offset = 15; + break; + case 16: + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 24: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 32: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 8; + var->transp.offset = 24; + break; + default: + return -EINVAL; + } + + return 0; +} + +/* this will let fbcon do the mode init */ +/* FIXME: take mode config lock? */ +static int intelfb_set_par(struct fb_info *info) +{ + struct intelfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct fb_var_screeninfo *var = &info->var; + int i; + + DRM_DEBUG("%d %d\n", var->xres, var->pixclock); + + if (var->pixclock != -1) { + + DRM_ERROR("PIXEL CLCOK SET\n"); + return -EINVAL; + } else { + struct drm_crtc *crtc; + int ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + for (i = 0; i < par->crtc_count; i++) + if (crtc->base.id == par->crtc_ids[i]) + break; + + if (i == par->crtc_count) + continue; + + if (crtc->fb == intel_crtc->mode_set.fb) { + mutex_lock(&dev->mode_config.mutex); + ret = crtc->funcs->set_config(&intel_crtc->mode_set); + mutex_unlock(&dev->mode_config.mutex); + if (ret) + return ret; + } + } + return 0; + } +} + +static int intelfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct intelfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_mode_set *modeset; + struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + int ret = 0; + int i; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for (i = 0; i < par->crtc_count; i++) + if (crtc->base.id == par->crtc_ids[i]) + break; + + if (i == par->crtc_count) + continue; + + intel_crtc = to_intel_crtc(crtc); + modeset = &intel_crtc->mode_set; + + modeset->x = var->xoffset; + modeset->y = var->yoffset; + + if (modeset->num_connectors) { + mutex_lock(&dev->mode_config.mutex); + ret = crtc->funcs->set_config(modeset); + mutex_unlock(&dev->mode_config.mutex); + if (!ret) { + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + } + } + } + + return ret; +} + +static void intelfb_on(struct fb_info *info) +{ + struct intelfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_crtc *crtc; + struct drm_encoder *encoder; + int i; + + /* + * For each CRTC in this fb, find all associated encoders + * and turn them off, then turn off the CRTC. + */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + + for (i = 0; i < par->crtc_count; i++) + if (crtc->base.id == par->crtc_ids[i]) + break; + + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); + + /* Found a CRTC on this fb, now find encoders */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + struct drm_encoder_helper_funcs *encoder_funcs; + encoder_funcs = encoder->helper_private; + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); + } + } + } +} + +static void intelfb_off(struct fb_info *info, int dpms_mode) +{ + struct intelfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_crtc *crtc; + struct drm_encoder *encoder; + int i; + + /* + * For each CRTC in this fb, find all associated encoders + * and turn them off, then turn off the CRTC. + */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + + for (i = 0; i < par->crtc_count; i++) + if (crtc->base.id == par->crtc_ids[i]) + break; + + /* Found a CRTC on this fb, now find encoders */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + struct drm_encoder_helper_funcs *encoder_funcs; + encoder_funcs = encoder->helper_private; + encoder_funcs->dpms(encoder, dpms_mode); + } + } + if (dpms_mode == DRM_MODE_DPMS_OFF) + crtc_funcs->dpms(crtc, dpms_mode); + } +} + +static int intelfb_blank(int blank, struct fb_info *info) +{ + switch (blank) { + case FB_BLANK_UNBLANK: + intelfb_on(info); + break; + case FB_BLANK_NORMAL: + intelfb_off(info, DRM_MODE_DPMS_STANDBY); + break; + case FB_BLANK_HSYNC_SUSPEND: + intelfb_off(info, DRM_MODE_DPMS_STANDBY); + break; + case FB_BLANK_VSYNC_SUSPEND: + intelfb_off(info, DRM_MODE_DPMS_SUSPEND); + break; + case FB_BLANK_POWERDOWN: + intelfb_off(info, DRM_MODE_DPMS_OFF); + break; + } + return 0; +} + +static struct fb_ops intelfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = intelfb_check_var, + .fb_set_par = intelfb_set_par, + .fb_setcolreg = intelfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_pan_display = intelfb_pan_display, + .fb_blank = intelfb_blank, +}; + +/** + * Curretly it is assumed that the old framebuffer is reused. + * + * LOCKING + * caller should hold the mode config lock. + * + */ +int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct fb_info *info; + struct drm_framebuffer *fb; + struct drm_display_mode *mode = crtc->desired_mode; + + fb = crtc->fb; + if (!fb) + return 1; + + info = fb->fbdev; + if (!info) + return 1; + + if (!mode) + return 1; + + info->var.xres = mode->hdisplay; + info->var.right_margin = mode->hsync_start - mode->hdisplay; + info->var.hsync_len = mode->hsync_end - mode->hsync_start; + info->var.left_margin = mode->htotal - mode->hsync_end; + info->var.yres = mode->vdisplay; + info->var.lower_margin = mode->vsync_start - mode->vdisplay; + info->var.vsync_len = mode->vsync_end - mode->vsync_start; + info->var.upper_margin = mode->vtotal - mode->vsync_end; + info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100; + /* avoid overflow */ + info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; + + return 0; +} +EXPORT_SYMBOL(intelfb_resize); + +static struct drm_mode_set kernelfb_mode; + +static int intelfb_panic(struct notifier_block *n, unsigned long ununsed, + void *panic_str) +{ + DRM_ERROR("panic occurred, switching back to text console\n"); + + intelfb_restore(); + return 0; +} + +static struct notifier_block paniced = { + .notifier_call = intelfb_panic, +}; + +static int intelfb_create(struct drm_device *dev, uint32_t fb_width, + uint32_t fb_height, uint32_t surface_width, + uint32_t surface_height, + struct intel_framebuffer **intel_fb_p) +{ + struct fb_info *info; + struct intelfb_par *par; + struct drm_framebuffer *fb; + struct intel_framebuffer *intel_fb; + struct drm_mode_fb_cmd mode_cmd; + struct drm_gem_object *fbo = NULL; + struct drm_i915_gem_object *obj_priv; + struct device *device = &dev->pdev->dev; + int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; + + mode_cmd.width = surface_width; + mode_cmd.height = surface_height; + + mode_cmd.bpp = 32; + mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); + mode_cmd.depth = 24; + + size = mode_cmd.pitch * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + fbo = drm_gem_object_alloc(dev, size); + if (!fbo) { + printk(KERN_ERR "failed to allocate framebuffer\n"); + ret = -ENOMEM; + goto out; + } + obj_priv = fbo->driver_private; + + mutex_lock(&dev->struct_mutex); + + ret = i915_gem_object_pin(fbo, PAGE_SIZE); + if (ret) { + DRM_ERROR("failed to pin fb: %d\n", ret); + goto out_unref; + } + + /* Flush everything out, we'll be doing GTT only from now on */ + i915_gem_object_set_to_gtt_domain(fbo, 1); + + ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); + if (ret) { + DRM_ERROR("failed to allocate fb.\n"); + goto out_unref; + } + + list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); + + intel_fb = to_intel_framebuffer(fb); + *intel_fb_p = intel_fb; + + info = framebuffer_alloc(sizeof(struct intelfb_par), device); + if (!info) { + ret = -ENOMEM; + goto out_unref; + } + + par = info->par; + + strcpy(info->fix.id, "inteldrmfb"); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.type_aux = 0; + info->fix.xpanstep = 1; /* doing it in hw */ + info->fix.ypanstep = 1; /* doing it in hw */ + info->fix.ywrapstep = 0; + info->fix.accel = FB_ACCEL_I830; + info->fix.type_aux = 0; + + info->flags = FBINFO_DEFAULT; + + info->fbops = &intelfb_ops; + + info->fix.line_length = fb->pitch; + info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; + info->fix.smem_len = size; + + info->flags = FBINFO_DEFAULT; + + info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, + size); + if (!info->screen_base) { + ret = -ENOSPC; + goto out_unref; + } + info->screen_size = size; + +// memset(info->screen_base, 0, size); + + info->pseudo_palette = fb->pseudo_palette; + info->var.xres_virtual = fb->width; + info->var.yres_virtual = fb->height; + info->var.bits_per_pixel = fb->bits_per_pixel; + info->var.xoffset = 0; + info->var.yoffset = 0; + info->var.activate = FB_ACTIVATE_NOW; + info->var.height = -1; + info->var.width = -1; + + info->var.xres = fb_width; + info->var.yres = fb_height; + + /* FIXME: we really shouldn't expose mmio space at all */ + info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar); + info->fix.mmio_len = pci_resource_len(dev->pdev, mmio_bar); + + info->pixmap.size = 64*1024; + info->pixmap.buf_align = 8; + info->pixmap.access_align = 32; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + info->pixmap.scan_align = 1; + + switch(fb->depth) { + case 8: + info->var.red.offset = 0; + info->var.green.offset = 0; + info->var.blue.offset = 0; + info->var.red.length = 8; /* 8bit DAC */ + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 0; + info->var.transp.length = 0; + break; + case 15: + info->var.red.offset = 10; + info->var.green.offset = 5; + info->var.blue.offset = 0; + info->var.red.length = 5; + info->var.green.length = 5; + info->var.blue.length = 5; + info->var.transp.offset = 15; + info->var.transp.length = 1; + break; + case 16: + info->var.red.offset = 11; + info->var.green.offset = 5; + info->var.blue.offset = 0; + info->var.red.length = 5; + info->var.green.length = 6; + info->var.blue.length = 5; + info->var.transp.offset = 0; + break; + case 24: + info->var.red.offset = 16; + info->var.green.offset = 8; + info->var.blue.offset = 0; + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 0; + info->var.transp.length = 0; + break; + case 32: + info->var.red.offset = 16; + info->var.green.offset = 8; + info->var.blue.offset = 0; + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 24; + info->var.transp.length = 8; + break; + default: + break; + } + + fb->fbdev = info; + + par->intel_fb = intel_fb; + par->dev = dev; + + /* To allow resizeing without swapping buffers */ + printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, + intel_fb->base.height, obj_priv->gtt_offset, fbo); + + mutex_unlock(&dev->struct_mutex); + return 0; + +out_unref: + drm_gem_object_unreference(fbo); + mutex_unlock(&dev->struct_mutex); +out: + return ret; +} + +static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_framebuffer *intel_fb; + struct drm_framebuffer *fb; + struct drm_connector *connector; + struct fb_info *info; + struct intelfb_par *par; + struct drm_mode_set *modeset; + unsigned int width, height; + int new_fb = 0; + int ret, i, conn_count; + + if (!drm_helper_crtc_in_use(crtc)) + return 0; + + if (!crtc->desired_mode) + return 0; + + width = crtc->desired_mode->hdisplay; + height = crtc->desired_mode->vdisplay; + + /* is there an fb bound to this crtc already */ + if (!intel_crtc->mode_set.fb) { + ret = intelfb_create(dev, width, height, width, height, &intel_fb); + if (ret) + return -EINVAL; + new_fb = 1; + } else { + fb = intel_crtc->mode_set.fb; + intel_fb = to_intel_framebuffer(fb); + if ((intel_fb->base.width < width) || (intel_fb->base.height < height)) + return -EINVAL; + } + + info = intel_fb->base.fbdev; + par = info->par; + + modeset = &intel_crtc->mode_set; + modeset->fb = &intel_fb->base; + conn_count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder) + if (connector->encoder->crtc == modeset->crtc) { + modeset->connectors[conn_count] = connector; + conn_count++; + if (conn_count > INTELFB_CONN_LIMIT) + BUG(); + } + } + + for (i = conn_count; i < INTELFB_CONN_LIMIT; i++) + modeset->connectors[i] = NULL; + + par->crtc_ids[0] = crtc->base.id; + + modeset->num_connectors = conn_count; + if (modeset->mode != modeset->crtc->desired_mode) + modeset->mode = modeset->crtc->desired_mode; + + par->crtc_count = 1; + + if (new_fb) { + info->var.pixclock = -1; + if (register_framebuffer(info) < 0) + return -EINVAL; + } else + intelfb_set_par(info); + + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); + + /* Switch back to kernel console on panic */ + kernelfb_mode = *modeset; + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + printk(KERN_INFO "registered panic notifier\n"); + + return 0; +} + +static int intelfb_multi_fb_probe(struct drm_device *dev) +{ + + struct drm_crtc *crtc; + int ret = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + ret = intelfb_multi_fb_probe_crtc(dev, crtc); + if (ret) + return ret; + } + return ret; +} + +static int intelfb_single_fb_probe(struct drm_device *dev) +{ + struct drm_crtc *crtc; + struct drm_connector *connector; + unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; + unsigned int surface_width = 0, surface_height = 0; + int new_fb = 0; + int crtc_count = 0; + int ret, i, conn_count = 0; + struct intel_framebuffer *intel_fb; + struct fb_info *info; + struct intelfb_par *par; + struct drm_mode_set *modeset = NULL; + + DRM_DEBUG("\n"); + + /* Get a count of crtcs now in use and new min/maxes width/heights */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (!drm_helper_crtc_in_use(crtc)) + continue; + + crtc_count++; + if (!crtc->desired_mode) + continue; + + /* Smallest mode determines console size... */ + if (crtc->desired_mode->hdisplay < fb_width) + fb_width = crtc->desired_mode->hdisplay; + + if (crtc->desired_mode->vdisplay < fb_height) + fb_height = crtc->desired_mode->vdisplay; + + /* ... but largest for memory allocation dimensions */ + if (crtc->desired_mode->hdisplay > surface_width) + surface_width = crtc->desired_mode->hdisplay; + + if (crtc->desired_mode->vdisplay > surface_height) + surface_height = crtc->desired_mode->vdisplay; + } + + if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { + /* hmm everyone went away - assume VGA cable just fell out + and will come back later. */ + DRM_DEBUG("no CRTCs available?\n"); + return 0; + } + +//fail + /* Find the fb for our new config */ + if (list_empty(&dev->mode_config.fb_kernel_list)) { + DRM_DEBUG("creating new fb (console size %dx%d, " + "buffer size %dx%d)\n", fb_width, fb_height, + surface_width, surface_height); + ret = intelfb_create(dev, fb_width, fb_height, surface_width, + surface_height, &intel_fb); + if (ret) + return -EINVAL; + new_fb = 1; + } else { + struct drm_framebuffer *fb; + + fb = list_first_entry(&dev->mode_config.fb_kernel_list, + struct drm_framebuffer, filp_head); + intel_fb = to_intel_framebuffer(fb); + + /* if someone hotplugs something bigger than we have already + * allocated, we are pwned. As really we can't resize an + * fbdev that is in the wild currently due to fbdev not really + * being designed for the lower layers moving stuff around + * under it. + * - so in the grand style of things - punt. + */ + if ((fb->width < surface_width) || + (fb->height < surface_height)) { + DRM_ERROR("fb not large enough for console\n"); + return -EINVAL; + } + } +// fail + + info = intel_fb->base.fbdev; + par = info->par; + + crtc_count = 0; + /* + * For each CRTC, set up the connector list for the CRTC's mode + * set configuration. + */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + modeset = &intel_crtc->mode_set; + modeset->fb = &intel_fb->base; + conn_count = 0; + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + if (!connector->encoder) + continue; + + if(connector->encoder->crtc == modeset->crtc) { + modeset->connectors[conn_count++] = connector; + if (conn_count > INTELFB_CONN_LIMIT) + BUG(); + } + } + + /* Zero out remaining connector pointers */ + for (i = conn_count; i < INTELFB_CONN_LIMIT; i++) + modeset->connectors[i] = NULL; + + par->crtc_ids[crtc_count++] = crtc->base.id; + + modeset->num_connectors = conn_count; + if (modeset->mode != modeset->crtc->desired_mode) + modeset->mode = modeset->crtc->desired_mode; + } + par->crtc_count = crtc_count; + + if (new_fb) { + info->var.pixclock = -1; + if (register_framebuffer(info) < 0) + return -EINVAL; + } else + intelfb_set_par(info); + + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); + + /* Switch back to kernel console on panic */ + kernelfb_mode = *modeset; + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + printk(KERN_INFO "registered panic notifier\n"); + + return 0; +} + +/** + * intelfb_restore - restore the framebuffer console (kernel) config + * + * Restore's the kernel's fbcon mode, used for lastclose & panic paths. + */ +void intelfb_restore(void) +{ + drm_crtc_helper_set_config(&kernelfb_mode); +} + +static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3) +{ + intelfb_restore(); +} + +static struct sysrq_key_op sysrq_intelfb_restore_op = { + .handler = intelfb_sysrq, + .help_msg = "force fb", + .action_msg = "force restore of fb console", +}; + +int intelfb_probe(struct drm_device *dev) +{ + int ret; + + DRM_DEBUG("\n"); + + /* something has changed in the lower levels of hell - deal with it + here */ + + /* two modes : a) 1 fb to rule all crtcs. + b) one fb per crtc. + two actions 1) new connected device + 2) device removed. + case a/1 : if the fb surface isn't big enough - resize the surface fb. + if the fb size isn't big enough - resize fb into surface. + if everything big enough configure the new crtc/etc. + case a/2 : undo the configuration + possibly resize down the fb to fit the new configuration. + case b/1 : see if it is on a new crtc - setup a new fb and add it. + case b/2 : teardown the new fb. + */ + + /* mode a first */ + /* search for an fb */ + if (i915_fbpercrtc == 1) { + ret = intelfb_multi_fb_probe(dev); + } else { + ret = intelfb_single_fb_probe(dev); + } + + register_sysrq_key('g', &sysrq_intelfb_restore_op); + + return ret; +} +EXPORT_SYMBOL(intelfb_probe); + +int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) +{ + struct fb_info *info; + + if (!fb) + return -EINVAL; + + info = fb->fbdev; + + if (info) { + unregister_framebuffer(info); + iounmap(info->screen_base); + framebuffer_release(info); + } + + atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); + memset(&kernelfb_mode, 0, sizeof(struct drm_mode_set)); + return 0; +} +EXPORT_SYMBOL(intelfb_remove); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c new file mode 100644 index 000000000000..a5a2f5339e9e --- /dev/null +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> + * Copyright © 2006-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ +#include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/i2c-algo-bit.h> +#include "drmP.h" +#include "drm.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +/* + * Intel GPIO access functions + */ + +#define I2C_RISEFALL_TIME 20 + +static int get_clock(void *data) +{ + struct intel_i2c_chan *chan = data; + struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; + u32 val; + + val = I915_READ(chan->reg); + return ((val & GPIO_CLOCK_VAL_IN) != 0); +} + +static int get_data(void *data) +{ + struct intel_i2c_chan *chan = data; + struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; + u32 val; + + val = I915_READ(chan->reg); + return ((val & GPIO_DATA_VAL_IN) != 0); +} + +static void set_clock(void *data, int state_high) +{ + struct intel_i2c_chan *chan = data; + struct drm_device *dev = chan->drm_dev; + struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; + u32 reserved = 0, clock_bits; + + /* On most chips, these bits must be preserved in software. */ + if (!IS_I830(dev) && !IS_845G(dev)) + reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | + GPIO_CLOCK_PULLUP_DISABLE); + + if (state_high) + clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; + else + clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | + GPIO_CLOCK_VAL_MASK; + I915_WRITE(chan->reg, reserved | clock_bits); + udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ +} + +static void set_data(void *data, int state_high) +{ + struct intel_i2c_chan *chan = data; + struct drm_device *dev = chan->drm_dev; + struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; + u32 reserved = 0, data_bits; + + /* On most chips, these bits must be preserved in software. */ + if (!IS_I830(dev) && !IS_845G(dev)) + reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | + GPIO_CLOCK_PULLUP_DISABLE); + + if (state_high) + data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; + else + data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | + GPIO_DATA_VAL_MASK; + + I915_WRITE(chan->reg, reserved | data_bits); + udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ +} + +/** + * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg + * @dev: DRM device + * @output: driver specific output device + * @reg: GPIO reg to use + * @name: name for this bus + * + * Creates and registers a new i2c bus with the Linux i2c layer, for use + * in output probing and control (e.g. DDC or SDVO control functions). + * + * Possible values for @reg include: + * %GPIOA + * %GPIOB + * %GPIOC + * %GPIOD + * %GPIOE + * %GPIOF + * %GPIOG + * %GPIOH + * see PRM for details on how these different busses are used. + */ +struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, + const char *name) +{ + struct intel_i2c_chan *chan; + + chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); + if (!chan) + goto out_free; + + chan->drm_dev = dev; + chan->reg = reg; + snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); + chan->adapter.owner = THIS_MODULE; +#ifndef I2C_HW_B_INTELFB +#define I2C_HW_B_INTELFB I2C_HW_B_I810 +#endif + chan->adapter.id = I2C_HW_B_INTELFB; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &dev->pdev->dev; + chan->algo.setsda = set_data; + chan->algo.setscl = set_clock; + chan->algo.getsda = get_data; + chan->algo.getscl = get_clock; + chan->algo.udelay = 20; + chan->algo.timeout = usecs_to_jiffies(2200); + chan->algo.data = chan; + + i2c_set_adapdata(&chan->adapter, chan); + + if(i2c_bit_add_bus(&chan->adapter)) + goto out_free; + + /* JJJ: raise SCL and SDA? */ + set_data(chan, 1); + set_clock(chan, 1); + udelay(20); + + return chan; + +out_free: + kfree(chan); + return NULL; +} + +/** + * intel_i2c_destroy - unregister and free i2c bus resources + * @output: channel to free + * + * Unregister the adapter from the i2c layer, then free the structure. + */ +void intel_i2c_destroy(struct intel_i2c_chan *chan) +{ + if (!chan) + return; + + i2c_del_adapter(&chan->adapter); + kfree(chan); +} diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c new file mode 100644 index 000000000000..ccecfaf6307b --- /dev/null +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -0,0 +1,525 @@ +/* + * Copyright © 2006-2007 Intel Corporation + * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Dave Airlie <airlied@linux.ie> + * Jesse Barnes <jesse.barnes@intel.com> + */ + +#include <linux/i2c.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_edid.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +/** + * Sets the backlight level. + * + * \param level backlight level, from 0 to intel_lvds_get_max_backlight(). + */ +static void intel_lvds_set_backlight(struct drm_device *dev, int level) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 blc_pwm_ctl; + + blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | + (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); +} + +/** + * Returns the maximum level of the backlight duty cycle field. + */ +static u32 intel_lvds_get_max_backlight(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >> + BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; +} + +/** + * Sets the power state for the panel. + */ +static void intel_lvds_set_power(struct drm_device *dev, bool on) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_status; + + if (on) { + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | + POWER_TARGET_ON); + do { + pp_status = I915_READ(PP_STATUS); + } while ((pp_status & PP_ON) == 0); + + intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); + } else { + intel_lvds_set_backlight(dev, 0); + + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & + ~POWER_TARGET_ON); + do { + pp_status = I915_READ(PP_STATUS); + } while (pp_status & PP_ON); + } +} + +static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + + if (mode == DRM_MODE_DPMS_ON) + intel_lvds_set_power(dev, true); + else + intel_lvds_set_power(dev, false); + + /* XXX: We never power down the LVDS pairs. */ +} + +static void intel_lvds_save(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS); + dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS); + dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); + dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); + dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + + /* + * If the light is off at server startup, just make it full brightness + */ + if (dev_priv->backlight_duty_cycle == 0) + dev_priv->backlight_duty_cycle = + intel_lvds_get_max_backlight(dev); +} + +static void intel_lvds_restore(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); + I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON); + I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF); + I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); + I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) + intel_lvds_set_power(dev, true); + else + intel_lvds_set_power(dev, false); +} + +static int intel_lvds_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode; + + if (fixed_mode) { + if (mode->hdisplay > fixed_mode->hdisplay) + return MODE_PANEL; + if (mode->vdisplay > fixed_mode->vdisplay) + return MODE_PANEL; + } + + return MODE_OK; +} + +static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct drm_encoder *tmp_encoder; + + /* Should never happen!! */ + if (!IS_I965G(dev) && intel_crtc->pipe == 0) { + printk(KERN_ERR "Can't support LVDS on pipe A\n"); + return false; + } + + /* Should never happen!! */ + list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { + if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { + printk(KERN_ERR "Can't enable LVDS and another " + "encoder on the same pipe\n"); + return false; + } + } + + /* + * If we have timings from the BIOS for the panel, put them in + * to the adjusted mode. The CRTC will be set up for this mode, + * with the panel scaling set up to source from the H/VDisplay + * of the original mode. + */ + if (dev_priv->panel_fixed_mode != NULL) { + adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay; + adjusted_mode->hsync_start = + dev_priv->panel_fixed_mode->hsync_start; + adjusted_mode->hsync_end = + dev_priv->panel_fixed_mode->hsync_end; + adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal; + adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay; + adjusted_mode->vsync_start = + dev_priv->panel_fixed_mode->vsync_start; + adjusted_mode->vsync_end = + dev_priv->panel_fixed_mode->vsync_end; + adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal; + adjusted_mode->clock = dev_priv->panel_fixed_mode->clock; + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + } + + /* + * XXX: It would be nice to support lower refresh rates on the + * panels to reduce power consumption, and perhaps match the + * user's requested refresh rate. + */ + + return true; +} + +static void intel_lvds_prepare(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + + intel_lvds_set_power(dev, false); +} + +static void intel_lvds_commit( struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->backlight_duty_cycle == 0) + dev_priv->backlight_duty_cycle = + intel_lvds_get_max_backlight(dev); + + intel_lvds_set_power(dev, true); +} + +static void intel_lvds_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + u32 pfit_control; + + /* + * The LVDS pin pair will already have been turned on in the + * intel_crtc_mode_set since it has a large impact on the DPLL + * settings. + */ + + /* + * Enable automatic panel scaling so that non-native modes fill the + * screen. Should be enabled before the pipe is enabled, according to + * register description and PRM. + */ + if (mode->hdisplay != adjusted_mode->hdisplay || + mode->vdisplay != adjusted_mode->vdisplay) + pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | + HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + else + pfit_control = 0; + + if (!IS_I965G(dev)) { + if (dev_priv->panel_wants_dither) + pfit_control |= PANEL_8TO6_DITHER_ENABLE; + } + else + pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; + + I915_WRITE(PFIT_CONTROL, pfit_control); +} + +/** + * Detect the LVDS connection. + * + * This always returns CONNECTOR_STATUS_CONNECTED. This connector should only have + * been set up if the LVDS was actually connected anyway. + */ +static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) +{ + return connector_status_connected; +} + +/** + * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. + */ +static int intel_lvds_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct intel_output *intel_output = to_intel_output(connector); + struct drm_i915_private *dev_priv = dev->dev_private; + int ret = 0; + + ret = intel_ddc_get_modes(intel_output); + + if (ret) + return ret; + + /* Didn't get an EDID, so + * Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + connector->display_info.min_vfreq = 0; + connector->display_info.max_vfreq = 200; + connector->display_info.min_hfreq = 0; + connector->display_info.max_hfreq = 200; + + if (dev_priv->panel_fixed_mode != NULL) { + struct drm_display_mode *mode; + + mutex_unlock(&dev->mode_config.mutex); + mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); + drm_mode_probed_add(connector, mode); + mutex_unlock(&dev->mode_config.mutex); + + return 1; + } + + return 0; +} + +/** + * intel_lvds_destroy - unregister and free LVDS structures + * @connector: connector to free + * + * Unregister the DDC bus for this connector then free the driver private + * structure. + */ +static void intel_lvds_destroy(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + if (intel_output->ddc_bus) + intel_i2c_destroy(intel_output->ddc_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { + .dpms = intel_lvds_dpms, + .mode_fixup = intel_lvds_mode_fixup, + .prepare = intel_lvds_prepare, + .mode_set = intel_lvds_mode_set, + .commit = intel_lvds_commit, +}; + +static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { + .get_modes = intel_lvds_get_modes, + .mode_valid = intel_lvds_mode_valid, + .best_encoder = intel_best_encoder, +}; + +static const struct drm_connector_funcs intel_lvds_connector_funcs = { + .save = intel_lvds_save, + .restore = intel_lvds_restore, + .detect = intel_lvds_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = intel_lvds_destroy, +}; + + +static void intel_lvds_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_lvds_enc_funcs = { + .destroy = intel_lvds_enc_destroy, +}; + + + +/** + * intel_lvds_init - setup LVDS connectors on this device + * @dev: drm device + * + * Create the connector, register the LVDS DDC bus, and try to figure out what + * modes we can display on the LVDS panel (if present). + */ +void intel_lvds_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_display_mode *scan; /* *modes, *bios_mode; */ + struct drm_crtc *crtc; + u32 lvds; + int pipe; + + intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); + if (!intel_output) { + return; + } + + connector = &intel_output->base; + encoder = &intel_output->enc; + drm_connector_init(dev, &intel_output->base, &intel_lvds_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + + drm_encoder_init(dev, &intel_output->enc, &intel_lvds_enc_funcs, + DRM_MODE_ENCODER_LVDS); + + drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); + intel_output->type = INTEL_OUTPUT_LVDS; + + drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); + drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + + /* + * LVDS discovery: + * 1) check for EDID on DDC + * 2) check for VBT data + * 3) check to see if LVDS is already on + * if none of the above, no panel + * 4) make sure lid is open + * if closed, act like it's not there for now + */ + + /* Set up the DDC bus. */ + intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); + if (!intel_output->ddc_bus) { + dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " + "failed.\n"); + goto failed; + } + + /* + * Attempt to get the fixed panel mode from DDC. Assume that the + * preferred mode is the right one. + */ + intel_ddc_get_modes(intel_output); + + list_for_each_entry(scan, &connector->probed_modes, head) { + mutex_lock(&dev->mode_config.mutex); + if (scan->type & DRM_MODE_TYPE_PREFERRED) { + dev_priv->panel_fixed_mode = + drm_mode_duplicate(dev, scan); + mutex_unlock(&dev->mode_config.mutex); + goto out; /* FIXME: check for quirks */ + } + mutex_unlock(&dev->mode_config.mutex); + } + + /* Failed to get EDID, what about VBT? */ + if (dev_priv->vbt_mode) { + mutex_lock(&dev->mode_config.mutex); + dev_priv->panel_fixed_mode = + drm_mode_duplicate(dev, dev_priv->vbt_mode); + mutex_unlock(&dev->mode_config.mutex); + } + + /* + * If we didn't get EDID, try checking if the panel is already turned + * on. If so, assume that whatever is currently programmed is the + * correct mode. + */ + lvds = I915_READ(LVDS); + pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; + crtc = intel_get_crtc_from_pipe(dev, pipe); + + if (crtc && (lvds & LVDS_PORT_EN)) { + dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc); + if (dev_priv->panel_fixed_mode) { + dev_priv->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + goto out; /* FIXME: check for quirks */ + } + } + + /* If we still don't have a mode after all that, give up. */ + if (!dev_priv->panel_fixed_mode) + goto failed; + + /* FIXME: detect aopen & mac mini type stuff automatically? */ + /* + * Blacklist machines with BIOSes that list an LVDS panel without + * actually having one. + */ + if (IS_I945GM(dev)) { + /* aopen mini pc */ + if (dev->pdev->subsystem_vendor == 0xa0a0) + goto failed; + + if ((dev->pdev->subsystem_vendor == 0x8086) && + (dev->pdev->subsystem_device == 0x7270)) { + /* It's a Mac Mini or Macbook Pro. + * + * Apple hardware is out to get us. The macbook pro + * has a real LVDS panel, but the mac mini does not, + * and they have the same device IDs. We'll + * distinguish by panel size, on the assumption + * that Apple isn't about to make any machines with an + * 800x600 display. + */ + + if (dev_priv->panel_fixed_mode != NULL && + dev_priv->panel_fixed_mode->hdisplay == 800 && + dev_priv->panel_fixed_mode->vdisplay == 600) { + DRM_DEBUG("Suspected Mac Mini, ignoring the LVDS\n"); + goto failed; + } + } + } + + +out: + drm_sysfs_connector_add(connector); + return; + +failed: + DRM_DEBUG("No LVDS modes found, disabling.\n"); + if (intel_output->ddc_bus) + intel_i2c_destroy(intel_output->ddc_bus); + drm_connector_cleanup(connector); + kfree(connector); +} diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c new file mode 100644 index 000000000000..e42019e5d661 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (c) 2007 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <linux/i2c.h> +#include <linux/fb.h> +#include "drmP.h" +#include "intel_drv.h" + +/** + * intel_ddc_probe + * + */ +bool intel_ddc_probe(struct intel_output *intel_output) +{ + u8 out_buf[] = { 0x0, 0x0}; + u8 buf[2]; + int ret; + struct i2c_msg msgs[] = { + { + .addr = 0x50, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = 0x50, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2); + if (ret == 2) + return true; + + return false; +} + +/** + * intel_ddc_get_modes - get modelist from monitor + * @connector: DRM connector device to use + * + * Fetch the EDID information from @connector using the DDC bus. + */ +int intel_ddc_get_modes(struct intel_output *intel_output) +{ + struct edid *edid; + int ret = 0; + + edid = drm_get_edid(&intel_output->base, + &intel_output->ddc_bus->adapter); + if (edid) { + drm_mode_connector_update_edid_property(&intel_output->base, + edid); + ret = drm_add_edid_modes(&intel_output->base, edid); + kfree(edid); + } + + return ret; +} diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c new file mode 100644 index 000000000000..fbbaa4f414a0 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -0,0 +1,1128 @@ +/* + * Copyright 2006 Dave Airlie <airlied@linux.ie> + * Copyright © 2006-2007 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ +#include <linux/i2c.h> +#include <linux/delay.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "intel_sdvo_regs.h" + +#undef SDVO_DEBUG + +struct intel_sdvo_priv { + struct intel_i2c_chan *i2c_bus; + int slaveaddr; + int output_device; + + u16 active_outputs; + + struct intel_sdvo_caps caps; + int pixel_clock_min, pixel_clock_max; + + int save_sdvo_mult; + u16 save_active_outputs; + struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; + struct intel_sdvo_dtd save_output_dtd[16]; + u32 save_SDVOX; +}; + +/** + * Writes the SDVOB or SDVOC with the given value, but always writes both + * SDVOB and SDVOC to work around apparent hardware issues (according to + * comments in the BIOS). + */ +static void intel_sdvo_write_sdvox(struct intel_output *intel_output, u32 val) +{ + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u32 bval = val, cval = val; + int i; + + if (sdvo_priv->output_device == SDVOB) { + cval = I915_READ(SDVOC); + } else { + bval = I915_READ(SDVOB); + } + /* + * Write the registers twice for luck. Sometimes, + * writing them only once doesn't appear to 'stick'. + * The BIOS does this too. Yay, magic + */ + for (i = 0; i < 2; i++) + { + I915_WRITE(SDVOB, bval); + I915_READ(SDVOB); + I915_WRITE(SDVOC, cval); + I915_READ(SDVOC); + } +} + +static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, + u8 *ch) +{ + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2]; + u8 buf[2]; + int ret; + + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->i2c_bus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = sdvo_priv->i2c_bus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) + { + *ch = buf[0]; + return true; + } + + DRM_DEBUG("i2c transfer returned %d\n", ret); + return false; +} + +static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, + u8 ch) +{ + u8 out_buf[2]; + struct i2c_msg msgs[] = { + { + .addr = intel_output->i2c_bus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = ch; + + if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) + { + return true; + } + return false; +} + +#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} +/** Mapping of command numbers to names, for debug output */ +const static struct _sdvo_cmd_name { + u8 cmd; + char *name; +} sdvo_cmd_names[] = { + SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), +}; + +#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") +#define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv) + +#ifdef SDVO_DEBUG +static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, + void *args, int args_len) +{ + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + int i; + + DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); + for (i = 0; i < args_len; i++) + printk("%02X ", ((u8 *)args)[i]); + for (; i < 8; i++) + printk(" "); + for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { + if (cmd == sdvo_cmd_names[i].cmd) { + printk("(%s)", sdvo_cmd_names[i].name); + break; + } + } + if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) + printk("(%02X)",cmd); + printk("\n"); +} +#else +#define intel_sdvo_debug_write(o, c, a, l) +#endif + +static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd, + void *args, int args_len) +{ + int i; + + intel_sdvo_debug_write(intel_output, cmd, args, args_len); + + for (i = 0; i < args_len; i++) { + intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0 - i, + ((u8*)args)[i]); + } + + intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd); +} + +#ifdef SDVO_DEBUG +static const char *cmd_status_names[] = { + "Power on", + "Success", + "Not supported", + "Invalid arg", + "Pending", + "Target not specified", + "Scaling not supported" +}; + +static void intel_sdvo_debug_response(struct intel_output *intel_output, + void *response, int response_len, + u8 status) +{ + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + + DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); + for (i = 0; i < response_len; i++) + printk("%02X ", ((u8 *)response)[i]); + for (; i < 8; i++) + printk(" "); + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) + printk("(%s)", cmd_status_names[status]); + else + printk("(??? %d)", status); + printk("\n"); +} +#else +#define intel_sdvo_debug_response(o, r, l, s) +#endif + +static u8 intel_sdvo_read_response(struct intel_output *intel_output, + void *response, int response_len) +{ + int i; + u8 status; + u8 retry = 50; + + while (retry--) { + /* Read the command response */ + for (i = 0; i < response_len; i++) { + intel_sdvo_read_byte(intel_output, + SDVO_I2C_RETURN_0 + i, + &((u8 *)response)[i]); + } + + /* read the return status */ + intel_sdvo_read_byte(intel_output, SDVO_I2C_CMD_STATUS, + &status); + + intel_sdvo_debug_response(intel_output, response, response_len, + status); + if (status != SDVO_CMD_STATUS_PENDING) + return status; + + mdelay(50); + } + + return status; +} + +static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) +{ + if (mode->clock >= 100000) + return 1; + else if (mode->clock >= 50000) + return 2; + else + return 4; +} + +/** + * Don't check status code from this as it switches the bus back to the + * SDVO chips which defeats the purpose of doing a bus switch in the first + * place. + */ +static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, + u8 target) +{ + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); +} + +static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) +{ + struct intel_sdvo_set_target_input_args targets = {0}; + u8 status; + + if (target_0 && target_1) + return SDVO_CMD_STATUS_NOTSUPP; + + if (target_1) + targets.target_1 = 1; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_INPUT, &targets, + sizeof(targets)); + + status = intel_sdvo_read_response(intel_output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +/** + * Return whether each input is trained. + * + * This function is making an assumption about the layout of the response, + * which should be checked against the docs. + */ +static bool intel_sdvo_get_trained_inputs(struct intel_output *intel_output, bool *input_1, bool *input_2) +{ + struct intel_sdvo_get_trained_inputs_response response; + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0); + status = intel_sdvo_read_response(intel_output, &response, sizeof(response)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + *input_1 = response.input0_trained; + *input_2 = response.input1_trained; + return true; +} + +static bool intel_sdvo_get_active_outputs(struct intel_output *intel_output, + u16 *outputs) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0); + status = intel_sdvo_read_response(intel_output, outputs, sizeof(*outputs)); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_set_active_outputs(struct intel_output *intel_output, + u16 outputs) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, + sizeof(outputs)); + status = intel_sdvo_read_response(intel_output, NULL, 0); + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_set_encoder_power_state(struct intel_output *intel_output, + int mode) +{ + u8 status, state = SDVO_ENCODER_STATE_ON; + + switch (mode) { + case DRM_MODE_DPMS_ON: + state = SDVO_ENCODER_STATE_ON; + break; + case DRM_MODE_DPMS_STANDBY: + state = SDVO_ENCODER_STATE_STANDBY; + break; + case DRM_MODE_DPMS_SUSPEND: + state = SDVO_ENCODER_STATE_SUSPEND; + break; + case DRM_MODE_DPMS_OFF: + state = SDVO_ENCODER_STATE_OFF; + break; + } + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state, + sizeof(state)); + status = intel_sdvo_read_response(intel_output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_get_input_pixel_clock_range(struct intel_output *intel_output, + int *clock_min, + int *clock_max) +{ + struct intel_sdvo_pixel_clock_range clocks; + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, + NULL, 0); + + status = intel_sdvo_read_response(intel_output, &clocks, sizeof(clocks)); + + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + /* Convert the values from units of 10 kHz to kHz. */ + *clock_min = clocks.min * 10; + *clock_max = clocks.max * 10; + + return true; +} + +static bool intel_sdvo_set_target_output(struct intel_output *intel_output, + u16 outputs) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs, + sizeof(outputs)); + + status = intel_sdvo_read_response(intel_output, NULL, 0); + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_get_timing(struct intel_output *intel_output, u8 cmd, + struct intel_sdvo_dtd *dtd) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, cmd, NULL, 0); + status = intel_sdvo_read_response(intel_output, &dtd->part1, + sizeof(dtd->part1)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + intel_sdvo_write_cmd(intel_output, cmd + 1, NULL, 0); + status = intel_sdvo_read_response(intel_output, &dtd->part2, + sizeof(dtd->part2)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + return true; +} + +static bool intel_sdvo_get_input_timing(struct intel_output *intel_output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_get_timing(intel_output, + SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_get_output_timing(struct intel_output *intel_output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_get_timing(intel_output, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_set_timing(struct intel_output *intel_output, u8 cmd, + struct intel_sdvo_dtd *dtd) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, cmd, &dtd->part1, sizeof(dtd->part1)); + status = intel_sdvo_read_response(intel_output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + intel_sdvo_write_cmd(intel_output, cmd + 1, &dtd->part2, sizeof(dtd->part2)); + status = intel_sdvo_read_response(intel_output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + return true; +} + +static bool intel_sdvo_set_input_timing(struct intel_output *intel_output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_set_timing(intel_output, + SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_set_output_timing(struct intel_output *intel_output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_set_timing(intel_output, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); +} + + +static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output) +{ + u8 response, status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0); + status = intel_sdvo_read_response(intel_output, &response, 1); + + if (status != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); + return SDVO_CLOCK_RATE_MULT_1X; + } else { + DRM_DEBUG("Current clock rate multiplier: %d\n", response); + } + + return response; +} + +static bool intel_sdvo_set_clock_rate_mult(struct intel_output *intel_output, u8 val) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1); + status = intel_sdvo_read_response(intel_output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + return true; +} + +static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO + * device will be told of the multiplier during mode_set. + */ + adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); + return true; +} + +static void intel_sdvo_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = encoder->crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u16 width, height; + u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; + u16 h_sync_offset, v_sync_offset; + u32 sdvox; + struct intel_sdvo_dtd output_dtd; + int sdvo_pixel_multiply; + + if (!mode) + return; + + width = mode->crtc_hdisplay; + height = mode->crtc_vdisplay; + + /* do some mode translations */ + h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; + h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; + + v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; + v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; + + h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; + v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; + + output_dtd.part1.clock = mode->clock / 10; + output_dtd.part1.h_active = width & 0xff; + output_dtd.part1.h_blank = h_blank_len & 0xff; + output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | + ((h_blank_len >> 8) & 0xf); + output_dtd.part1.v_active = height & 0xff; + output_dtd.part1.v_blank = v_blank_len & 0xff; + output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | + ((v_blank_len >> 8) & 0xf); + + output_dtd.part2.h_sync_off = h_sync_offset; + output_dtd.part2.h_sync_width = h_sync_len & 0xff; + output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | + (v_sync_len & 0xf); + output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | + ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | + ((v_sync_len & 0x30) >> 4); + + output_dtd.part2.dtd_flags = 0x18; + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + output_dtd.part2.dtd_flags |= 0x2; + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + output_dtd.part2.dtd_flags |= 0x4; + + output_dtd.part2.sdvo_flags = 0; + output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; + output_dtd.part2.reserved = 0; + + /* Set the output timing to the screen */ + intel_sdvo_set_target_output(intel_output, sdvo_priv->active_outputs); + intel_sdvo_set_output_timing(intel_output, &output_dtd); + + /* Set the input timing to the screen. Assume always input 0. */ + intel_sdvo_set_target_input(intel_output, true, false); + + /* We would like to use i830_sdvo_create_preferred_input_timing() to + * provide the device with a timing it can support, if it supports that + * feature. However, presumably we would need to adjust the CRTC to + * output the preferred timing, and we don't support that currently. + */ + intel_sdvo_set_input_timing(intel_output, &output_dtd); + + switch (intel_sdvo_get_pixel_multiplier(mode)) { + case 1: + intel_sdvo_set_clock_rate_mult(intel_output, + SDVO_CLOCK_RATE_MULT_1X); + break; + case 2: + intel_sdvo_set_clock_rate_mult(intel_output, + SDVO_CLOCK_RATE_MULT_2X); + break; + case 4: + intel_sdvo_set_clock_rate_mult(intel_output, + SDVO_CLOCK_RATE_MULT_4X); + break; + } + + /* Set the SDVO control regs. */ + if (0/*IS_I965GM(dev)*/) { + sdvox = SDVO_BORDER_ENABLE; + } else { + sdvox = I915_READ(sdvo_priv->output_device); + switch (sdvo_priv->output_device) { + case SDVOB: + sdvox &= SDVOB_PRESERVE_MASK; + break; + case SDVOC: + sdvox &= SDVOC_PRESERVE_MASK; + break; + } + sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; + } + if (intel_crtc->pipe == 1) + sdvox |= SDVO_PIPE_B_SELECT; + + sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); + if (IS_I965G(dev)) { + /* done in crtc_mode_set as the dpll_md reg must be written + early */ + } else if (IS_I945G(dev) || IS_I945GM(dev)) { + /* done in crtc_mode_set as it lives inside the + dpll register */ + } else { + sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; + } + + intel_sdvo_write_sdvox(intel_output, sdvox); +} + +static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u32 temp; + + if (mode != DRM_MODE_DPMS_ON) { + intel_sdvo_set_active_outputs(intel_output, 0); + if (0) + intel_sdvo_set_encoder_power_state(intel_output, mode); + + if (mode == DRM_MODE_DPMS_OFF) { + temp = I915_READ(sdvo_priv->output_device); + if ((temp & SDVO_ENABLE) != 0) { + intel_sdvo_write_sdvox(intel_output, temp & ~SDVO_ENABLE); + } + } + } else { + bool input1, input2; + int i; + u8 status; + + temp = I915_READ(sdvo_priv->output_device); + if ((temp & SDVO_ENABLE) == 0) + intel_sdvo_write_sdvox(intel_output, temp | SDVO_ENABLE); + for (i = 0; i < 2; i++) + intel_wait_for_vblank(dev); + + status = intel_sdvo_get_trained_inputs(intel_output, &input1, + &input2); + + + /* Warn if the device reported failure to sync. + * A lot of SDVO devices fail to notify of sync, but it's + * a given it the status is a success, we succeeded. + */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + DRM_DEBUG("First %s output reported failure to sync\n", + SDVO_NAME(sdvo_priv)); + } + + if (0) + intel_sdvo_set_encoder_power_state(intel_output, mode); + intel_sdvo_set_active_outputs(intel_output, sdvo_priv->active_outputs); + } + return; +} + +static void intel_sdvo_save(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + int o; + + sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(intel_output); + intel_sdvo_get_active_outputs(intel_output, &sdvo_priv->save_active_outputs); + + if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { + intel_sdvo_set_target_input(intel_output, true, false); + intel_sdvo_get_input_timing(intel_output, + &sdvo_priv->save_input_dtd_1); + } + + if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { + intel_sdvo_set_target_input(intel_output, false, true); + intel_sdvo_get_input_timing(intel_output, + &sdvo_priv->save_input_dtd_2); + } + + for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) + { + u16 this_output = (1 << o); + if (sdvo_priv->caps.output_flags & this_output) + { + intel_sdvo_set_target_output(intel_output, this_output); + intel_sdvo_get_output_timing(intel_output, + &sdvo_priv->save_output_dtd[o]); + } + } + + sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device); +} + +static void intel_sdvo_restore(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + int o; + int i; + bool input1, input2; + u8 status; + + intel_sdvo_set_active_outputs(intel_output, 0); + + for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) + { + u16 this_output = (1 << o); + if (sdvo_priv->caps.output_flags & this_output) { + intel_sdvo_set_target_output(intel_output, this_output); + intel_sdvo_set_output_timing(intel_output, &sdvo_priv->save_output_dtd[o]); + } + } + + if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { + intel_sdvo_set_target_input(intel_output, true, false); + intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_1); + } + + if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { + intel_sdvo_set_target_input(intel_output, false, true); + intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_2); + } + + intel_sdvo_set_clock_rate_mult(intel_output, sdvo_priv->save_sdvo_mult); + + I915_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); + + if (sdvo_priv->save_SDVOX & SDVO_ENABLE) + { + for (i = 0; i < 2; i++) + intel_wait_for_vblank(dev); + status = intel_sdvo_get_trained_inputs(intel_output, &input1, &input2); + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) + DRM_DEBUG("First %s output reported failure to sync\n", + SDVO_NAME(sdvo_priv)); + } + + intel_sdvo_set_active_outputs(intel_output, sdvo_priv->save_active_outputs); +} + +static int intel_sdvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (sdvo_priv->pixel_clock_min > mode->clock) + return MODE_CLOCK_LOW; + + if (sdvo_priv->pixel_clock_max < mode->clock) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static bool intel_sdvo_get_capabilities(struct intel_output *intel_output, struct intel_sdvo_caps *caps) +{ + u8 status; + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0); + status = intel_sdvo_read_response(intel_output, caps, sizeof(*caps)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + return true; +} + +struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB) +{ + struct drm_connector *connector = NULL; + struct intel_output *iout = NULL; + struct intel_sdvo_priv *sdvo; + + /* find the sdvo connector */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + iout = to_intel_output(connector); + + if (iout->type != INTEL_OUTPUT_SDVO) + continue; + + sdvo = iout->dev_priv; + + if (sdvo->output_device == SDVOB && sdvoB) + return connector; + + if (sdvo->output_device == SDVOC && !sdvoB) + return connector; + + } + + return NULL; +} + +int intel_sdvo_supports_hotplug(struct drm_connector *connector) +{ + u8 response[2]; + u8 status; + struct intel_output *intel_output; + DRM_DEBUG("\n"); + + if (!connector) + return 0; + + intel_output = to_intel_output(connector); + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); + status = intel_sdvo_read_response(intel_output, &response, 2); + + if (response[0] !=0) + return 1; + + return 0; +} + +void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) +{ + u8 response[2]; + u8 status; + struct intel_output *intel_output = to_intel_output(connector); + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); + intel_sdvo_read_response(intel_output, &response, 2); + + if (on) { + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); + status = intel_sdvo_read_response(intel_output, &response, 2); + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); + } else { + response[0] = 0; + response[1] = 0; + intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); + } + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); + intel_sdvo_read_response(intel_output, &response, 2); +} + +static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) +{ + u8 response[2]; + u8 status; + struct intel_output *intel_output = to_intel_output(connector); + + intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); + status = intel_sdvo_read_response(intel_output, &response, 2); + + DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); + if ((response[0] != 0) || (response[1] != 0)) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static int intel_sdvo_get_modes(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + /* set the bus switch and get the modes */ + intel_sdvo_set_control_bus_switch(intel_output, SDVO_CONTROL_BUS_DDC2); + intel_ddc_get_modes(intel_output); + + if (list_empty(&connector->probed_modes)) + return 0; + return 1; +} + +static void intel_sdvo_destroy(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + if (intel_output->i2c_bus) + intel_i2c_destroy(intel_output->i2c_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(intel_output); +} + +static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = { + .dpms = intel_sdvo_dpms, + .mode_fixup = intel_sdvo_mode_fixup, + .prepare = intel_encoder_prepare, + .mode_set = intel_sdvo_mode_set, + .commit = intel_encoder_commit, +}; + +static const struct drm_connector_funcs intel_sdvo_connector_funcs = { + .save = intel_sdvo_save, + .restore = intel_sdvo_restore, + .detect = intel_sdvo_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = intel_sdvo_destroy, +}; + +static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = { + .get_modes = intel_sdvo_get_modes, + .mode_valid = intel_sdvo_mode_valid, + .best_encoder = intel_best_encoder, +}; + +static void intel_sdvo_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { + .destroy = intel_sdvo_enc_destroy, +}; + + +void intel_sdvo_init(struct drm_device *dev, int output_device) +{ + struct drm_connector *connector; + struct intel_output *intel_output; + struct intel_sdvo_priv *sdvo_priv; + struct intel_i2c_chan *i2cbus = NULL; + int connector_type; + u8 ch[0x40]; + int i; + int encoder_type, output_id; + + intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); + if (!intel_output) { + return; + } + + connector = &intel_output->base; + + drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, + DRM_MODE_CONNECTOR_Unknown); + drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); + sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); + intel_output->type = INTEL_OUTPUT_SDVO; + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + /* setup the DDC bus. */ + if (output_device == SDVOB) + i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); + else + i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); + + if (!i2cbus) + goto err_connector; + + sdvo_priv->i2c_bus = i2cbus; + + if (output_device == SDVOB) { + output_id = 1; + sdvo_priv->i2c_bus->slave_addr = 0x38; + } else { + output_id = 2; + sdvo_priv->i2c_bus->slave_addr = 0x39; + } + + sdvo_priv->output_device = output_device; + intel_output->i2c_bus = i2cbus; + intel_output->dev_priv = sdvo_priv; + + + /* Read the regs to test if we can talk to the device */ + for (i = 0; i < 0x40; i++) { + if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) { + DRM_DEBUG("No SDVO device found on SDVO%c\n", + output_device == SDVOB ? 'B' : 'C'); + goto err_i2c; + } + } + + intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); + + memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs)); + + /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ + if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + encoder_type = DRM_MODE_ENCODER_DAC; + connector_type = DRM_MODE_CONNECTOR_VGA; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + encoder_type = DRM_MODE_ENCODER_DAC; + connector_type = DRM_MODE_CONNECTOR_VGA; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + encoder_type = DRM_MODE_ENCODER_TMDS; + connector_type = DRM_MODE_CONNECTOR_DVID; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + encoder_type = DRM_MODE_ENCODER_TMDS; + connector_type = DRM_MODE_CONNECTOR_DVID; + } + else + { + unsigned char bytes[2]; + + memcpy (bytes, &sdvo_priv->caps.output_flags, 2); + DRM_DEBUG("%s: No active RGB or TMDS outputs (0x%02x%02x)\n", + SDVO_NAME(sdvo_priv), + bytes[0], bytes[1]); + goto err_i2c; + } + + drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type); + drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); + connector->connector_type = connector_type; + + drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); + drm_sysfs_connector_add(connector); + + /* Set the input timing to the screen. Assume always input 0. */ + intel_sdvo_set_target_input(intel_output, true, false); + + intel_sdvo_get_input_pixel_clock_range(intel_output, + &sdvo_priv->pixel_clock_min, + &sdvo_priv->pixel_clock_max); + + + DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, " + "clock range %dMHz - %dMHz, " + "input 1: %c, input 2: %c, " + "output 1: %c, output 2: %c\n", + SDVO_NAME(sdvo_priv), + sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, + sdvo_priv->caps.device_rev_id, + sdvo_priv->pixel_clock_min / 1000, + sdvo_priv->pixel_clock_max / 1000, + (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', + (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', + /* check currently supported outputs */ + sdvo_priv->caps.output_flags & + (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', + sdvo_priv->caps.output_flags & + (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); + + intel_output->ddc_bus = i2cbus; + + return; + +err_i2c: + intel_i2c_destroy(intel_output->i2c_bus); +err_connector: + drm_connector_cleanup(connector); + kfree(intel_output); + + return; +} diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h new file mode 100644 index 000000000000..861a43f8693c --- /dev/null +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -0,0 +1,327 @@ +/* + * Copyright © 2006-2007 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + */ + +/** + * @file SDVO command definitions and structures. + */ + +#define SDVO_OUTPUT_FIRST (0) +#define SDVO_OUTPUT_TMDS0 (1 << 0) +#define SDVO_OUTPUT_RGB0 (1 << 1) +#define SDVO_OUTPUT_CVBS0 (1 << 2) +#define SDVO_OUTPUT_SVID0 (1 << 3) +#define SDVO_OUTPUT_YPRPB0 (1 << 4) +#define SDVO_OUTPUT_SCART0 (1 << 5) +#define SDVO_OUTPUT_LVDS0 (1 << 6) +#define SDVO_OUTPUT_TMDS1 (1 << 8) +#define SDVO_OUTPUT_RGB1 (1 << 9) +#define SDVO_OUTPUT_CVBS1 (1 << 10) +#define SDVO_OUTPUT_SVID1 (1 << 11) +#define SDVO_OUTPUT_YPRPB1 (1 << 12) +#define SDVO_OUTPUT_SCART1 (1 << 13) +#define SDVO_OUTPUT_LVDS1 (1 << 14) +#define SDVO_OUTPUT_LAST (14) + +struct intel_sdvo_caps { + u8 vendor_id; + u8 device_id; + u8 device_rev_id; + u8 sdvo_version_major; + u8 sdvo_version_minor; + unsigned int sdvo_inputs_mask:2; + unsigned int smooth_scaling:1; + unsigned int sharp_scaling:1; + unsigned int up_scaling:1; + unsigned int down_scaling:1; + unsigned int stall_support:1; + unsigned int pad:1; + u16 output_flags; +} __attribute__((packed)); + +/** This matches the EDID DTD structure, more or less */ +struct intel_sdvo_dtd { + struct { + u16 clock; /**< pixel clock, in 10kHz units */ + u8 h_active; /**< lower 8 bits (pixels) */ + u8 h_blank; /**< lower 8 bits (pixels) */ + u8 h_high; /**< upper 4 bits each h_active, h_blank */ + u8 v_active; /**< lower 8 bits (lines) */ + u8 v_blank; /**< lower 8 bits (lines) */ + u8 v_high; /**< upper 4 bits each v_active, v_blank */ + } part1; + + struct { + u8 h_sync_off; /**< lower 8 bits, from hblank start */ + u8 h_sync_width; /**< lower 8 bits (pixels) */ + /** lower 4 bits each vsync offset, vsync width */ + u8 v_sync_off_width; + /** + * 2 high bits of hsync offset, 2 high bits of hsync width, + * bits 4-5 of vsync offset, and 2 high bits of vsync width. + */ + u8 sync_off_width_high; + u8 dtd_flags; + u8 sdvo_flags; + /** bits 6-7 of vsync offset at bits 6-7 */ + u8 v_sync_off_high; + u8 reserved; + } part2; +} __attribute__((packed)); + +struct intel_sdvo_pixel_clock_range { + u16 min; /**< pixel clock, in 10kHz units */ + u16 max; /**< pixel clock, in 10kHz units */ +} __attribute__((packed)); + +struct intel_sdvo_preferred_input_timing_args { + u16 clock; + u16 width; + u16 height; +} __attribute__((packed)); + +/* I2C registers for SDVO */ +#define SDVO_I2C_ARG_0 0x07 +#define SDVO_I2C_ARG_1 0x06 +#define SDVO_I2C_ARG_2 0x05 +#define SDVO_I2C_ARG_3 0x04 +#define SDVO_I2C_ARG_4 0x03 +#define SDVO_I2C_ARG_5 0x02 +#define SDVO_I2C_ARG_6 0x01 +#define SDVO_I2C_ARG_7 0x00 +#define SDVO_I2C_OPCODE 0x08 +#define SDVO_I2C_CMD_STATUS 0x09 +#define SDVO_I2C_RETURN_0 0x0a +#define SDVO_I2C_RETURN_1 0x0b +#define SDVO_I2C_RETURN_2 0x0c +#define SDVO_I2C_RETURN_3 0x0d +#define SDVO_I2C_RETURN_4 0x0e +#define SDVO_I2C_RETURN_5 0x0f +#define SDVO_I2C_RETURN_6 0x10 +#define SDVO_I2C_RETURN_7 0x11 +#define SDVO_I2C_VENDOR_BEGIN 0x20 + +/* Status results */ +#define SDVO_CMD_STATUS_POWER_ON 0x0 +#define SDVO_CMD_STATUS_SUCCESS 0x1 +#define SDVO_CMD_STATUS_NOTSUPP 0x2 +#define SDVO_CMD_STATUS_INVALID_ARG 0x3 +#define SDVO_CMD_STATUS_PENDING 0x4 +#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 +#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 + +/* SDVO commands, argument/result registers */ + +#define SDVO_CMD_RESET 0x01 + +/** Returns a struct intel_sdvo_caps */ +#define SDVO_CMD_GET_DEVICE_CAPS 0x02 + +#define SDVO_CMD_GET_FIRMWARE_REV 0x86 +# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 +# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 +# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 + +/** + * Reports which inputs are trained (managed to sync). + * + * Devices must have trained within 2 vsyncs of a mode change. + */ +#define SDVO_CMD_GET_TRAINED_INPUTS 0x03 +struct intel_sdvo_get_trained_inputs_response { + unsigned int input0_trained:1; + unsigned int input1_trained:1; + unsigned int pad:6; +} __attribute__((packed)); + +/** Returns a struct intel_sdvo_output_flags of active outputs. */ +#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 + +/** + * Sets the current set of active outputs. + * + * Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP + * on multi-output devices. + */ +#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 + +/** + * Returns the current mapping of SDVO inputs to outputs on the device. + * + * Returns two struct intel_sdvo_output_flags structures. + */ +#define SDVO_CMD_GET_IN_OUT_MAP 0x06 + +/** + * Sets the current mapping of SDVO inputs to outputs on the device. + * + * Takes two struct i380_sdvo_output_flags structures. + */ +#define SDVO_CMD_SET_IN_OUT_MAP 0x07 + +/** + * Returns a struct intel_sdvo_output_flags of attached displays. + */ +#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b + +/** + * Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging. + */ +#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c + +/** + * Takes a struct intel_sdvo_output_flags. + */ +#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d + +/** + * Returns a struct intel_sdvo_output_flags of displays with hot plug + * interrupts enabled. + */ +#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e + +#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f +struct intel_sdvo_get_interrupt_event_source_response { + u16 interrupt_status; + unsigned int ambient_light_interrupt:1; + unsigned int pad:7; +} __attribute__((packed)); + +/** + * Selects which input is affected by future input commands. + * + * Commands affected include SET_INPUT_TIMINGS_PART[12], + * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], + * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. + */ +#define SDVO_CMD_SET_TARGET_INPUT 0x10 +struct intel_sdvo_set_target_input_args { + unsigned int target_1:1; + unsigned int pad:7; +} __attribute__((packed)); + +/** + * Takes a struct intel_sdvo_output_flags of which outputs are targetted by + * future output commands. + * + * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], + * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. + */ +#define SDVO_CMD_SET_TARGET_OUTPUT 0x11 + +#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 +#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 +#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 +#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 +#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 +#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 +#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 +#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 +/* Part 1 */ +# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 +# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 +# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 +# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 +# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 +# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 +# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 +# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 +/* Part 2 */ +# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 +# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 +# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 +# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 +# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 +# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) +# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) +# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) +# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) +# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 +# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) +# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) +# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) +# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) +# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 + +/** + * Generates a DTD based on the given width, height, and flags. + * + * This will be supported by any device supporting scaling or interlaced + * modes. + */ +#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a +# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 +# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 +# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 +# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 +# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 +# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) + +#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b +#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c + +/** Returns a struct intel_sdvo_pixel_clock_range */ +#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d +/** Returns a struct intel_sdvo_pixel_clock_range */ +#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e + +/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ +#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f + +/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 +/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 +# define SDVO_CLOCK_RATE_MULT_1X (1 << 0) +# define SDVO_CLOCK_RATE_MULT_2X (1 << 1) +# define SDVO_CLOCK_RATE_MULT_4X (1 << 3) + +#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 + +#define SDVO_CMD_GET_TV_FORMAT 0x28 + +#define SDVO_CMD_SET_TV_FORMAT 0x29 + +#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a +#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b +#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c +# define SDVO_ENCODER_STATE_ON (1 << 0) +# define SDVO_ENCODER_STATE_STANDBY (1 << 1) +# define SDVO_ENCODER_STATE_SUSPEND (1 << 2) +# define SDVO_ENCODER_STATE_OFF (1 << 3) + +#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 + +#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a +# define SDVO_CONTROL_BUS_PROM 0x0 +# define SDVO_CONTROL_BUS_DDC1 0x1 +# define SDVO_CONTROL_BUS_DDC2 0x2 +# define SDVO_CONTROL_BUS_DDC3 0x3 diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c new file mode 100644 index 000000000000..fbb35dc56f5c --- /dev/null +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -0,0 +1,1725 @@ +/* + * Copyright © 2006-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +/** @file + * Integrated TV-out support for the 915GM and 945GM. + */ + +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_edid.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +enum tv_margin { + TV_MARGIN_LEFT, TV_MARGIN_TOP, + TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM +}; + +/** Private structure for the integrated TV support */ +struct intel_tv_priv { + int type; + char *tv_format; + int margin[4]; + u32 save_TV_H_CTL_1; + u32 save_TV_H_CTL_2; + u32 save_TV_H_CTL_3; + u32 save_TV_V_CTL_1; + u32 save_TV_V_CTL_2; + u32 save_TV_V_CTL_3; + u32 save_TV_V_CTL_4; + u32 save_TV_V_CTL_5; + u32 save_TV_V_CTL_6; + u32 save_TV_V_CTL_7; + u32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3; + + u32 save_TV_CSC_Y; + u32 save_TV_CSC_Y2; + u32 save_TV_CSC_U; + u32 save_TV_CSC_U2; + u32 save_TV_CSC_V; + u32 save_TV_CSC_V2; + u32 save_TV_CLR_KNOBS; + u32 save_TV_CLR_LEVEL; + u32 save_TV_WIN_POS; + u32 save_TV_WIN_SIZE; + u32 save_TV_FILTER_CTL_1; + u32 save_TV_FILTER_CTL_2; + u32 save_TV_FILTER_CTL_3; + + u32 save_TV_H_LUMA[60]; + u32 save_TV_H_CHROMA[60]; + u32 save_TV_V_LUMA[43]; + u32 save_TV_V_CHROMA[43]; + + u32 save_TV_DAC; + u32 save_TV_CTL; +}; + +struct video_levels { + int blank, black, burst; +}; + +struct color_conversion { + u16 ry, gy, by, ay; + u16 ru, gu, bu, au; + u16 rv, gv, bv, av; +}; + +static const u32 filter_table[] = { + 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140, + 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000, + 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160, + 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780, + 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50, + 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20, + 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0, + 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0, + 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020, + 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140, + 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20, + 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848, + 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900, + 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080, + 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060, + 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140, + 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000, + 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160, + 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780, + 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50, + 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20, + 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0, + 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0, + 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020, + 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140, + 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20, + 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848, + 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900, + 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080, + 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060, + 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0, + 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540, + 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00, + 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000, + 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00, + 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40, + 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240, + 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00, + 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0, + 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840, + 0x28003100, 0x28002F00, 0x00003100, 0x36403000, + 0x2D002CC0, 0x30003640, 0x2D0036C0, + 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540, + 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00, + 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000, + 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00, + 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40, + 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240, + 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00, + 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0, + 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840, + 0x28003100, 0x28002F00, 0x00003100, +}; + +/* + * Color conversion values have 3 separate fixed point formats: + * + * 10 bit fields (ay, au) + * 1.9 fixed point (b.bbbbbbbbb) + * 11 bit fields (ry, by, ru, gu, gv) + * exp.mantissa (ee.mmmmmmmmm) + * ee = 00 = 10^-1 (0.mmmmmmmmm) + * ee = 01 = 10^-2 (0.0mmmmmmmmm) + * ee = 10 = 10^-3 (0.00mmmmmmmmm) + * ee = 11 = 10^-4 (0.000mmmmmmmmm) + * 12 bit fields (gy, rv, bu) + * exp.mantissa (eee.mmmmmmmmm) + * eee = 000 = 10^-1 (0.mmmmmmmmm) + * eee = 001 = 10^-2 (0.0mmmmmmmmm) + * eee = 010 = 10^-3 (0.00mmmmmmmmm) + * eee = 011 = 10^-4 (0.000mmmmmmmmm) + * eee = 100 = reserved + * eee = 101 = reserved + * eee = 110 = reserved + * eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation) + * + * Saturation and contrast are 8 bits, with their own representation: + * 8 bit field (saturation, contrast) + * exp.mantissa (ee.mmmmmm) + * ee = 00 = 10^-1 (0.mmmmmm) + * ee = 01 = 10^0 (m.mmmmm) + * ee = 10 = 10^1 (mm.mmmm) + * ee = 11 = 10^2 (mmm.mmm) + * + * Simple conversion function: + * + * static u32 + * float_to_csc_11(float f) + * { + * u32 exp; + * u32 mant; + * u32 ret; + * + * if (f < 0) + * f = -f; + * + * if (f >= 1) { + * exp = 0x7; + * mant = 1 << 8; + * } else { + * for (exp = 0; exp < 3 && f < 0.5; exp++) + * f *= 2.0; + * mant = (f * (1 << 9) + 0.5); + * if (mant >= (1 << 9)) + * mant = (1 << 9) - 1; + * } + * ret = (exp << 9) | mant; + * return ret; + * } + */ + +/* + * Behold, magic numbers! If we plant them they might grow a big + * s-video cable to the sky... or something. + * + * Pre-converted to appropriate hex value. + */ + +/* + * PAL & NTSC values for composite & s-video connections + */ +static const struct color_conversion ntsc_m_csc_composite = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, +}; + +static const struct video_levels ntsc_m_levels_composite = { + .blank = 225, .black = 267, .burst = 113, +}; + +static const struct color_conversion ntsc_m_csc_svideo = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, +}; + +static const struct video_levels ntsc_m_levels_svideo = { + .blank = 266, .black = 316, .burst = 133, +}; + +static const struct color_conversion ntsc_j_csc_composite = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119, + .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0f00, + .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0f00, +}; + +static const struct video_levels ntsc_j_levels_composite = { + .blank = 225, .black = 225, .burst = 113, +}; + +static const struct color_conversion ntsc_j_csc_svideo = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c, + .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0f00, + .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0f00, +}; + +static const struct video_levels ntsc_j_levels_svideo = { + .blank = 266, .black = 266, .burst = 133, +}; + +static const struct color_conversion pal_csc_composite = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113, + .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0f00, + .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0f00, +}; + +static const struct video_levels pal_levels_composite = { + .blank = 237, .black = 237, .burst = 118, +}; + +static const struct color_conversion pal_csc_svideo = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145, + .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0f00, + .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0f00, +}; + +static const struct video_levels pal_levels_svideo = { + .blank = 280, .black = 280, .burst = 139, +}; + +static const struct color_conversion pal_m_csc_composite = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, +}; + +static const struct video_levels pal_m_levels_composite = { + .blank = 225, .black = 267, .burst = 113, +}; + +static const struct color_conversion pal_m_csc_svideo = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, +}; + +static const struct video_levels pal_m_levels_svideo = { + .blank = 266, .black = 316, .burst = 133, +}; + +static const struct color_conversion pal_n_csc_composite = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, +}; + +static const struct video_levels pal_n_levels_composite = { + .blank = 225, .black = 267, .burst = 118, +}; + +static const struct color_conversion pal_n_csc_svideo = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, +}; + +static const struct video_levels pal_n_levels_svideo = { + .blank = 266, .black = 316, .burst = 139, +}; + +/* + * Component connections + */ +static const struct color_conversion sdtv_csc_yprpb = { + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0146, + .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0f00, + .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0f00, +}; + +static const struct color_conversion sdtv_csc_rgb = { + .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166, + .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166, + .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166, +}; + +static const struct color_conversion hdtv_csc_yprpb = { + .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0146, + .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0f00, + .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0f00, +}; + +static const struct color_conversion hdtv_csc_rgb = { + .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166, + .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166, + .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166, +}; + +static const struct video_levels component_levels = { + .blank = 279, .black = 279, .burst = 0, +}; + + +struct tv_mode { + char *name; + int clock; + int refresh; /* in millihertz (for precision) */ + u32 oversample; + int hsync_end, hblank_start, hblank_end, htotal; + bool progressive, trilevel_sync, component_only; + int vsync_start_f1, vsync_start_f2, vsync_len; + bool veq_ena; + int veq_start_f1, veq_start_f2, veq_len; + int vi_end_f1, vi_end_f2, nbr_end; + bool burst_ena; + int hburst_start, hburst_len; + int vburst_start_f1, vburst_end_f1; + int vburst_start_f2, vburst_end_f2; + int vburst_start_f3, vburst_end_f3; + int vburst_start_f4, vburst_end_f4; + /* + * subcarrier programming + */ + int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc; + u32 sc_reset; + bool pal_burst; + /* + * blank/black levels + */ + const struct video_levels *composite_levels, *svideo_levels; + const struct color_conversion *composite_color, *svideo_color; + const u32 *filter_table; + int max_srcw; +}; + + +/* + * Sub carrier DDA + * + * I think this works as follows: + * + * subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096 + * + * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value + * + * So, + * dda1_ideal = subcarrier/pixel * 4096 + * dda1_inc = floor (dda1_ideal) + * dda2 = dda1_ideal - dda1_inc + * + * then pick a ratio for dda2 that gives the closest approximation. If + * you can't get close enough, you can play with dda3 as well. This + * seems likely to happen when dda2 is small as the jumps would be larger + * + * To invert this, + * + * pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size) + * + * The constants below were all computed using a 107.520MHz clock + */ + +/** + * Register programming values for TV modes. + * + * These values account for -1s required. + */ + +const static struct tv_mode tv_modes[] = { + { + .name = "NTSC-M", + .clock = 107520, + .refresh = 29970, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */ + + .hsync_end = 64, .hblank_end = 124, + .hblank_start = 836, .htotal = 857, + + .progressive = false, .trilevel_sync = false, + + .vsync_start_f1 = 6, .vsync_start_f2 = 7, + .vsync_len = 6, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 18, + + .vi_end_f1 = 20, .vi_end_f2 = 21, + .nbr_end = 240, + + .burst_ena = true, + .hburst_start = 72, .hburst_len = 34, + .vburst_start_f1 = 9, .vburst_end_f1 = 240, + .vburst_start_f2 = 10, .vburst_end_f2 = 240, + .vburst_start_f3 = 9, .vburst_end_f3 = 240, + .vburst_start_f4 = 10, .vburst_end_f4 = 240, + + /* desired 3.5800000 actual 3.5800000 clock 107.52 */ + .dda1_inc = 136, + .dda2_inc = 7624, .dda2_size = 20013, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_4, + .pal_burst = false, + + .composite_levels = &ntsc_m_levels_composite, + .composite_color = &ntsc_m_csc_composite, + .svideo_levels = &ntsc_m_levels_svideo, + .svideo_color = &ntsc_m_csc_svideo, + + .filter_table = filter_table, + }, + { + .name = "NTSC-443", + .clock = 107520, + .refresh = 29970, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */ + .hsync_end = 64, .hblank_end = 124, + .hblank_start = 836, .htotal = 857, + + .progressive = false, .trilevel_sync = false, + + .vsync_start_f1 = 6, .vsync_start_f2 = 7, + .vsync_len = 6, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 18, + + .vi_end_f1 = 20, .vi_end_f2 = 21, + .nbr_end = 240, + + .burst_ena = 8, + .hburst_start = 72, .hburst_len = 34, + .vburst_start_f1 = 9, .vburst_end_f1 = 240, + .vburst_start_f2 = 10, .vburst_end_f2 = 240, + .vburst_start_f3 = 9, .vburst_end_f3 = 240, + .vburst_start_f4 = 10, .vburst_end_f4 = 240, + + /* desired 4.4336180 actual 4.4336180 clock 107.52 */ + .dda1_inc = 168, + .dda2_inc = 18557, .dda2_size = 20625, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_8, + .pal_burst = true, + + .composite_levels = &ntsc_m_levels_composite, + .composite_color = &ntsc_m_csc_composite, + .svideo_levels = &ntsc_m_levels_svideo, + .svideo_color = &ntsc_m_csc_svideo, + + .filter_table = filter_table, + }, + { + .name = "NTSC-J", + .clock = 107520, + .refresh = 29970, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + + /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */ + .hsync_end = 64, .hblank_end = 124, + .hblank_start = 836, .htotal = 857, + + .progressive = false, .trilevel_sync = false, + + .vsync_start_f1 = 6, .vsync_start_f2 = 7, + .vsync_len = 6, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 18, + + .vi_end_f1 = 20, .vi_end_f2 = 21, + .nbr_end = 240, + + .burst_ena = true, + .hburst_start = 72, .hburst_len = 34, + .vburst_start_f1 = 9, .vburst_end_f1 = 240, + .vburst_start_f2 = 10, .vburst_end_f2 = 240, + .vburst_start_f3 = 9, .vburst_end_f3 = 240, + .vburst_start_f4 = 10, .vburst_end_f4 = 240, + + /* desired 3.5800000 actual 3.5800000 clock 107.52 */ + .dda1_inc = 136, + .dda2_inc = 7624, .dda2_size = 20013, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_4, + .pal_burst = false, + + .composite_levels = &ntsc_j_levels_composite, + .composite_color = &ntsc_j_csc_composite, + .svideo_levels = &ntsc_j_levels_svideo, + .svideo_color = &ntsc_j_csc_svideo, + + .filter_table = filter_table, + }, + { + .name = "PAL-M", + .clock = 107520, + .refresh = 29970, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + + /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */ + .hsync_end = 64, .hblank_end = 124, + .hblank_start = 836, .htotal = 857, + + .progressive = false, .trilevel_sync = false, + + .vsync_start_f1 = 6, .vsync_start_f2 = 7, + .vsync_len = 6, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 18, + + .vi_end_f1 = 20, .vi_end_f2 = 21, + .nbr_end = 240, + + .burst_ena = true, + .hburst_start = 72, .hburst_len = 34, + .vburst_start_f1 = 9, .vburst_end_f1 = 240, + .vburst_start_f2 = 10, .vburst_end_f2 = 240, + .vburst_start_f3 = 9, .vburst_end_f3 = 240, + .vburst_start_f4 = 10, .vburst_end_f4 = 240, + + /* desired 3.5800000 actual 3.5800000 clock 107.52 */ + .dda1_inc = 136, + .dda2_inc = 7624, .dda2_size = 20013, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_4, + .pal_burst = false, + + .composite_levels = &pal_m_levels_composite, + .composite_color = &pal_m_csc_composite, + .svideo_levels = &pal_m_levels_svideo, + .svideo_color = &pal_m_csc_svideo, + + .filter_table = filter_table, + }, + { + /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ + .name = "PAL-N", + .clock = 107520, + .refresh = 25000, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + + .hsync_end = 64, .hblank_end = 128, + .hblank_start = 844, .htotal = 863, + + .progressive = false, .trilevel_sync = false, + + + .vsync_start_f1 = 6, .vsync_start_f2 = 7, + .vsync_len = 6, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 18, + + .vi_end_f1 = 24, .vi_end_f2 = 25, + .nbr_end = 286, + + .burst_ena = true, + .hburst_start = 73, .hburst_len = 34, + .vburst_start_f1 = 8, .vburst_end_f1 = 285, + .vburst_start_f2 = 8, .vburst_end_f2 = 286, + .vburst_start_f3 = 9, .vburst_end_f3 = 286, + .vburst_start_f4 = 9, .vburst_end_f4 = 285, + + + /* desired 4.4336180 actual 4.4336180 clock 107.52 */ + .dda1_inc = 168, + .dda2_inc = 18557, .dda2_size = 20625, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_8, + .pal_burst = true, + + .composite_levels = &pal_n_levels_composite, + .composite_color = &pal_n_csc_composite, + .svideo_levels = &pal_n_levels_svideo, + .svideo_color = &pal_n_csc_svideo, + + .filter_table = filter_table, + }, + { + /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ + .name = "PAL", + .clock = 107520, + .refresh = 25000, + .oversample = TV_OVERSAMPLE_8X, + .component_only = 0, + + .hsync_end = 64, .hblank_end = 128, + .hblank_start = 844, .htotal = 863, + + .progressive = false, .trilevel_sync = false, + + .vsync_start_f1 = 5, .vsync_start_f2 = 6, + .vsync_len = 5, + + .veq_ena = true, .veq_start_f1 = 0, + .veq_start_f2 = 1, .veq_len = 15, + + .vi_end_f1 = 24, .vi_end_f2 = 25, + .nbr_end = 286, + + .burst_ena = true, + .hburst_start = 73, .hburst_len = 32, + .vburst_start_f1 = 8, .vburst_end_f1 = 285, + .vburst_start_f2 = 8, .vburst_end_f2 = 286, + .vburst_start_f3 = 9, .vburst_end_f3 = 286, + .vburst_start_f4 = 9, .vburst_end_f4 = 285, + + /* desired 4.4336180 actual 4.4336180 clock 107.52 */ + .dda1_inc = 168, + .dda2_inc = 18557, .dda2_size = 20625, + .dda3_inc = 0, .dda3_size = 0, + .sc_reset = TV_SC_RESET_EVERY_8, + .pal_burst = true, + + .composite_levels = &pal_levels_composite, + .composite_color = &pal_csc_composite, + .svideo_levels = &pal_levels_svideo, + .svideo_color = &pal_csc_svideo, + + .filter_table = filter_table, + }, + { + .name = "480p@59.94Hz", + .clock = 107520, + .refresh = 59940, + .oversample = TV_OVERSAMPLE_4X, + .component_only = 1, + + .hsync_end = 64, .hblank_end = 122, + .hblank_start = 842, .htotal = 857, + + .progressive = true,.trilevel_sync = false, + + .vsync_start_f1 = 12, .vsync_start_f2 = 12, + .vsync_len = 12, + + .veq_ena = false, + + .vi_end_f1 = 44, .vi_end_f2 = 44, + .nbr_end = 496, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "480p@60Hz", + .clock = 107520, + .refresh = 60000, + .oversample = TV_OVERSAMPLE_4X, + .component_only = 1, + + .hsync_end = 64, .hblank_end = 122, + .hblank_start = 842, .htotal = 856, + + .progressive = true,.trilevel_sync = false, + + .vsync_start_f1 = 12, .vsync_start_f2 = 12, + .vsync_len = 12, + + .veq_ena = false, + + .vi_end_f1 = 44, .vi_end_f2 = 44, + .nbr_end = 496, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "576p", + .clock = 107520, + .refresh = 50000, + .oversample = TV_OVERSAMPLE_4X, + .component_only = 1, + + .hsync_end = 64, .hblank_end = 139, + .hblank_start = 859, .htotal = 863, + + .progressive = true, .trilevel_sync = false, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, + + .veq_ena = false, + + .vi_end_f1 = 48, .vi_end_f2 = 48, + .nbr_end = 575, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "720p@60Hz", + .clock = 148800, + .refresh = 60000, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 80, .hblank_end = 300, + .hblank_start = 1580, .htotal = 1649, + + .progressive = true, .trilevel_sync = true, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, + + .veq_ena = false, + + .vi_end_f1 = 29, .vi_end_f2 = 29, + .nbr_end = 719, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "720p@59.94Hz", + .clock = 148800, + .refresh = 59940, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 80, .hblank_end = 300, + .hblank_start = 1580, .htotal = 1651, + + .progressive = true, .trilevel_sync = true, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, + + .veq_ena = false, + + .vi_end_f1 = 29, .vi_end_f2 = 29, + .nbr_end = 719, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "720p@50Hz", + .clock = 148800, + .refresh = 50000, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 80, .hblank_end = 300, + .hblank_start = 1580, .htotal = 1979, + + .progressive = true, .trilevel_sync = true, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, + + .veq_ena = false, + + .vi_end_f1 = 29, .vi_end_f2 = 29, + .nbr_end = 719, + + .burst_ena = false, + + .filter_table = filter_table, + .max_srcw = 800 + }, + { + .name = "1080i@50Hz", + .clock = 148800, + .refresh = 25000, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 88, .hblank_end = 235, + .hblank_start = 2155, .htotal = 2639, + + .progressive = false, .trilevel_sync = true, + + .vsync_start_f1 = 4, .vsync_start_f2 = 5, + .vsync_len = 10, + + .veq_ena = true, .veq_start_f1 = 4, + .veq_start_f2 = 4, .veq_len = 10, + + + .vi_end_f1 = 21, .vi_end_f2 = 22, + .nbr_end = 539, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "1080i@60Hz", + .clock = 148800, + .refresh = 30000, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 88, .hblank_end = 235, + .hblank_start = 2155, .htotal = 2199, + + .progressive = false, .trilevel_sync = true, + + .vsync_start_f1 = 4, .vsync_start_f2 = 5, + .vsync_len = 10, + + .veq_ena = true, .veq_start_f1 = 4, + .veq_start_f2 = 4, .veq_len = 10, + + + .vi_end_f1 = 21, .vi_end_f2 = 22, + .nbr_end = 539, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "1080i@59.94Hz", + .clock = 148800, + .refresh = 29970, + .oversample = TV_OVERSAMPLE_2X, + .component_only = 1, + + .hsync_end = 88, .hblank_end = 235, + .hblank_start = 2155, .htotal = 2200, + + .progressive = false, .trilevel_sync = true, + + .vsync_start_f1 = 4, .vsync_start_f2 = 5, + .vsync_len = 10, + + .veq_ena = true, .veq_start_f1 = 4, + .veq_start_f2 = 4, .veq_len = 10, + + + .vi_end_f1 = 21, .vi_end_f2 = 22, + .nbr_end = 539, + + .burst_ena = false, + + .filter_table = filter_table, + }, +}; + +#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0]) + +static void +intel_tv_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + switch(mode) { + case DRM_MODE_DPMS_ON: + I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE); + break; + } +} + +static void +intel_tv_save(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + int i; + + tv_priv->save_TV_H_CTL_1 = I915_READ(TV_H_CTL_1); + tv_priv->save_TV_H_CTL_2 = I915_READ(TV_H_CTL_2); + tv_priv->save_TV_H_CTL_3 = I915_READ(TV_H_CTL_3); + tv_priv->save_TV_V_CTL_1 = I915_READ(TV_V_CTL_1); + tv_priv->save_TV_V_CTL_2 = I915_READ(TV_V_CTL_2); + tv_priv->save_TV_V_CTL_3 = I915_READ(TV_V_CTL_3); + tv_priv->save_TV_V_CTL_4 = I915_READ(TV_V_CTL_4); + tv_priv->save_TV_V_CTL_5 = I915_READ(TV_V_CTL_5); + tv_priv->save_TV_V_CTL_6 = I915_READ(TV_V_CTL_6); + tv_priv->save_TV_V_CTL_7 = I915_READ(TV_V_CTL_7); + tv_priv->save_TV_SC_CTL_1 = I915_READ(TV_SC_CTL_1); + tv_priv->save_TV_SC_CTL_2 = I915_READ(TV_SC_CTL_2); + tv_priv->save_TV_SC_CTL_3 = I915_READ(TV_SC_CTL_3); + + tv_priv->save_TV_CSC_Y = I915_READ(TV_CSC_Y); + tv_priv->save_TV_CSC_Y2 = I915_READ(TV_CSC_Y2); + tv_priv->save_TV_CSC_U = I915_READ(TV_CSC_U); + tv_priv->save_TV_CSC_U2 = I915_READ(TV_CSC_U2); + tv_priv->save_TV_CSC_V = I915_READ(TV_CSC_V); + tv_priv->save_TV_CSC_V2 = I915_READ(TV_CSC_V2); + tv_priv->save_TV_CLR_KNOBS = I915_READ(TV_CLR_KNOBS); + tv_priv->save_TV_CLR_LEVEL = I915_READ(TV_CLR_LEVEL); + tv_priv->save_TV_WIN_POS = I915_READ(TV_WIN_POS); + tv_priv->save_TV_WIN_SIZE = I915_READ(TV_WIN_SIZE); + tv_priv->save_TV_FILTER_CTL_1 = I915_READ(TV_FILTER_CTL_1); + tv_priv->save_TV_FILTER_CTL_2 = I915_READ(TV_FILTER_CTL_2); + tv_priv->save_TV_FILTER_CTL_3 = I915_READ(TV_FILTER_CTL_3); + + for (i = 0; i < 60; i++) + tv_priv->save_TV_H_LUMA[i] = I915_READ(TV_H_LUMA_0 + (i <<2)); + for (i = 0; i < 60; i++) + tv_priv->save_TV_H_CHROMA[i] = I915_READ(TV_H_CHROMA_0 + (i <<2)); + for (i = 0; i < 43; i++) + tv_priv->save_TV_V_LUMA[i] = I915_READ(TV_V_LUMA_0 + (i <<2)); + for (i = 0; i < 43; i++) + tv_priv->save_TV_V_CHROMA[i] = I915_READ(TV_V_CHROMA_0 + (i <<2)); + + tv_priv->save_TV_DAC = I915_READ(TV_DAC); + tv_priv->save_TV_CTL = I915_READ(TV_CTL); +} + +static void +intel_tv_restore(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + struct drm_crtc *crtc = connector->encoder->crtc; + struct intel_crtc *intel_crtc; + int i; + + /* FIXME: No CRTC? */ + if (!crtc) + return; + + intel_crtc = to_intel_crtc(crtc); + I915_WRITE(TV_H_CTL_1, tv_priv->save_TV_H_CTL_1); + I915_WRITE(TV_H_CTL_2, tv_priv->save_TV_H_CTL_2); + I915_WRITE(TV_H_CTL_3, tv_priv->save_TV_H_CTL_3); + I915_WRITE(TV_V_CTL_1, tv_priv->save_TV_V_CTL_1); + I915_WRITE(TV_V_CTL_2, tv_priv->save_TV_V_CTL_2); + I915_WRITE(TV_V_CTL_3, tv_priv->save_TV_V_CTL_3); + I915_WRITE(TV_V_CTL_4, tv_priv->save_TV_V_CTL_4); + I915_WRITE(TV_V_CTL_5, tv_priv->save_TV_V_CTL_5); + I915_WRITE(TV_V_CTL_6, tv_priv->save_TV_V_CTL_6); + I915_WRITE(TV_V_CTL_7, tv_priv->save_TV_V_CTL_7); + I915_WRITE(TV_SC_CTL_1, tv_priv->save_TV_SC_CTL_1); + I915_WRITE(TV_SC_CTL_2, tv_priv->save_TV_SC_CTL_2); + I915_WRITE(TV_SC_CTL_3, tv_priv->save_TV_SC_CTL_3); + + I915_WRITE(TV_CSC_Y, tv_priv->save_TV_CSC_Y); + I915_WRITE(TV_CSC_Y2, tv_priv->save_TV_CSC_Y2); + I915_WRITE(TV_CSC_U, tv_priv->save_TV_CSC_U); + I915_WRITE(TV_CSC_U2, tv_priv->save_TV_CSC_U2); + I915_WRITE(TV_CSC_V, tv_priv->save_TV_CSC_V); + I915_WRITE(TV_CSC_V2, tv_priv->save_TV_CSC_V2); + I915_WRITE(TV_CLR_KNOBS, tv_priv->save_TV_CLR_KNOBS); + I915_WRITE(TV_CLR_LEVEL, tv_priv->save_TV_CLR_LEVEL); + + { + int pipeconf_reg = (intel_crtc->pipe == 0) ? + PIPEACONF : PIPEBCONF; + int dspcntr_reg = (intel_crtc->plane == 0) ? + DSPACNTR : DSPBCNTR; + int pipeconf = I915_READ(pipeconf_reg); + int dspcntr = I915_READ(dspcntr_reg); + int dspbase_reg = (intel_crtc->plane == 0) ? + DSPAADDR : DSPBADDR; + /* Pipe must be off here */ + I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + + if (!IS_I9XX(dev)) { + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank(dev); + } + + I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); + /* Wait for vblank for the disable to take effect. */ + intel_wait_for_vblank(dev); + + /* Filter ctl must be set before TV_WIN_SIZE */ + I915_WRITE(TV_FILTER_CTL_1, tv_priv->save_TV_FILTER_CTL_1); + I915_WRITE(TV_FILTER_CTL_2, tv_priv->save_TV_FILTER_CTL_2); + I915_WRITE(TV_FILTER_CTL_3, tv_priv->save_TV_FILTER_CTL_3); + I915_WRITE(TV_WIN_POS, tv_priv->save_TV_WIN_POS); + I915_WRITE(TV_WIN_SIZE, tv_priv->save_TV_WIN_SIZE); + I915_WRITE(pipeconf_reg, pipeconf); + I915_WRITE(dspcntr_reg, dspcntr); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + } + + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_LUMA_0 + (i <<2), tv_priv->save_TV_H_LUMA[i]); + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_CHROMA_0 + (i <<2), tv_priv->save_TV_H_CHROMA[i]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_LUMA_0 + (i <<2), tv_priv->save_TV_V_LUMA[i]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_CHROMA_0 + (i <<2), tv_priv->save_TV_V_CHROMA[i]); + + I915_WRITE(TV_DAC, tv_priv->save_TV_DAC); + I915_WRITE(TV_CTL, tv_priv->save_TV_CTL); +} + +static const struct tv_mode * +intel_tv_mode_lookup (char *tv_format) +{ + int i; + + for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) { + const struct tv_mode *tv_mode = &tv_modes[i]; + + if (!strcmp(tv_format, tv_mode->name)) + return tv_mode; + } + return NULL; +} + +static const struct tv_mode * +intel_tv_mode_find (struct intel_output *intel_output) +{ + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + + return intel_tv_mode_lookup(tv_priv->tv_format); +} + +static enum drm_mode_status +intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) +{ + struct intel_output *intel_output = to_intel_output(connector); + const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output); + + /* Ensure TV refresh is close to desired refresh */ + if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 1) + return MODE_OK; + return MODE_CLOCK_RANGE; +} + + +static bool +intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_mode_config *drm_config = &dev->mode_config; + struct intel_output *intel_output = enc_to_intel_output(encoder); + const struct tv_mode *tv_mode = intel_tv_mode_find (intel_output); + struct drm_encoder *other_encoder; + + if (!tv_mode) + return false; + + /* FIXME: lock encoder list */ + list_for_each_entry(other_encoder, &drm_config->encoder_list, head) { + if (other_encoder != encoder && + other_encoder->crtc == encoder->crtc) + return false; + } + + adjusted_mode->clock = tv_mode->clock; + return true; +} + +static void +intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = encoder->crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output); + u32 tv_ctl; + u32 hctl1, hctl2, hctl3; + u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7; + u32 scctl1, scctl2, scctl3; + int i, j; + const struct video_levels *video_levels; + const struct color_conversion *color_conversion; + bool burst_ena; + + if (!tv_mode) + return; /* can't happen (mode_prepare prevents this) */ + + tv_ctl = 0; + + switch (tv_priv->type) { + default: + case DRM_MODE_CONNECTOR_Unknown: + case DRM_MODE_CONNECTOR_Composite: + tv_ctl |= TV_ENC_OUTPUT_COMPOSITE; + video_levels = tv_mode->composite_levels; + color_conversion = tv_mode->composite_color; + burst_ena = tv_mode->burst_ena; + break; + case DRM_MODE_CONNECTOR_Component: + tv_ctl |= TV_ENC_OUTPUT_COMPONENT; + video_levels = &component_levels; + if (tv_mode->burst_ena) + color_conversion = &sdtv_csc_yprpb; + else + color_conversion = &hdtv_csc_yprpb; + burst_ena = false; + break; + case DRM_MODE_CONNECTOR_SVIDEO: + tv_ctl |= TV_ENC_OUTPUT_SVIDEO; + video_levels = tv_mode->svideo_levels; + color_conversion = tv_mode->svideo_color; + burst_ena = tv_mode->burst_ena; + break; + } + hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | + (tv_mode->htotal << TV_HTOTAL_SHIFT); + + hctl2 = (tv_mode->hburst_start << 16) | + (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT); + + if (burst_ena) + hctl2 |= TV_BURST_ENA; + + hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) | + (tv_mode->hblank_end << TV_HBLANK_END_SHIFT); + + vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) | + (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) | + (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT); + + vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) | + (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) | + (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT); + + vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) | + (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) | + (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT); + + if (tv_mode->veq_ena) + vctl3 |= TV_EQUAL_ENA; + + vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) | + (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT); + + vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) | + (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT); + + vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) | + (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT); + + vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) | + (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT); + + if (intel_crtc->pipe == 1) + tv_ctl |= TV_ENC_PIPEB_SELECT; + tv_ctl |= tv_mode->oversample; + + if (tv_mode->progressive) + tv_ctl |= TV_PROGRESSIVE; + if (tv_mode->trilevel_sync) + tv_ctl |= TV_TRILEVEL_SYNC; + if (tv_mode->pal_burst) + tv_ctl |= TV_PAL_BURST; + scctl1 = 0; + /* dda1 implies valid video levels */ + if (tv_mode->dda1_inc) { + scctl1 |= TV_SC_DDA1_EN; + scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; + } + + if (tv_mode->dda2_inc) + scctl1 |= TV_SC_DDA2_EN; + + if (tv_mode->dda3_inc) + scctl1 |= TV_SC_DDA3_EN; + + scctl1 |= tv_mode->sc_reset; + scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; + + scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | + tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT; + + scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT | + tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; + + /* Enable two fixes for the chips that need them. */ + if (dev->pci_device < 0x2772) + tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; + + I915_WRITE(TV_H_CTL_1, hctl1); + I915_WRITE(TV_H_CTL_2, hctl2); + I915_WRITE(TV_H_CTL_3, hctl3); + I915_WRITE(TV_V_CTL_1, vctl1); + I915_WRITE(TV_V_CTL_2, vctl2); + I915_WRITE(TV_V_CTL_3, vctl3); + I915_WRITE(TV_V_CTL_4, vctl4); + I915_WRITE(TV_V_CTL_5, vctl5); + I915_WRITE(TV_V_CTL_6, vctl6); + I915_WRITE(TV_V_CTL_7, vctl7); + I915_WRITE(TV_SC_CTL_1, scctl1); + I915_WRITE(TV_SC_CTL_2, scctl2); + I915_WRITE(TV_SC_CTL_3, scctl3); + + if (color_conversion) { + I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) | + color_conversion->gy); + I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) | + color_conversion->ay); + I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) | + color_conversion->gu); + I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) | + color_conversion->au); + I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) | + color_conversion->gv); + I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) | + color_conversion->av); + } + + I915_WRITE(TV_CLR_KNOBS, 0x00606000); + if (video_levels) + I915_WRITE(TV_CLR_LEVEL, + ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | + (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); + { + int pipeconf_reg = (intel_crtc->pipe == 0) ? + PIPEACONF : PIPEBCONF; + int dspcntr_reg = (intel_crtc->plane == 0) ? + DSPACNTR : DSPBCNTR; + int pipeconf = I915_READ(pipeconf_reg); + int dspcntr = I915_READ(dspcntr_reg); + int dspbase_reg = (intel_crtc->plane == 0) ? + DSPAADDR : DSPBADDR; + int xpos = 0x0, ypos = 0x0; + unsigned int xsize, ysize; + /* Pipe must be off here */ + I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + + /* Wait for vblank for the disable to take effect */ + if (!IS_I9XX(dev)) + intel_wait_for_vblank(dev); + + I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); + /* Wait for vblank for the disable to take effect. */ + intel_wait_for_vblank(dev); + + /* Filter ctl must be set before TV_WIN_SIZE */ + I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); + xsize = tv_mode->hblank_start - tv_mode->hblank_end; + if (tv_mode->progressive) + ysize = tv_mode->nbr_end + 1; + else + ysize = 2*tv_mode->nbr_end + 1; + + xpos += tv_priv->margin[TV_MARGIN_LEFT]; + ypos += tv_priv->margin[TV_MARGIN_TOP]; + xsize -= (tv_priv->margin[TV_MARGIN_LEFT] + + tv_priv->margin[TV_MARGIN_RIGHT]); + ysize -= (tv_priv->margin[TV_MARGIN_TOP] + + tv_priv->margin[TV_MARGIN_BOTTOM]); + I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos); + I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize); + + I915_WRITE(pipeconf_reg, pipeconf); + I915_WRITE(dspcntr_reg, dspcntr); + /* Flush the plane changes */ + I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); + } + + j = 0; + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_DAC, 0); + I915_WRITE(TV_CTL, tv_ctl); +} + +static const struct drm_display_mode reported_modes[] = { + { + .name = "NTSC 480i", + .clock = 107520, + .hdisplay = 1280, + .hsync_start = 1368, + .hsync_end = 1496, + .htotal = 1712, + + .vdisplay = 1024, + .vsync_start = 1027, + .vsync_end = 1034, + .vtotal = 1104, + .type = DRM_MODE_TYPE_DRIVER, + }, +}; + +/** + * Detects TV presence by checking for load. + * + * Requires that the current pipe's DPLL is active. + + * \return true if TV is connected. + * \return false if TV is disconnected. + */ +static int +intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) +{ + struct drm_encoder *encoder = &intel_output->enc; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long irqflags; + u32 tv_ctl, save_tv_ctl; + u32 tv_dac, save_tv_dac; + int type = DRM_MODE_CONNECTOR_Unknown; + + tv_dac = I915_READ(TV_DAC); + + /* Disable TV interrupts around load detect or we'll recurse */ + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + i915_disable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | + PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); + spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + + /* + * Detect TV by polling) + */ + if (intel_output->load_detect_temp) { + /* TV not currently running, prod it with destructive detect */ + save_tv_dac = tv_dac; + tv_ctl = I915_READ(TV_CTL); + save_tv_ctl = tv_ctl; + tv_ctl &= ~TV_ENC_ENABLE; + tv_ctl &= ~TV_TEST_MODE_MASK; + tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; + tv_dac &= ~TVDAC_SENSE_MASK; + tv_dac |= (TVDAC_STATE_CHG_EN | + TVDAC_A_SENSE_CTL | + TVDAC_B_SENSE_CTL | + TVDAC_C_SENSE_CTL | + DAC_CTL_OVERRIDE | + DAC_A_0_7_V | + DAC_B_0_7_V | + DAC_C_0_7_V); + I915_WRITE(TV_CTL, tv_ctl); + I915_WRITE(TV_DAC, tv_dac); + intel_wait_for_vblank(dev); + tv_dac = I915_READ(TV_DAC); + I915_WRITE(TV_DAC, save_tv_dac); + I915_WRITE(TV_CTL, save_tv_ctl); + } + /* + * A B C + * 0 1 1 Composite + * 1 0 X svideo + * 0 0 0 Component + */ + if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { + DRM_DEBUG("Detected Composite TV connection\n"); + type = DRM_MODE_CONNECTOR_Composite; + } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { + DRM_DEBUG("Detected S-Video TV connection\n"); + type = DRM_MODE_CONNECTOR_SVIDEO; + } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { + DRM_DEBUG("Detected Component TV connection\n"); + type = DRM_MODE_CONNECTOR_Component; + } else { + DRM_DEBUG("No TV connection detected\n"); + type = -1; + } + + /* Restore interrupt config */ + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | + PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); + spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + + return type; +} + +/** + * Detect the TV connection. + * + * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure + * we have a pipe programmed in order to probe the TV. + */ +static enum drm_connector_status +intel_tv_detect(struct drm_connector *connector) +{ + struct drm_crtc *crtc; + struct drm_display_mode mode; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + struct drm_encoder *encoder = &intel_output->enc; + int dpms_mode; + int type = tv_priv->type; + + mode = reported_modes[0]; + drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); + + if (encoder->crtc) { + type = intel_tv_detect_type(encoder->crtc, intel_output); + } else { + crtc = intel_get_load_detect_pipe(intel_output, &mode, &dpms_mode); + if (crtc) { + type = intel_tv_detect_type(crtc, intel_output); + intel_release_load_detect_pipe(intel_output, dpms_mode); + } else + type = -1; + } + + if (type < 0) + return connector_status_disconnected; + + return connector_status_connected; +} + +static struct input_res { + char *name; + int w, h; +} input_res_table[] = +{ + {"640x480", 640, 480}, + {"800x600", 800, 600}, + {"1024x768", 1024, 768}, + {"1280x1024", 1280, 1024}, + {"848x480", 848, 480}, + {"1280x720", 1280, 720}, + {"1920x1080", 1920, 1080}, +}; + +/** + * Stub get_modes function. + * + * This should probably return a set of fixed modes, unless we can figure out + * how to probe modes off of TV connections. + */ + +static int +intel_tv_get_modes(struct drm_connector *connector) +{ + struct drm_display_mode *mode_ptr; + struct intel_output *intel_output = to_intel_output(connector); + const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output); + int j; + + for (j = 0; j < sizeof(input_res_table) / sizeof(input_res_table[0]); + j++) { + struct input_res *input = &input_res_table[j]; + unsigned int hactive_s = input->w; + unsigned int vactive_s = input->h; + + if (tv_mode->max_srcw && input->w > tv_mode->max_srcw) + continue; + + if (input->w > 1024 && (!tv_mode->progressive + && !tv_mode->component_only)) + continue; + + mode_ptr = drm_calloc(1, sizeof(struct drm_display_mode), + DRM_MEM_DRIVER); + strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN); + + mode_ptr->hdisplay = hactive_s; + mode_ptr->hsync_start = hactive_s + 1; + mode_ptr->hsync_end = hactive_s + 64; + if (mode_ptr->hsync_end <= mode_ptr->hsync_start) + mode_ptr->hsync_end = mode_ptr->hsync_start + 1; + mode_ptr->htotal = hactive_s + 96; + + mode_ptr->vdisplay = vactive_s; + mode_ptr->vsync_start = vactive_s + 1; + mode_ptr->vsync_end = vactive_s + 32; + if (mode_ptr->vsync_end <= mode_ptr->vsync_start) + mode_ptr->vsync_end = mode_ptr->vsync_start + 1; + mode_ptr->vtotal = vactive_s + 33; + + mode_ptr->clock = (int) (tv_mode->refresh * + mode_ptr->vtotal * + mode_ptr->htotal / 1000) / 1000; + + mode_ptr->type = DRM_MODE_TYPE_DRIVER; + drm_mode_probed_add(connector, mode_ptr); + } + + return 0; +} + +static void +intel_tv_destroy (struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + drm_free(intel_output, sizeof(struct intel_output) + sizeof(struct intel_tv_priv), + DRM_MEM_DRIVER); +} + + +static int +intel_tv_set_property(struct drm_connector *connector, struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_tv_priv *tv_priv = intel_output->dev_priv; + int ret = 0; + + ret = drm_connector_property_set_value(connector, property, val); + if (ret < 0) + goto out; + + if (property == dev->mode_config.tv_left_margin_property) + tv_priv->margin[TV_MARGIN_LEFT] = val; + else if (property == dev->mode_config.tv_right_margin_property) + tv_priv->margin[TV_MARGIN_RIGHT] = val; + else if (property == dev->mode_config.tv_top_margin_property) + tv_priv->margin[TV_MARGIN_TOP] = val; + else if (property == dev->mode_config.tv_bottom_margin_property) + tv_priv->margin[TV_MARGIN_BOTTOM] = val; + else if (property == dev->mode_config.tv_mode_property) { + if (val >= NUM_TV_MODES) { + ret = -EINVAL; + goto out; + } + tv_priv->tv_format = tv_modes[val].name; + intel_tv_mode_set(&intel_output->enc, NULL, NULL); + } else { + ret = -EINVAL; + goto out; + } + + intel_tv_mode_set(&intel_output->enc, NULL, NULL); +out: + return ret; +} + +static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = { + .dpms = intel_tv_dpms, + .mode_fixup = intel_tv_mode_fixup, + .prepare = intel_encoder_prepare, + .mode_set = intel_tv_mode_set, + .commit = intel_encoder_commit, +}; + +static const struct drm_connector_funcs intel_tv_connector_funcs = { + .save = intel_tv_save, + .restore = intel_tv_restore, + .detect = intel_tv_detect, + .destroy = intel_tv_destroy, + .set_property = intel_tv_set_property, + .fill_modes = drm_helper_probe_single_connector_modes, +}; + +static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { + .mode_valid = intel_tv_mode_valid, + .get_modes = intel_tv_get_modes, + .best_encoder = intel_best_encoder, +}; + +static void intel_tv_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_tv_enc_funcs = { + .destroy = intel_tv_enc_destroy, +}; + + +void +intel_tv_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_connector *connector; + struct intel_output *intel_output; + struct intel_tv_priv *tv_priv; + u32 tv_dac_on, tv_dac_off, save_tv_dac; + char **tv_format_names; + int i, initial_mode = 0; + + if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) + return; + + /* Even if we have an encoder we may not have a connector */ + if (!dev_priv->int_tv_support) + return; + + /* + * Sanity check the TV output by checking to see if the + * DAC register holds a value + */ + save_tv_dac = I915_READ(TV_DAC); + + I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN); + tv_dac_on = I915_READ(TV_DAC); + + I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); + tv_dac_off = I915_READ(TV_DAC); + + I915_WRITE(TV_DAC, save_tv_dac); + + /* + * If the register does not hold the state change enable + * bit, (either as a 0 or a 1), assume it doesn't really + * exist + */ + if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 || + (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) + return; + + intel_output = drm_calloc(1, sizeof(struct intel_output) + + sizeof(struct intel_tv_priv), DRM_MEM_DRIVER); + if (!intel_output) { + return; + } + connector = &intel_output->base; + + drm_connector_init(dev, connector, &intel_tv_connector_funcs, + DRM_MODE_CONNECTOR_SVIDEO); + + drm_encoder_init(dev, &intel_output->enc, &intel_tv_enc_funcs, + DRM_MODE_ENCODER_TVDAC); + + drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); + tv_priv = (struct intel_tv_priv *)(intel_output + 1); + intel_output->type = INTEL_OUTPUT_TVOUT; + intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1)); + intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); + intel_output->dev_priv = tv_priv; + tv_priv->type = DRM_MODE_CONNECTOR_Unknown; + + /* BIOS margin values */ + tv_priv->margin[TV_MARGIN_LEFT] = 54; + tv_priv->margin[TV_MARGIN_TOP] = 36; + tv_priv->margin[TV_MARGIN_RIGHT] = 46; + tv_priv->margin[TV_MARGIN_BOTTOM] = 37; + + tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL); + + drm_encoder_helper_add(&intel_output->enc, &intel_tv_helper_funcs); + drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + /* Create TV properties then attach current values */ + tv_format_names = drm_alloc(sizeof(char *) * NUM_TV_MODES, + DRM_MEM_DRIVER); + if (!tv_format_names) + goto out; + for (i = 0; i < NUM_TV_MODES; i++) + tv_format_names[i] = tv_modes[i].name; + drm_mode_create_tv_properties(dev, NUM_TV_MODES, tv_format_names); + + drm_connector_attach_property(connector, dev->mode_config.tv_mode_property, + initial_mode); + drm_connector_attach_property(connector, + dev->mode_config.tv_left_margin_property, + tv_priv->margin[TV_MARGIN_LEFT]); + drm_connector_attach_property(connector, + dev->mode_config.tv_top_margin_property, + tv_priv->margin[TV_MARGIN_TOP]); + drm_connector_attach_property(connector, + dev->mode_config.tv_right_margin_property, + tv_priv->margin[TV_MARGIN_RIGHT]); + drm_connector_attach_property(connector, + dev->mode_config.tv_bottom_margin_property, + tv_priv->margin[TV_MARGIN_BOTTOM]); +out: + drm_sysfs_connector_add(connector); +} diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 4b27d9abb7bc..cace3964feeb 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -860,12 +860,12 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must * be careful about how this function is called. */ -static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) +static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) { - drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; - buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; + buf_priv->age = ++master_priv->sarea_priv->last_dispatch; buf->pending = 1; buf->used = 0; } @@ -1027,6 +1027,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, drm_radeon_kcmd_buffer_t *cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf = NULL; int emit_dispatch_age = 0; @@ -1134,7 +1135,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, } emit_dispatch_age = 1; - r300_discard_buffer(dev, buf); + r300_discard_buffer(dev, file_priv->master, buf); break; case R300_CMD_WAIT: @@ -1189,7 +1190,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, /* Emit the vertex buffer age */ BEGIN_RING(2); - RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch); + RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch); ADVANCE_RING(); } diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index dcebb4bee7aa..63212d7bbc28 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -31,6 +31,7 @@ #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" #include "radeon_drm.h" #include "radeon_drv.h" #include "r300_reg.h" @@ -667,15 +668,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, RADEON_WRITE(RADEON_BUS_CNTL, tmp); } /* PCIE cards appears to not need this */ - dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; - RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); + dev_priv->scratch[0] = 0; + RADEON_WRITE(RADEON_LAST_FRAME_REG, 0); - dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; - RADEON_WRITE(RADEON_LAST_DISPATCH_REG, - dev_priv->sarea_priv->last_dispatch); + dev_priv->scratch[1] = 0; + RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0); - dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; - RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); + dev_priv->scratch[2] = 0; + RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); radeon_do_wait_for_idle(dev_priv); @@ -871,9 +871,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) } } -static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) +static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, + struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; DRM_DEBUG("\n"); @@ -998,8 +1000,8 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) dev_priv->buffers_offset = init->buffers_offset; dev_priv->gart_textures_offset = init->gart_textures_offset; - dev_priv->sarea = drm_getsarea(dev); - if (!dev_priv->sarea) { + master_priv->sarea = drm_getsarea(dev); + if (!master_priv->sarea) { DRM_ERROR("could not find sarea!\n"); radeon_do_cleanup_cp(dev); return -EINVAL; @@ -1035,10 +1037,6 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) } } - dev_priv->sarea_priv = - (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle + - init->sarea_priv_offset); - #if __OS_HAS_AGP if (dev_priv->flags & RADEON_IS_AGP) { drm_core_ioremap(dev_priv->cp_ring, dev); @@ -1329,7 +1327,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri case RADEON_INIT_CP: case RADEON_INIT_R200_CP: case RADEON_INIT_R300_CP: - return radeon_do_init_cp(dev, init); + return radeon_do_init_cp(dev, init, file_priv); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp(dev); } @@ -1768,6 +1766,51 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) return ret; } +int radeon_master_create(struct drm_device *dev, struct drm_master *master) +{ + struct drm_radeon_master_private *master_priv; + unsigned long sareapage; + int ret; + + master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); + if (!master_priv) + return -ENOMEM; + + /* prebuild the SAREA */ + sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE); + ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER, + &master_priv->sarea); + if (ret) { + DRM_ERROR("SAREA setup failed\n"); + return ret; + } + master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); + master_priv->sarea_priv->pfCurrentPage = 0; + + master->driver_priv = master_priv; + return 0; +} + +void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) +{ + struct drm_radeon_master_private *master_priv = master->driver_priv; + + if (!master_priv) + return; + + if (master_priv->sarea_priv && + master_priv->sarea_priv->pfCurrentPage != 0) + radeon_cp_dispatch_flip(dev, master); + + master_priv->sarea_priv = NULL; + if (master_priv->sarea) + drm_rmmap_locked(dev, master_priv->sarea); + + drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); + + master->driver_priv = NULL; +} + /* Create mappings for registers and framebuffer so userland doesn't necessarily * have to find them. */ diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 71af746a4e47..fef207881f45 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -96,6 +96,8 @@ static struct drm_driver driver = { .enable_vblank = radeon_enable_vblank, .disable_vblank = radeon_disable_vblank, .dri_library_name = dri_library_name, + .master_create = radeon_master_create, + .master_destroy = radeon_master_destroy, .irq_preinstall = radeon_driver_irq_preinstall, .irq_postinstall = radeon_driver_irq_postinstall, .irq_uninstall = radeon_driver_irq_uninstall, diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 3bbb871b25d5..490bc7ceef60 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -226,9 +226,13 @@ struct radeon_virt_surface { #define RADEON_FLUSH_EMITED (1 < 0) #define RADEON_PURGE_EMITED (1 < 1) +struct drm_radeon_master_private { + drm_local_map_t *sarea; + drm_radeon_sarea_t *sarea_priv; +}; + typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; - drm_radeon_sarea_t *sarea_priv; u32 fb_location; u32 fb_size; @@ -409,6 +413,9 @@ extern int radeon_driver_open(struct drm_device *dev, extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +extern int radeon_master_create(struct drm_device *dev, struct drm_master *master); +extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master); +extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master); /* r300_cmdbuf.c */ extern void r300_init_reg_flags(struct drm_device *dev); @@ -1335,8 +1342,9 @@ do { \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ -do { \ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \ +do { \ + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \ + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ int __ret = radeon_do_cp_idle( dev_priv ); \ if ( __ret ) return __ret; \ diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 5d7153fcc7b0..ef940a079dcb 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -742,13 +742,14 @@ static struct { */ static void radeon_clear_box(drm_radeon_private_t * dev_priv, + struct drm_radeon_master_private *master_priv, int x, int y, int w, int h, int r, int g, int b) { u32 color; RING_LOCALS; - x += dev_priv->sarea_priv->boxes[0].x1; - y += dev_priv->sarea_priv->boxes[0].y1; + x += master_priv->sarea_priv->boxes[0].x1; + y += master_priv->sarea_priv->boxes[0].y1; switch (dev_priv->color_fmt) { case RADEON_COLOR_FORMAT_RGB565: @@ -776,7 +777,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); - if (dev_priv->sarea_priv->pfCurrentPage == 1) { + if (master_priv->sarea_priv->pfCurrentPage == 1) { OUT_RING(dev_priv->front_pitch_offset); } else { OUT_RING(dev_priv->back_pitch_offset); @@ -790,7 +791,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, ADVANCE_RING(); } -static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) +static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv) { /* Collapse various things into a wait flag -- trying to * guess if userspase slept -- better just to have them tell us. @@ -807,12 +808,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) /* Purple box for page flipping */ if (dev_priv->stats.boxes & RADEON_BOX_FLIP) - radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255); + radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255); /* Red box if we have to wait for idle at any point */ if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) - radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0); + radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0); /* Blue box: lost context? */ @@ -820,12 +821,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) /* Yellow box for texture swaps */ if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) - radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0); + radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0); /* Green box if hardware never idles (as far as we can tell) */ if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) - radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); + radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0); /* Draw bars indicating number of buffers allocated * (not a great measure, easily confused) @@ -834,7 +835,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) if (dev_priv->stats.requested_bufs > 100) dev_priv->stats.requested_bufs = 100; - radeon_clear_box(dev_priv, 4, 16, + radeon_clear_box(dev_priv, master_priv, 4, 16, dev_priv->stats.requested_bufs, 4, 196, 128, 128); } @@ -848,11 +849,13 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) */ static void radeon_cp_dispatch_clear(struct drm_device * dev, + struct drm_master *master, drm_radeon_clear_t * clear, drm_radeon_clear_rect_t * depth_boxes) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; int nbox = sarea_priv->nbox; struct drm_clip_rect *pbox = sarea_priv->boxes; @@ -864,7 +867,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, dev_priv->stats.clears++; - if (dev_priv->sarea_priv->pfCurrentPage == 1) { + if (sarea_priv->pfCurrentPage == 1) { unsigned int tmp = flags; flags &= ~(RADEON_FRONT | RADEON_BACK); @@ -890,7 +893,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { int x = pbox[i].x1; @@ -967,7 +970,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. * we haven't touched any "normal" state - still need this? */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; if ((dev_priv->flags & RADEON_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) { @@ -1214,7 +1217,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { @@ -1285,7 +1288,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { @@ -1328,20 +1331,21 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, * wait on this value before performing the clear ioctl. We * need this because the card's so damned fast... */ - dev_priv->sarea_priv->last_clear++; + sarea_priv->last_clear++; BEGIN_RING(4); - RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear); + RADEON_CLEAR_AGE(sarea_priv->last_clear); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); } -static void radeon_cp_dispatch_swap(struct drm_device * dev) +static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; int nbox = sarea_priv->nbox; struct drm_clip_rect *pbox = sarea_priv->boxes; int i; @@ -1351,7 +1355,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) - radeon_cp_performance_boxes(dev_priv); + radeon_cp_performance_boxes(dev_priv, master_priv); /* Wait for the 3D stream to idle before dispatching the bitblt. * This will prevent data corruption between the two streams. @@ -1385,7 +1389,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) /* Make this work even if front & back are flipped: */ OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); - if (dev_priv->sarea_priv->pfCurrentPage == 0) { + if (sarea_priv->pfCurrentPage == 0) { OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->front_pitch_offset); } else { @@ -1405,31 +1409,32 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ - dev_priv->sarea_priv->last_frame++; + sarea_priv->last_frame++; BEGIN_RING(4); - RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); + RADEON_FRAME_AGE(sarea_priv->last_frame); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); } -static void radeon_cp_dispatch_flip(struct drm_device * dev) +void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master) { drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle; - int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) + struct drm_radeon_master_private *master_priv = master->driver_priv; + struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle; + int offset = (master_priv->sarea_priv->pfCurrentPage == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG("pfCurrentPage=%d\n", - dev_priv->sarea_priv->pfCurrentPage); + master_priv->sarea_priv->pfCurrentPage); /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) { dev_priv->stats.boxes |= RADEON_BOX_FLIP; - radeon_cp_performance_boxes(dev_priv); + radeon_cp_performance_boxes(dev_priv, master_priv); } /* Update the frame offsets for both CRTCs @@ -1441,7 +1446,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev) ((sarea->frame.y * dev_priv->front_pitch + sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) + offset); - OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base + offset); ADVANCE_RING(); @@ -1450,13 +1455,13 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev) * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ - dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = - 1 - dev_priv->sarea_priv->pfCurrentPage; + master_priv->sarea_priv->last_frame++; + master_priv->sarea_priv->pfCurrentPage = + 1 - master_priv->sarea_priv->pfCurrentPage; BEGIN_RING(2); - RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); + RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame); ADVANCE_RING(); } @@ -1494,11 +1499,13 @@ typedef struct { } drm_radeon_tcl_prim_t; static void radeon_cp_dispatch_vertex(struct drm_device * dev, + struct drm_file *file_priv, struct drm_buf * buf, drm_radeon_tcl_prim_t * prim) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; int nbox = sarea_priv->nbox; @@ -1539,13 +1546,14 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev, } while (i < nbox); } -static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf) +static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) { drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; - buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; + buf_priv->age = ++master_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING(2); @@ -1590,12 +1598,14 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev, } } -static void radeon_cp_dispatch_indices(struct drm_device * dev, +static void radeon_cp_dispatch_indices(struct drm_device *dev, + struct drm_master *master, struct drm_buf * elt_buf, drm_radeon_tcl_prim_t * prim) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + prim->offset; u32 *data; int dwords; @@ -1870,7 +1880,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, ADVANCE_RING(); COMMIT_RING(); - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); /* Update the input parameters for next time */ image->y += height; @@ -2110,7 +2120,8 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; drm_radeon_clear_t *clear = data; drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG("\n"); @@ -2126,7 +2137,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * sarea_priv->nbox * sizeof(depth_boxes[0]))) return -EFAULT; - radeon_cp_dispatch_clear(dev, clear, depth_boxes); + radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes); COMMIT_RING(); return 0; @@ -2134,9 +2145,10 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * /* Not sure why this isn't set all the time: */ -static int radeon_do_init_pageflip(struct drm_device * dev) +static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master) { drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; RING_LOCALS; DRM_DEBUG("\n"); @@ -2153,8 +2165,8 @@ static int radeon_do_init_pageflip(struct drm_device * dev) dev_priv->page_flipping = 1; - if (dev_priv->sarea_priv->pfCurrentPage != 1) - dev_priv->sarea_priv->pfCurrentPage = 0; + if (master_priv->sarea_priv->pfCurrentPage != 1) + master_priv->sarea_priv->pfCurrentPage = 0; return 0; } @@ -2172,9 +2184,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f RING_SPACE_TEST_WITH_RETURN(dev_priv); if (!dev_priv->page_flipping) - radeon_do_init_pageflip(dev); + radeon_do_init_pageflip(dev, file_priv->master); - radeon_cp_dispatch_flip(dev); + radeon_cp_dispatch_flip(dev, file_priv->master); COMMIT_RING(); return 0; @@ -2183,7 +2195,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -2193,8 +2207,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - radeon_cp_dispatch_swap(dev); - dev_priv->sarea_priv->ctx_owner = 0; + radeon_cp_dispatch_swap(dev, file_priv->master); + sarea_priv->ctx_owner = 0; COMMIT_RING(); return 0; @@ -2203,7 +2217,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_radeon_vertex_t *vertex = data; @@ -2211,6 +2226,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); + sarea_priv = master_priv->sarea_priv; + DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); @@ -2263,13 +2280,13 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file prim.finish = vertex->count; /* unused */ prim.prim = vertex->prim; prim.numverts = vertex->count; - prim.vc_format = dev_priv->sarea_priv->vc_format; + prim.vc_format = sarea_priv->vc_format; - radeon_cp_dispatch_vertex(dev, buf, &prim); + radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim); } if (vertex->discard) { - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); } COMMIT_RING(); @@ -2279,7 +2296,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_radeon_indices_t *elts = data; @@ -2288,6 +2306,8 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); + sarea_priv = master_priv->sarea_priv; + DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", DRM_CURRENTPID, elts->idx, elts->start, elts->end, elts->discard); @@ -2353,11 +2373,11 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file prim.prim = elts->prim; prim.offset = 0; /* offset from start of dma buffers */ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - prim.vc_format = dev_priv->sarea_priv->vc_format; + prim.vc_format = sarea_priv->vc_format; - radeon_cp_dispatch_indices(dev, buf, &prim); + radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim); if (elts->discard) { - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); } COMMIT_RING(); @@ -2468,7 +2488,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil */ radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); if (indirect->discard) { - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); } COMMIT_RING(); @@ -2478,7 +2498,8 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; + drm_radeon_sarea_t *sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_radeon_vertex2_t *vertex = data; @@ -2487,6 +2508,8 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); + sarea_priv = master_priv->sarea_priv; + DRM_DEBUG("pid=%d index=%d discard=%d\n", DRM_CURRENTPID, vertex->idx, vertex->discard); @@ -2547,12 +2570,12 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file tclprim.offset = prim.numverts * 64; tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - radeon_cp_dispatch_indices(dev, buf, &tclprim); + radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim); } else { tclprim.numverts = prim.numverts; tclprim.offset = 0; /* not used */ - radeon_cp_dispatch_vertex(dev, buf, &tclprim); + radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim); } if (sarea_priv->nbox == 1) @@ -2560,7 +2583,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file } if (vertex->discard) { - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); } COMMIT_RING(); @@ -2909,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file goto err; } - radeon_cp_discard_buffer(dev, buf); + radeon_cp_discard_buffer(dev, file_priv->master, buf); break; case RADEON_CMD_PACKET3: @@ -3020,7 +3043,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil */ case RADEON_PARAM_SAREA_HANDLE: /* The lock is the first dword in the sarea. */ - value = (long)dev->lock.hw_lock; + /* no users of this parameter */ break; #endif case RADEON_PARAM_GART_TEX_HANDLE: @@ -3064,6 +3087,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; drm_radeon_setparam_t *sp = data; struct drm_radeon_driver_file_fields *radeon_priv; @@ -3078,12 +3102,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil DRM_DEBUG("color tiling disabled\n"); dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; - dev_priv->sarea_priv->tiling_enabled = 0; + if (master_priv->sarea_priv) + master_priv->sarea_priv->tiling_enabled = 0; } else if (sp->value == 1) { DRM_DEBUG("color tiling enabled\n"); dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; - dev_priv->sarea_priv->tiling_enabled = 1; + if (master_priv->sarea_priv) + master_priv->sarea_priv->tiling_enabled = 1; } break; case RADEON_SETPARAM_PCIGART_LOCATION: @@ -3129,14 +3155,6 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) void radeon_driver_lastclose(struct drm_device *dev) { - if (dev->dev_private) { - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (dev_priv->sarea_priv && - dev_priv->sarea_priv->pfCurrentPage != 0) - radeon_cp_dispatch_flip(dev); - } - radeon_do_release(dev); } diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 906f9b9d715d..587f5b2380d4 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1016,7 +1016,7 @@ static int i2c_pxa_probe(struct platform_device *dev) snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u", i2c->adap.nr); - i2c->clk = clk_get(&dev->dev, "I2CCLK"); + i2c->clk = clk_get(&dev->dev, NULL); if (IS_ERR(i2c->clk)) { ret = PTR_ERR(i2c->clk); goto eclk; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index b7434d24904e..c39079f9c73f 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -40,8 +40,8 @@ #include <asm/io.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c/regs-iic.h> -#include <asm/plat-s3c/iic.h> +#include <plat/regs-iic.h> +#include <plat/iic.h> /* i2c controller state */ diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index e6857e01d1ba..c9f21e3d4ead 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -62,6 +62,9 @@ config IDE_TIMINGS config IDE_ATAPI bool +config IDE_LEGACY + bool + config BLK_DEV_IDE_SATA bool "Support for SATA (deprecated; conflicts with libata SATA driver)" default n @@ -724,7 +727,7 @@ config BLK_DEV_IDE_TX4939 config IDE_ARM tristate "ARM IDE support" - depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) + depends on ARM && (ARCH_RPC || ARCH_SHARK) default y config BLK_DEV_IDE_ICSIDE @@ -856,6 +859,7 @@ config BLK_DEV_4DRIVES config BLK_DEV_ALI14XX tristate "ALI M14xx support" select IDE_TIMINGS + select IDE_LEGACY help This driver is enabled at runtime using the "ali14xx.probe" kernel boot parameter. It enables support for the secondary IDE interface @@ -866,6 +870,7 @@ config BLK_DEV_ALI14XX config BLK_DEV_DTC2278 tristate "DTC-2278 support" + select IDE_LEGACY help This driver is enabled at runtime using the "dtc2278.probe" kernel boot parameter. It enables support for the secondary IDE interface @@ -876,6 +881,7 @@ config BLK_DEV_DTC2278 config BLK_DEV_HT6560B tristate "Holtek HT6560B support" select IDE_TIMINGS + select IDE_LEGACY help This driver is enabled at runtime using the "ht6560b.probe" kernel boot parameter. It enables support for the secondary IDE interface @@ -886,6 +892,7 @@ config BLK_DEV_HT6560B config BLK_DEV_QD65XX tristate "QDI QD65xx support" select IDE_TIMINGS + select IDE_LEGACY help This driver is enabled at runtime using the "qd65xx.probe" kernel boot parameter. It permits faster I/O speeds to be set. See the @@ -894,6 +901,7 @@ config BLK_DEV_QD65XX config BLK_DEV_UMC8672 tristate "UMC-8672 support" + select IDE_LEGACY help This driver is enabled at runtime using the "umc8672.probe" kernel boot parameter. It enables support for the secondary IDE interface diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 7818d402b188..177e3f8523ed 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,7 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-park.o ide-pio-blacklist.o + ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o @@ -15,6 +15,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o +ide-core-$(CONFIG_IDE_LEGACY) += ide-legacy.o obj-$(CONFIG_IDE) += ide-core.o diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 935385c77e06..3623bf013bcf 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -424,10 +424,10 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, - .chipset = ide_cmd646, .port_ops = &cmd64x_port_ops, .dma_ops = &cmd648_dma_ops, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH, + .host_flags = IDE_HFLAG_SERIALIZE | + IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 5297f07d2933..d37baf8ecc5f 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -292,7 +292,6 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = { .name = DRV_NAME, .init_iops = init_iops_cy82c693, .port_ops = &cy82c693_port_ops, - .chipset = ide_cy82c693, .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2, diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index 691506886561..59bd0be9dcb3 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c @@ -117,6 +117,10 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, hw->chipset = ide_generic; } +static const struct ide_port_info gayle_port_info = { + .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, +}; + /* * Probe for a Gayle IDE interface (and optionally for an IDE doubler) */ @@ -178,7 +182,7 @@ found: hws[i] = &hw[i]; } - rc = ide_host_add(NULL, hws, NULL); + rc = ide_host_add(&gayle_port_info, hws, NULL); if (rc) release_mem_region(res_start, res_n); diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index f5afd46ed51c..b18e10d99d2e 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -135,7 +135,6 @@ /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE #undef HPT_DELAY_INTERRUPT -#define HPT_SERIALIZE_IO 0 static const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", @@ -1288,7 +1287,6 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { struct hpt_info *info = hpt3xx_get_info(hwif->dev); - int serialize = HPT_SERIALIZE_IO; u8 chip_type = info->chip_type; /* Cache the channel's MISC. control registers' offset */ @@ -1305,13 +1303,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) * Clock is shared between the channels, * so we'll have to serialize them... :-( */ - serialize = 1; + hwif->host->host_flags |= IDE_HFLAG_SERIALIZE; hwif->rw_disk = &hpt3xxn_rw_disk; } - - /* Serialize access to this device if needed */ - if (serialize && hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; } static int __devinit init_dma_hpt366(ide_hwif_t *hwif, diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 244a8a052ce8..fd4a36433050 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -615,10 +615,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) in_params[0].buffer.length = sizeof(struct GTM_buffer); in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; in_params[1].type = ACPI_TYPE_BUFFER; - in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2); + in_params[1].buffer.length = ATA_ID_WORDS * 2; in_params[1].buffer.pointer = (u8 *)&master->idbuff; in_params[2].type = ACPI_TYPE_BUFFER; - in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2); + in_params[2].buffer.length = ATA_ID_WORDS * 2; in_params[2].buffer.pointer = (u8 *)&slave->idbuff; /* Output buffer: _STM has no output */ diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 42ab6d8715f2..5daa4dd1b018 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -262,7 +262,6 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate) struct request *failed = (struct request *) rq->buffer; struct cdrom_info *info = drive->driver_data; void *sense = &info->sense_data; - unsigned long flags; if (failed) { if (failed->sense) { @@ -278,11 +277,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate) failed->hard_nr_sectors)) BUG(); } else { - spin_lock_irqsave(&ide_lock, flags); - if (__blk_end_request(failed, -EIO, - failed->data_len)) + if (blk_end_request(failed, -EIO, + failed->data_len)) BUG(); - spin_unlock_irqrestore(&ide_lock, flags); } } else cdrom_analyze_sense_data(drive, NULL, sense); @@ -317,7 +314,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st) static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { ide_hwif_t *hwif = drive->hwif; - struct request *rq = hwif->hwgroup->rq; + ide_hwgroup_t *hwgroup = hwif->hwgroup; + struct request *rq = hwgroup->rq; int stat, err, sense_key; /* check for errors */ @@ -426,16 +424,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) if (time_after(jiffies, info->write_timeout)) do_end_request = 1; else { + struct request_queue *q = drive->queue; unsigned long flags; /* * take a breather relying on the unplug * timer to kick us again */ - spin_lock_irqsave(&ide_lock, flags); - blk_plug_device(drive->queue); - spin_unlock_irqrestore(&ide_lock, - flags); + spin_lock_irqsave(q->queue_lock, flags); + blk_plug_device(q); + spin_unlock_irqrestore(q->queue_lock, flags); + return 1; } } @@ -504,12 +503,14 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) end_request: if (stat & ATA_ERR) { + struct request_queue *q = drive->queue; unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(q->queue_lock, flags); blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(q->queue_lock, flags); + + hwgroup->rq = NULL; cdrom_queue_request_sense(drive, rq->sense, rq); } else @@ -773,52 +774,6 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); } -#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ -#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ -#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */ - -static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - int stat; - static int retry = 10; - - ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); - - if (cdrom_decode_status(drive, 0, &stat)) - return ide_stopped; - - drive->atapi_flags |= IDE_AFLAG_SEEKING; - - if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) { - if (--retry == 0) - drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; - } - return ide_stopped; -} - -static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq) -{ - sector_t frame = rq->sector; - - ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); - - sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); - - memset(rq->cmd, 0, BLK_MAX_CDB); - rq->cmd[0] = GPCMD_SEEK; - put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]); - - rq->timeout = ATAPI_WAIT_PC; -} - -static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) -{ - struct request *rq = drive->hwif->hwgroup->rq; - - return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr); -} - /* * Fix up a possibly partially-processed request so that we can start it over * entirely, or even put it back on the request queue. @@ -950,7 +905,8 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct request *rq = HWGROUP(drive)->rq; + ide_hwgroup_t *hwgroup = hwif->hwgroup; + struct request *rq = hwgroup->rq; xfer_func_t *xferfunc; ide_expiry_t *expiry = NULL; int dma_error = 0, dma, stat, thislen, uptodate = 0; @@ -1148,17 +1104,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) end_request: if (blk_pc_request(rq)) { - unsigned long flags; unsigned int dlen = rq->data_len; if (dma) rq->data_len = 0; - spin_lock_irqsave(&ide_lock, flags); - if (__blk_end_request(rq, 0, dlen)) + if (blk_end_request(rq, 0, dlen)) BUG(); - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&ide_lock, flags); + + hwgroup->rq = NULL; } else { if (!uptodate) rq->cmd_flags |= REQ_FAILED; @@ -1260,7 +1214,6 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { - struct cdrom_info *info = drive->driver_data; ide_handler_t *fn; int xferlen; @@ -1270,44 +1223,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, (unsigned long long)block); if (blk_fs_request(rq)) { - if (drive->atapi_flags & IDE_AFLAG_SEEKING) { - ide_hwif_t *hwif = drive->hwif; - unsigned long elapsed = jiffies - info->start_seek; - int stat = hwif->tp_ops->read_status(hwif); - - if ((stat & ATA_DSC) != ATA_DSC) { - if (elapsed < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, - IDECD_SEEK_TIMER); - return ide_stopped; - } - printk(KERN_ERR PFX "%s: DSC timeout\n", - drive->name); - } - drive->atapi_flags &= ~IDE_AFLAG_SEEKING; - } - if (rq_data_dir(rq) == READ && - IDE_LARGE_SEEK(info->last_block, block, - IDECD_SEEK_THRESHOLD) && - (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) { - xferlen = 0; - fn = cdrom_start_seek_continuation; + xferlen = 32768; + fn = cdrom_start_rw_cont; - drive->dma = 0; - info->start_seek = jiffies; - - ide_cd_prepare_seek_request(drive, rq); - } else { - xferlen = 32768; - fn = cdrom_start_rw_cont; - - if (cdrom_start_rw(drive, rq) == ide_stopped) - return ide_stopped; + if (cdrom_start_rw(drive, rq) == ide_stopped) + return ide_stopped; - if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped) - return ide_stopped; - } - info->last_block = block; + if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped) + return ide_stopped; } else if (blk_sense_request(rq) || blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { xferlen = rq->data_len; @@ -1908,13 +1831,6 @@ static ide_proc_entry_t idecd_proc[] = { { NULL, 0, NULL, NULL } }; -ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP); - -static const struct ide_proc_devset idecd_settings[] = { - IDE_PROC_DEVSET(dsc_overlap, 0, 1), - { 0 }, -}; - static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive) { return idecd_proc; @@ -1922,7 +1838,7 @@ static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive) static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive) { - return idecd_settings; + return NULL; } #endif @@ -2022,11 +1938,6 @@ static int ide_cdrom_setup(ide_drive_t *drive) /* set correct block size */ blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE); - if (drive->next != drive) - drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; - else - drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; - if (ide_cdrom_register(drive, nslots)) { printk(KERN_ERR PFX "%s: %s failed to register device with the" " cdrom driver.\n", drive->name, __func__); @@ -2063,7 +1974,6 @@ static void ide_cd_release(struct kref *kref) kfree(info->toc); if (devinfo->handle == drive) unregister_cdrom(devinfo); - drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); g->private_data = NULL; diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 5882b9a9ea8b..d5ce3362dbd1 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -88,8 +88,6 @@ struct cdrom_info { struct request_sense sense_data; struct request request_sense_request; - unsigned long last_block; - unsigned long start_seek; u8 max_speed; /* Max speed of the drive. */ u8 current_speed; /* Current speed of the drive. */ diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c index cac431f0df17..f6d2d44d8a9a 100644 --- a/drivers/ide/ide-dma-sff.c +++ b/drivers/ide/ide-dma-sff.c @@ -98,10 +98,10 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; __le32 *table = (__le32 *)hwif->dmatable_cpu; - unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0; unsigned int count = 0; int i; struct scatterlist *sg; + u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290); hwif->sg_nents = ide_build_sglist(drive, rq); if (hwif->sg_nents == 0) @@ -176,15 +176,10 @@ int ide_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->hwgroup->rq; - unsigned int reading; + unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; u8 dma_stat; - if (rq_data_dir(rq)) - reading = 0; - else - reading = 1 << 3; - /* fall back to pio! */ if (!ide_build_dmatable(drive, rq)) { ide_map_sg(drive, rq); @@ -209,10 +204,11 @@ int ide_dma_setup(ide_drive_t *drive) /* clear INTR & ERROR flags */ if (mmio) - writeb(dma_stat | 6, + writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR, (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)); else - outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); + outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR, + hwif->dma_base + ATA_DMA_STATUS); drive->waiting_for_dma = 1; return 0; @@ -246,14 +242,13 @@ static int dma_timer_expiry(ide_drive_t *drive) hwif->hwgroup->expiry = NULL; /* one free ride for now */ - /* 1 dmaing, 2 error, 4 intr */ - if (dma_stat & 2) /* ERROR */ + if (dma_stat & ATA_DMA_ERR) /* ERROR */ return -1; - if (dma_stat & 1) /* DMAing */ + if (dma_stat & ATA_DMA_ACTIVE) /* DMAing */ return WAIT_CMD; - if (dma_stat & 4) /* Got an Interrupt */ + if (dma_stat & ATA_DMA_INTR) /* Got an Interrupt */ return WAIT_CMD; return 0; /* Status is unknown -- reset the bus */ @@ -279,12 +274,11 @@ void ide_dma_start(ide_drive_t *drive) */ if (hwif->host_flags & IDE_HFLAG_MMIO) { dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); - /* start DMA */ - writeb(dma_cmd | 1, + writeb(dma_cmd | ATA_DMA_START, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); } else { dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD); + outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); } wmb(); @@ -296,19 +290,18 @@ int ide_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 dma_stat = 0, dma_cmd = 0; + u8 dma_stat = 0, dma_cmd = 0, mask; drive->waiting_for_dma = 0; + /* stop DMA */ if (mmio) { - /* get DMA command mode */ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); - /* stop DMA */ - writeb(dma_cmd & ~1, + writeb(dma_cmd & ~ATA_DMA_START, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); } else { dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); - outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); + outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); } /* get DMA status */ @@ -316,16 +309,21 @@ int ide_dma_end(ide_drive_t *drive) if (mmio) /* clear the INTR & ERROR bits */ - writeb(dma_stat | 6, + writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR, (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)); else - outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); + outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR, + hwif->dma_base + ATA_DMA_STATUS); /* purge DMA mappings */ ide_destroy_dmatable(drive); - /* verify good DMA status */ wmb(); - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; + + /* verify good DMA status */ + mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR; + if ((dma_stat & mask) != ATA_DMA_INTR) + return 0x10 | dma_stat; + return 0; } EXPORT_SYMBOL_GPL(ide_dma_end); @@ -335,11 +333,7 @@ int ide_dma_test_irq(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); - /* return 1 if INTR asserted */ - if ((dma_stat & 4) == 4) - return 1; - - return 0; + return (dma_stat & ATA_DMA_INTR) ? 1 : 0; } EXPORT_SYMBOL_GPL(ide_dma_test_irq); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index cc35d6dbd410..ecacc008fdaf 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -84,11 +84,11 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, ide_dma_on(drive); } - if (!__blk_end_request(rq, error, nr_bytes)) { - if (dequeue) - HWGROUP(drive)->rq = NULL; + if (!blk_end_request(rq, error, nr_bytes)) ret = 0; - } + + if (ret == 0 && dequeue) + drive->hwif->hwgroup->rq = NULL; return ret; } @@ -107,16 +107,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) { unsigned int nr_bytes = nr_sectors << 9; - struct request *rq; - unsigned long flags; - int ret = 1; - - /* - * room for locking improvements here, the calls below don't - * need the queue lock held at all - */ - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; + struct request *rq = drive->hwif->hwgroup->rq; if (!nr_bytes) { if (blk_pc_request(rq)) @@ -125,105 +116,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) nr_bytes = rq->hard_cur_sectors << 9; } - ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1); - - spin_unlock_irqrestore(&ide_lock, flags); - return ret; + return __ide_end_request(drive, rq, uptodate, nr_bytes, 1); } EXPORT_SYMBOL(ide_end_request); -static void ide_complete_power_step(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - -#ifdef DEBUG_PM - printk(KERN_INFO "%s: complete_power_step(step: %d)\n", - drive->name, pm->pm_step); -#endif - if (drive->media != ide_disk) - return; - - switch (pm->pm_step) { - case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ - if (pm->pm_state == PM_EVENT_FREEZE) - pm->pm_step = IDE_PM_COMPLETED; - else - pm->pm_step = IDE_PM_STANDBY; - break; - case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ - pm->pm_step = IDE_PM_COMPLETED; - break; - case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ - pm->pm_step = IDE_PM_IDLE; - break; - case IDE_PM_IDLE: /* Resume step 2 (idle)*/ - pm->pm_step = IDE_PM_RESTORE_DMA; - break; - } -} - -static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (pm->pm_step) { - case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ - if (drive->media != ide_disk) - break; - /* Not supported? Switch to next step now. */ - if (ata_id_flush_enabled(drive->id) == 0 || - (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { - ide_complete_power_step(drive, rq); - return ide_stopped; - } - if (ata_id_flush_ext_enabled(drive->id)) - args->tf.command = ATA_CMD_FLUSH_EXT; - else - args->tf.command = ATA_CMD_FLUSH; - goto out_do_tf; - case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ - args->tf.command = ATA_CMD_STANDBYNOW1; - goto out_do_tf; - case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ - ide_set_max_pio(drive); - /* - * skip IDE_PM_IDLE for ATAPI devices - */ - if (drive->media != ide_disk) - pm->pm_step = IDE_PM_RESTORE_DMA; - else - ide_complete_power_step(drive, rq); - return ide_stopped; - case IDE_PM_IDLE: /* Resume step 2 (idle) */ - args->tf.command = ATA_CMD_IDLEIMMEDIATE; - goto out_do_tf; - case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ - /* - * Right now, all we do is call ide_set_dma(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - */ - if (drive->hwif->dma_ops == NULL) - break; - /* - * TODO: respect IDE_DFLAG_USING_DMA - */ - ide_set_dma(drive); - break; - } - - pm->pm_step = IDE_PM_COMPLETED; - return ide_stopped; - -out_do_tf: - args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - args->data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, args); -} - /** * ide_end_dequeued_request - complete an IDE I/O * @drive: IDE device for the I/O @@ -242,48 +138,12 @@ out_do_tf: int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors) { - unsigned long flags; - int ret; - - spin_lock_irqsave(&ide_lock, flags); BUG_ON(!blk_rq_started(rq)); - ret = __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0); - spin_unlock_irqrestore(&ide_lock, flags); - return ret; + return __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0); } EXPORT_SYMBOL_GPL(ide_end_dequeued_request); - -/** - * ide_complete_pm_request - end the current Power Management request - * @drive: target drive - * @rq: request - * - * This function cleans up the current PM request and stops the queue - * if necessary. - */ -static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) -{ - unsigned long flags; - -#ifdef DEBUG_PM - printk("%s: completing PM request, %s\n", drive->name, - blk_pm_suspend_request(rq) ? "suspend" : "resume"); -#endif - spin_lock_irqsave(&ide_lock, flags); - if (blk_pm_suspend_request(rq)) { - blk_stop_queue(drive->queue); - } else { - drive->dev_flags &= ~IDE_DFLAG_BLOCKED; - blk_start_queue(drive->queue); - } - HWGROUP(drive)->rq = NULL; - if (__blk_end_request(rq, 0, 0)) - BUG(); - spin_unlock_irqrestore(&ide_lock, flags); -} - /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -300,19 +160,12 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) { - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&ide_lock, flags); + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; + struct request *rq = hwgroup->rq; if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { ide_task_t *task = (ide_task_t *)rq->special; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT); - if (task) { struct ide_taskfile *tf = &task->tf; @@ -333,15 +186,14 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) return; } - spin_lock_irqsave(&ide_lock, flags); - HWGROUP(drive)->rq = NULL; + hwgroup->rq = NULL; + rq->errors = err; - if (unlikely(__blk_end_request(rq, (rq->errors ? -EIO : 0), - blk_rq_bytes(rq)))) + + if (unlikely(blk_end_request(rq, (rq->errors ? -EIO : 0), + blk_rq_bytes(rq)))) BUG(); - spin_unlock_irqrestore(&ide_lock, flags); } - EXPORT_SYMBOL(ide_end_drive_cmd); static void ide_kill_rq(ide_drive_t *drive, struct request *rq) @@ -720,40 +572,6 @@ static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) } } -static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - - if (blk_pm_suspend_request(rq) && - pm->pm_step == IDE_PM_START_SUSPEND) - /* Mark drive blocked when starting the suspend sequence. */ - drive->dev_flags |= IDE_DFLAG_BLOCKED; - else if (blk_pm_resume_request(rq) && - pm->pm_step == IDE_PM_START_RESUME) { - /* - * The first thing we do on wakeup is to wait for BSY bit to - * go away (with a looong timeout) as a drive on this hwif may - * just be POSTing itself. - * We do that before even selecting as the "other" device on - * the bus may be broken enough to walk on our toes at this - * point. - */ - ide_hwif_t *hwif = drive->hwif; - int rc; -#ifdef DEBUG_PM - printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); -#endif - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); - SELECT_DRIVE(drive); - hwif->tp_ops->set_irq(hwif, 1); - rc = ide_wait_not_busy(hwif, 100000); - if (rc) - printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); - } -} - /** * start_request - start of I/O and command issuing for IDE * @@ -927,7 +745,7 @@ repeat: /* * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&ide_lock, ..); + * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..); * * A hwgroup is a serialized group of IDE interfaces. Usually there is * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) @@ -939,7 +757,7 @@ repeat: * possibly along with many other devices. This is especially common in * PCI-based systems with off-board IDE controller cards. * - * The IDE driver uses the single global ide_lock spinlock to protect + * The IDE driver uses a per-hwgroup spinlock to protect * access to the request queues, and to protect the hwgroup->busy flag. * * The first thread into the driver for a particular hwgroup sets the @@ -955,7 +773,7 @@ repeat: * will start the next request from the queue. If no more work remains, * the driver will clear the hwgroup->busy flag and exit. * - * The ide_lock (spinlock) is used to protect all access to the + * The per-hwgroup spinlock is used to protect all access to the * hwgroup->busy flag, but is otherwise not needed for most processing in * the driver. This makes the driver much more friendlier to shared IRQs * than previous designs, while remaining 100% (?) SMP safe and capable. @@ -968,7 +786,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) ide_startstop_t startstop; int loops = 0; - /* caller must own ide_lock */ + /* caller must own hwgroup->lock */ BUG_ON(!irqs_disabled()); while (!hwgroup->busy) { @@ -1023,12 +841,12 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) } again: hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) { + if (hwif != hwgroup->hwif) { /* * set nIEN for previous hwif, drives in the * quirk_list may not like intr setups/cleanups */ - if (drive->quirk_list != 1) + if (drive->quirk_list == 0) hwif->tp_ops->set_irq(hwif, 0); } hwgroup->hwif = hwif; @@ -1036,11 +854,6 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); drive->service_start = jiffies; - if (blk_queue_plugged(drive->queue)) { - printk(KERN_ERR "ide: huh? queue was plugged!\n"); - break; - } - /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request @@ -1090,11 +903,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) */ if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); - spin_unlock(&ide_lock); + spin_unlock(&hwgroup->lock); local_irq_enable_in_hardirq(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_stopped) @@ -1192,7 +1005,7 @@ void ide_timer_expiry (unsigned long data) unsigned long flags; unsigned long wait = -1; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); if (((handler = hwgroup->handler) == NULL) || (hwgroup->req_gen != hwgroup->req_gen_timer)) { @@ -1225,7 +1038,7 @@ void ide_timer_expiry (unsigned long data) hwgroup->timer.expires = jiffies + wait; hwgroup->req_gen_timer = hwgroup->req_gen; add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); return; } } @@ -1235,7 +1048,7 @@ void ide_timer_expiry (unsigned long data) * the handler() function, which means we need to * globally mask the specific IRQ: */ - spin_unlock(&ide_lock); + spin_unlock(&hwgroup->lock); hwif = HWIF(drive); /* disable_irq_nosync ?? */ disable_irq(hwif->irq); @@ -1259,14 +1072,14 @@ void ide_timer_expiry (unsigned long data) hwif->tp_ops->read_status(hwif)); } drive->service_time = jiffies - drive->service_start; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); enable_irq(hwif->irq); if (startstop == ide_stopped) hwgroup->busy = 0; } } ide_do_request(hwgroup, IDE_NO_IRQ); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); } /** @@ -1359,18 +1172,16 @@ irqreturn_t ide_intr (int irq, void *dev_id) { unsigned long flags; ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; + ide_hwif_t *hwif = hwgroup->hwif; ide_drive_t *drive; ide_handler_t *handler; ide_startstop_t startstop; + irqreturn_t irq_ret = IRQ_NONE; - spin_lock_irqsave(&ide_lock, flags); - hwif = hwgroup->hwif; + spin_lock_irqsave(&hwgroup->lock, flags); - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_NONE; - } + if (!ide_ack_intr(hwif)) + goto out; if ((handler = hwgroup->handler) == NULL || hwgroup->polling) { /* @@ -1406,9 +1217,9 @@ irqreturn_t ide_intr (int irq, void *dev_id) (void)hwif->tp_ops->read_status(hwif); #endif /* CONFIG_BLK_DEV_IDEPCI */ } - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_NONE; + goto out; } + drive = hwgroup->drive; if (!drive) { /* @@ -1417,10 +1228,10 @@ irqreturn_t ide_intr (int irq, void *dev_id) * * [Note - this can occur if the drive is hot unplugged] */ - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_HANDLED; + goto out_handled; } - if (!drive_is_ready(drive)) { + + if (!drive_is_ready(drive)) /* * This happens regularly when we share a PCI IRQ with * another device. Unfortunately, it can also happen @@ -1428,9 +1239,8 @@ irqreturn_t ide_intr (int irq, void *dev_id) * their status register is up to date. Hopefully we have * enough advance overhead that the latter isn't a problem. */ - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_NONE; - } + goto out; + if (!hwgroup->busy) { hwgroup->busy = 1; /* paranoia */ printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); @@ -1438,7 +1248,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) hwgroup->handler = NULL; hwgroup->req_gen++; del_timer(&hwgroup->timer); - spin_unlock(&ide_lock); + spin_unlock(&hwgroup->lock); if (hwif->port_ops && hwif->port_ops->clear_irq) hwif->port_ops->clear_irq(drive); @@ -1449,7 +1259,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) /* service this interrupt, may set handler for next interrupt */ startstop = handler(drive); - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); /* * Note that handler() may have set things up for another * interrupt to occur soon, but it cannot happen until @@ -1467,8 +1277,11 @@ irqreturn_t ide_intr (int irq, void *dev_id) "on exit\n", drive->name); } } - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_HANDLED; +out_handled: + irq_ret = IRQ_HANDLED; +out: + spin_unlock_irqrestore(&hwgroup->lock, flags); + return irq_ret; } /** @@ -1488,16 +1301,17 @@ irqreturn_t ide_intr (int irq, void *dev_id) void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) { + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; + struct request_queue *q = drive->queue; unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - spin_lock_irqsave(&ide_lock, flags); hwgroup->rq = NULL; - __elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); - blk_start_queueing(drive->queue); - spin_unlock_irqrestore(&ide_lock, flags); -} + spin_lock_irqsave(q->queue_lock, flags); + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); + blk_start_queueing(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} EXPORT_SYMBOL(ide_do_drive_cmd); void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index fcde16bb53a7..28232c64c346 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -19,7 +19,6 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, const struct ide_ioctl_devset *s) { const struct ide_devset *ds; - unsigned long flags; int err = -EOPNOTSUPP; for (; (ds = s->setting); s++) { @@ -33,9 +32,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, read_val: mutex_lock(&ide_setting_mtx); - spin_lock_irqsave(&ide_lock, flags); err = ds->get(drive); - spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); return err >= 0 ? put_user(err, (long __user *)arg) : err; @@ -98,7 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return -EPERM; if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && - (drive->media == ide_disk || drive->media == ide_floppy || + (drive->media != ide_tape || (drive->dev_flags & IDE_DFLAG_SCSI))) return -EPERM; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index c41c3b9b6f02..ad8bd6539283 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -835,10 +835,12 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry) { + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + + spin_lock_irqsave(&hwgroup->lock, flags); __ide_set_handler(drive, handler, timeout, expiry); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); } EXPORT_SYMBOL(ide_set_handler); @@ -860,10 +862,11 @@ EXPORT_SYMBOL(ide_set_handler); void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry) { + ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; unsigned long flags; - ide_hwif_t *hwif = HWIF(drive); - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); __ide_set_handler(drive, handler, timeout, expiry); hwif->tp_ops->exec_command(hwif, cmd); /* @@ -873,19 +876,20 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, * FIXME: we could skip this delay with care on non shared devices */ ndelay(400); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); } EXPORT_SYMBOL(ide_execute_command); void ide_execute_pkt_cmd(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); ndelay(400); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); } EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); @@ -1076,22 +1080,16 @@ static void pre_reset(ide_drive_t *drive) */ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) { - unsigned int unit; - unsigned long flags, timeout; - ide_hwif_t *hwif; - ide_hwgroup_t *hwgroup; - struct ide_io_ports *io_ports; - const struct ide_tp_ops *tp_ops; + ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; + struct ide_io_ports *io_ports = &hwif->io_ports; + const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_port_ops *port_ops; + unsigned long flags, timeout; + unsigned int unit; DEFINE_WAIT(wait); - spin_lock_irqsave(&ide_lock, flags); - hwif = HWIF(drive); - hwgroup = HWGROUP(drive); - - io_ports = &hwif->io_ports; - - tp_ops = hwif->tp_ops; + spin_lock_irqsave(&hwgroup->lock, flags); /* We must not reset with running handlers */ BUG_ON(hwgroup->handler != NULL); @@ -1106,7 +1104,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); return ide_started; } @@ -1129,9 +1127,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) if (time_before_eq(timeout, now)) break; - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); timeout = schedule_timeout_uninterruptible(timeout - now); - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); } while (timeout); finish_wait(&ide_park_wq, &wait); @@ -1143,7 +1141,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) pre_reset(&hwif->drives[unit]); if (io_ports->ctl_addr == 0) { - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); ide_complete_drive_reset(drive, -ENXIO); return ide_stopped; } @@ -1179,7 +1177,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) if (port_ops && port_ops->resetproc) port_ops->resetproc(drive); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); return ide_started; } diff --git a/drivers/ide/ide-legacy.c b/drivers/ide/ide-legacy.c new file mode 100644 index 000000000000..8c5dcbf22547 --- /dev/null +++ b/drivers/ide/ide-legacy.c @@ -0,0 +1,58 @@ +#include <linux/kernel.h> +#include <linux/ide.h> + +static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, + u8 port_no, const struct ide_port_info *d, + unsigned long config) +{ + unsigned long base, ctl; + int irq; + + if (port_no == 0) { + base = 0x1f0; + ctl = 0x3f6; + irq = 14; + } else { + base = 0x170; + ctl = 0x376; + irq = 15; + } + + if (!request_region(base, 8, d->name)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + d->name, base, base + 7); + return; + } + + if (!request_region(ctl, 1, d->name)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + d->name, ctl); + release_region(base, 8); + return; + } + + ide_std_init_ports(hw, base, ctl); + hw->irq = irq; + hw->chipset = d->chipset; + hw->config = config; + + hws[port_no] = hw; +} + +int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) +{ + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; + + memset(&hw, 0, sizeof(hw)); + + if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) + ide_legacy_init_one(hws, &hw[0], 0, d, config); + ide_legacy_init_one(hws, &hw[1], 1, d, config); + + if (hws[0] == NULL && hws[1] == NULL && + (d->host_flags & IDE_HFLAG_SINGLE)) + return -ENOENT; + + return ide_host_add(d, hws, NULL); +} +EXPORT_SYMBOL_GPL(ide_legacy_device_add); diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 9fc4cfb2a272..9f6e33d8a8b2 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -43,7 +43,6 @@ const char *ide_xfer_verbose(u8 mode) return s; } - EXPORT_SYMBOL(ide_xfer_verbose); /** @@ -87,7 +86,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) * This is used by most chipset support modules when "auto-tuning". */ -u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) +u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) { u16 *id = drive->id; int pio_mode = -1, overridden = 0; @@ -131,7 +130,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) return pio_mode; } - EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); /* req_pio == "255" for auto-tune */ @@ -162,7 +160,6 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio) (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); } - EXPORT_SYMBOL_GPL(ide_set_pio); /** @@ -173,7 +170,7 @@ EXPORT_SYMBOL_GPL(ide_set_pio); * Enable or disable bounce buffering for the device. Drives move * between PIO and DMA and that changes the rules we need. */ - + void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ @@ -243,14 +240,13 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) return ide_config_drive_speed(drive, mode); } } - EXPORT_SYMBOL_GPL(ide_set_dma_mode); /** * ide_set_xfer_rate - set transfer rate * @drive: drive to set * @rate: speed to attempt to set - * + * * General helper for setting the speed of an IDE device. This * function knows about user enforced limits from the configuration * which ->set_pio_mode/->set_dma_mode does not. @@ -277,21 +273,16 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) static void ide_dump_opcode(ide_drive_t *drive) { - struct request *rq; + struct request *rq = drive->hwif->hwgroup->rq; ide_task_t *task = NULL; - spin_lock(&ide_lock); - rq = NULL; - if (HWGROUP(drive)) - rq = HWGROUP(drive)->rq; - spin_unlock(&ide_lock); if (!rq) return; if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) task = rq->special; - printk("ide: failed opcode was: "); + printk(KERN_ERR "ide: failed opcode was: "); if (task == NULL) printk(KERN_CONT "unknown\n"); else @@ -329,44 +320,55 @@ static void ide_dump_sector(ide_drive_t *drive) drive->hwif->tp_ops->tf_read(drive, &task); if (lba48 || (tf->device & ATA_LBA)) - printk(", LBAsect=%llu", + printk(KERN_CONT ", LBAsect=%llu", (unsigned long long)ide_get_lba_addr(tf, lba48)); else - printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, - tf->device & 0xf, tf->lbal); + printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, + tf->device & 0xf, tf->lbal); } static void ide_dump_ata_error(ide_drive_t *drive, u8 err) { - printk("{ "); - if (err & ATA_ABORTED) printk("DriveStatusError "); + printk(KERN_ERR "{ "); + if (err & ATA_ABORTED) + printk(KERN_CONT "DriveStatusError "); if (err & ATA_ICRC) - printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector "); - if (err & ATA_UNC) printk("UncorrectableError "); - if (err & ATA_IDNF) printk("SectorIdNotFound "); - if (err & ATA_TRK0NF) printk("TrackZeroNotFound "); - if (err & ATA_AMNF) printk("AddrMarkNotFound "); - printk("}"); + printk(KERN_CONT "%s", + (err & ATA_ABORTED) ? "BadCRC " : "BadSector "); + if (err & ATA_UNC) + printk(KERN_CONT "UncorrectableError "); + if (err & ATA_IDNF) + printk(KERN_CONT "SectorIdNotFound "); + if (err & ATA_TRK0NF) + printk(KERN_CONT "TrackZeroNotFound "); + if (err & ATA_AMNF) + printk(KERN_CONT "AddrMarkNotFound "); + printk(KERN_CONT "}"); if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK || (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) { ide_dump_sector(drive); if (HWGROUP(drive) && HWGROUP(drive)->rq) - printk(", sector=%llu", + printk(KERN_CONT ", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector); } - printk("\n"); + printk(KERN_CONT "\n"); } static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) { - printk("{ "); - if (err & ATAPI_ILI) printk("IllegalLengthIndication "); - if (err & ATAPI_EOM) printk("EndOfMedia "); - if (err & ATA_ABORTED) printk("AbortedCommand "); - if (err & ATA_MCR) printk("MediaChangeRequested "); - if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ", - (err & ATAPI_LFS) >> 4); - printk("}\n"); + printk(KERN_ERR "{ "); + if (err & ATAPI_ILI) + printk(KERN_CONT "IllegalLengthIndication "); + if (err & ATAPI_EOM) + printk(KERN_CONT "EndOfMedia "); + if (err & ATA_ABORTED) + printk(KERN_CONT "AbortedCommand "); + if (err & ATA_MCR) + printk(KERN_CONT "MediaChangeRequested "); + if (err & ATAPI_LFS) + printk(KERN_CONT "LastFailedSense=0x%02x ", + (err & ATAPI_LFS) >> 4); + printk(KERN_CONT "}\n"); } /** @@ -382,34 +384,37 @@ static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) { - unsigned long flags; u8 err = 0; - local_irq_save(flags); - printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); + printk(KERN_ERR "%s: %s: status=0x%02x { ", drive->name, msg, stat); if (stat & ATA_BUSY) - printk("Busy "); + printk(KERN_CONT "Busy "); else { - if (stat & ATA_DRDY) printk("DriveReady "); - if (stat & ATA_DF) printk("DeviceFault "); - if (stat & ATA_DSC) printk("SeekComplete "); - if (stat & ATA_DRQ) printk("DataRequest "); - if (stat & ATA_CORR) printk("CorrectedError "); - if (stat & ATA_IDX) printk("Index "); - if (stat & ATA_ERR) printk("Error "); + if (stat & ATA_DRDY) + printk(KERN_CONT "DriveReady "); + if (stat & ATA_DF) + printk(KERN_CONT "DeviceFault "); + if (stat & ATA_DSC) + printk(KERN_CONT "SeekComplete "); + if (stat & ATA_DRQ) + printk(KERN_CONT "DataRequest "); + if (stat & ATA_CORR) + printk(KERN_CONT "CorrectedError "); + if (stat & ATA_IDX) + printk(KERN_CONT "Index "); + if (stat & ATA_ERR) + printk(KERN_CONT "Error "); } - printk("}\n"); + printk(KERN_CONT "}\n"); if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) { err = ide_read_error(drive); - printk("%s: %s: error=0x%02x ", drive->name, msg, err); + printk(KERN_ERR "%s: %s: error=0x%02x ", drive->name, msg, err); if (drive->media == ide_disk) ide_dump_ata_error(drive, err); else ide_dump_atapi_error(drive, err); } ide_dump_opcode(drive); - local_irq_restore(flags); return err; } - EXPORT_SYMBOL(ide_dump_status); diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 03b00e57e93f..63d01c55f865 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -7,17 +7,16 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq); static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) { + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; struct request_queue *q = drive->queue; struct request *rq; int rc; timeout += jiffies; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); if (drive->dev_flags & IDE_DFLAG_PARKED) { - ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; - int reset_timer; + int reset_timer = time_before(timeout, drive->sleep); - reset_timer = time_before(timeout, drive->sleep); drive->sleep = timeout; wake_up_all(&ide_park_wq); if (reset_timer && hwgroup->sleeping && @@ -26,10 +25,10 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) hwgroup->busy = 0; blk_start_queueing(q); } - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); return; } - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); rq = blk_get_request(q, READ, __GFP_WAIT); rq->cmd[0] = REQ_PARK_HEADS; @@ -62,20 +61,21 @@ ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, char *buf) { ide_drive_t *drive = to_ide_device(dev); + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; unsigned long now; unsigned int msecs; if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) return -EOPNOTSUPP; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); now = jiffies; if (drive->dev_flags & IDE_DFLAG_PARKED && time_after(drive->sleep, now)) msecs = jiffies_to_msecs(drive->sleep - now); else msecs = 0; - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); return snprintf(buf, 20, "%u\n", msecs); } diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c new file mode 100644 index 000000000000..8282c6086e6a --- /dev/null +++ b/drivers/ide/ide-pm.c @@ -0,0 +1,235 @@ +#include <linux/kernel.h> +#include <linux/ide.h> +#include <linux/hdreg.h> + +int generic_ide_suspend(struct device *dev, pm_message_t mesg) +{ + ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); + ide_hwif_t *hwif = HWIF(drive); + struct request *rq; + struct request_pm_state rqpm; + ide_task_t args; + int ret; + + /* call ACPI _GTM only once */ + if ((drive->dn & 1) == 0 || pair == NULL) + ide_acpi_get_timing(hwif); + + memset(&rqpm, 0, sizeof(rqpm)); + memset(&args, 0, sizeof(args)); + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_PM_SUSPEND; + rq->special = &args; + rq->data = &rqpm; + rqpm.pm_step = IDE_PM_START_SUSPEND; + if (mesg.event == PM_EVENT_PRETHAW) + mesg.event = PM_EVENT_FREEZE; + rqpm.pm_state = mesg.event; + + ret = blk_execute_rq(drive->queue, NULL, rq, 0); + blk_put_request(rq); + + /* call ACPI _PS3 only after both devices are suspended */ + if (ret == 0 && ((drive->dn & 1) || pair == NULL)) + ide_acpi_set_state(hwif, 0); + + return ret; +} + +int generic_ide_resume(struct device *dev) +{ + ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); + ide_hwif_t *hwif = HWIF(drive); + struct request *rq; + struct request_pm_state rqpm; + ide_task_t args; + int err; + + /* call ACPI _PS0 / _STM only once */ + if ((drive->dn & 1) == 0 || pair == NULL) { + ide_acpi_set_state(hwif, 1); + ide_acpi_push_timing(hwif); + } + + ide_acpi_exec_tfs(drive); + + memset(&rqpm, 0, sizeof(rqpm)); + memset(&args, 0, sizeof(args)); + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_PM_RESUME; + rq->cmd_flags |= REQ_PREEMPT; + rq->special = &args; + rq->data = &rqpm; + rqpm.pm_step = IDE_PM_START_RESUME; + rqpm.pm_state = PM_EVENT_ON; + + err = blk_execute_rq(drive->queue, NULL, rq, 1); + blk_put_request(rq); + + if (err == 0 && dev->driver) { + ide_driver_t *drv = to_ide_driver(dev->driver); + + if (drv->resume) + drv->resume(drive); + } + + return err; +} + +void ide_complete_power_step(ide_drive_t *drive, struct request *rq) +{ + struct request_pm_state *pm = rq->data; + +#ifdef DEBUG_PM + printk(KERN_INFO "%s: complete_power_step(step: %d)\n", + drive->name, pm->pm_step); +#endif + if (drive->media != ide_disk) + return; + + switch (pm->pm_step) { + case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ + if (pm->pm_state == PM_EVENT_FREEZE) + pm->pm_step = IDE_PM_COMPLETED; + else + pm->pm_step = IDE_PM_STANDBY; + break; + case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ + pm->pm_step = IDE_PM_COMPLETED; + break; + case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ + pm->pm_step = IDE_PM_IDLE; + break; + case IDE_PM_IDLE: /* Resume step 2 (idle)*/ + pm->pm_step = IDE_PM_RESTORE_DMA; + break; + } +} + +ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) +{ + struct request_pm_state *pm = rq->data; + ide_task_t *args = rq->special; + + memset(args, 0, sizeof(*args)); + + switch (pm->pm_step) { + case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ + if (drive->media != ide_disk) + break; + /* Not supported? Switch to next step now. */ + if (ata_id_flush_enabled(drive->id) == 0 || + (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { + ide_complete_power_step(drive, rq); + return ide_stopped; + } + if (ata_id_flush_ext_enabled(drive->id)) + args->tf.command = ATA_CMD_FLUSH_EXT; + else + args->tf.command = ATA_CMD_FLUSH; + goto out_do_tf; + case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ + args->tf.command = ATA_CMD_STANDBYNOW1; + goto out_do_tf; + case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ + ide_set_max_pio(drive); + /* + * skip IDE_PM_IDLE for ATAPI devices + */ + if (drive->media != ide_disk) + pm->pm_step = IDE_PM_RESTORE_DMA; + else + ide_complete_power_step(drive, rq); + return ide_stopped; + case IDE_PM_IDLE: /* Resume step 2 (idle) */ + args->tf.command = ATA_CMD_IDLEIMMEDIATE; + goto out_do_tf; + case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ + /* + * Right now, all we do is call ide_set_dma(drive), + * we could be smarter and check for current xfer_speed + * in struct drive etc... + */ + if (drive->hwif->dma_ops == NULL) + break; + /* + * TODO: respect IDE_DFLAG_USING_DMA + */ + ide_set_dma(drive); + break; + } + + pm->pm_step = IDE_PM_COMPLETED; + return ide_stopped; + +out_do_tf: + args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + args->data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, args); +} + +/** + * ide_complete_pm_request - end the current Power Management request + * @drive: target drive + * @rq: request + * + * This function cleans up the current PM request and stops the queue + * if necessary. + */ +void ide_complete_pm_request(ide_drive_t *drive, struct request *rq) +{ + struct request_queue *q = drive->queue; + unsigned long flags; + +#ifdef DEBUG_PM + printk("%s: completing PM request, %s\n", drive->name, + blk_pm_suspend_request(rq) ? "suspend" : "resume"); +#endif + spin_lock_irqsave(q->queue_lock, flags); + if (blk_pm_suspend_request(rq)) { + blk_stop_queue(q); + } else { + drive->dev_flags &= ~IDE_DFLAG_BLOCKED; + blk_start_queue(q); + } + spin_unlock_irqrestore(q->queue_lock, flags); + + drive->hwif->hwgroup->rq = NULL; + + if (blk_end_request(rq, 0, 0)) + BUG(); +} + +void ide_check_pm_state(ide_drive_t *drive, struct request *rq) +{ + struct request_pm_state *pm = rq->data; + + if (blk_pm_suspend_request(rq) && + pm->pm_step == IDE_PM_START_SUSPEND) + /* Mark drive blocked when starting the suspend sequence. */ + drive->dev_flags |= IDE_DFLAG_BLOCKED; + else if (blk_pm_resume_request(rq) && + pm->pm_step == IDE_PM_START_RESUME) { + /* + * The first thing we do on wakeup is to wait for BSY bit to + * go away (with a looong timeout) as a drive on this hwif may + * just be POSTing itself. + * We do that before even selecting as the "other" device on + * the bus may be broken enough to walk on our toes at this + * point. + */ + ide_hwif_t *hwif = drive->hwif; + int rc; +#ifdef DEBUG_PM + printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); +#endif + rc = ide_wait_not_busy(hwif, 35000); + if (rc) + printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); + SELECT_DRIVE(drive); + hwif->tp_ops->set_irq(hwif, 1); + rc = ide_wait_not_busy(hwif, 100000); + if (rc) + printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); + } +} diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c55bdbd22314..a64ec259f3d1 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -110,20 +110,22 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) * read and parse the results. This function is run with * interrupts disabled. */ - -static inline void do_identify (ide_drive_t *drive, u8 cmd) + +static void do_identify(ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; + unsigned long flags; int bswap = 1, is_cfa; + /* local CPU only; some systems need this */ + local_irq_save(flags); /* read 512 bytes of id info */ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); + local_irq_restore(flags); drive->dev_flags |= IDE_DFLAG_ID_READ; - - local_irq_enable(); #ifdef DEBUG printk(KERN_INFO "%s: dumping identify data\n", drive->name); ide_dump_identify((u8 *)id); @@ -306,17 +308,12 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) s = tp_ops->read_status(hwif); if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { - unsigned long flags; - - /* local CPU only; some systems need this */ - local_irq_save(flags); /* drive returned ID */ do_identify(drive, cmd); /* drive responded with ID */ rc = 0; /* clear drive IRQ */ (void)tp_ops->read_status(hwif); - local_irq_restore(flags); } else { /* drive refused ID */ rc = 2; @@ -554,8 +551,8 @@ static void enable_nest (ide_drive_t *drive) * 1 device was found * (note: IDE_DFLAG_PRESENT might still be not set) */ - -static inline u8 probe_for_drive (ide_drive_t *drive) + +static u8 probe_for_drive(ide_drive_t *drive) { char *m; @@ -642,7 +639,7 @@ static int ide_register_port(ide_hwif_t *hwif) int ret; /* register with global device tree */ - strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); + dev_set_name(&hwif->gendev, hwif->name); hwif->gendev.driver_data = hwif; if (hwif->gendev.parent == NULL) { if (hwif->dev) @@ -864,31 +861,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) } /* - * save_match() is used to simplify logic in init_irq() below. - * - * A loophole here is that we may not know about a particular - * hwif's irq until after that hwif is actually probed/initialized.. - * This could be a problem for the case where an hwif is on a - * dual interface that requires serialization (eg. cmd640) and another - * hwif using one of the same irqs is initialized beforehand. - * - * This routine detects and reports such situations, but does not fix them. - */ -static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) -{ - ide_hwif_t *m = *match; - - if (m && m->hwgroup && m->hwgroup != new->hwgroup) { - if (!new->hwgroup) - return; - printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n", - hwif->name, new->name, m->name); - } - if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ - *match = new; -} - -/* * init request queue */ static int ide_init_queue(ide_drive_t *drive) @@ -906,7 +878,8 @@ static int ide_init_queue(ide_drive_t *drive) * do not. */ - q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); + q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock, + hwif_to_node(hwif)); if (!q) return 1; @@ -947,7 +920,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) { ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); if (!hwgroup->drive) { /* first drive for hwgroup. */ drive->next = drive; @@ -957,7 +930,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) drive->next = hwgroup->drive->next; hwgroup->drive->next = drive; } - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); } /* @@ -1002,7 +975,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) ide_ports[hwif->index] = NULL; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); /* * Remove us from the hwgroup, and free * the hwgroup if we were the only member @@ -1030,7 +1003,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) } BUG_ON(hwgroup->hwif == hwif); } - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); } /* @@ -1051,27 +1024,13 @@ static int init_irq (ide_hwif_t *hwif) mutex_lock(&ide_cfg_mtx); hwif->hwgroup = NULL; - /* - * Group up with any other hwifs that share our irq(s). - */ for (index = 0; index < MAX_HWIFS; index++) { ide_hwif_t *h = ide_ports[index]; if (h && h->hwgroup) { /* scan only initialized ports */ - if (hwif->irq == h->irq) { - hwif->sharing_irq = h->sharing_irq = 1; - if (hwif->chipset != ide_pci || - h->chipset != ide_pci) { - save_match(hwif, h, &match); - } - } - if (hwif->serialized) { - if (hwif->mate && hwif->mate->irq == h->irq) - save_match(hwif, h, &match); - } - if (h->serialized) { - if (h->mate && hwif->irq == h->mate->irq) - save_match(hwif, h, &match); + if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) { + if (hwif->host == h->host) + match = h; } } } @@ -1092,17 +1051,19 @@ static int init_irq (ide_hwif_t *hwif) * linked list, the first entry is the hwif that owns * hwgroup->handler - do not change that. */ - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); hwif->next = hwgroup->hwif->next; hwgroup->hwif->next = hwif; BUG_ON(hwif->next == hwif); - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); } else { hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, hwif_to_node(hwif)); if (hwgroup == NULL) goto out_up; + spin_lock_init(&hwgroup->lock); + hwif->hwgroup = hwgroup; hwgroup->hwif = hwif->next = hwif; @@ -1122,8 +1083,7 @@ static int init_irq (ide_hwif_t *hwif) sa = IRQF_SHARED; #endif /* __mc68000__ */ - if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 || - hwif->chipset == ide_ali14xx) + if (hwif->chipset == ide_pci) sa = IRQF_SHARED; if (io_ports->ctl_addr) @@ -1150,8 +1110,7 @@ static int init_irq (ide_hwif_t *hwif) io_ports->data_addr, hwif->irq); #endif /* __mc68000__ */ if (match) - printk(KERN_CONT " (%sed with %s)", - hwif->sharing_irq ? "shar" : "serializ", match->name); + printk(KERN_CONT " (serialized with %s)", match->name); printk(KERN_CONT "\n"); mutex_unlock(&ide_cfg_mtx); @@ -1263,20 +1222,21 @@ static void ide_remove_drive_from_hwgroup(ide_drive_t *drive) static void drive_release_dev (struct device *dev) { ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; ide_proc_unregister_device(drive); - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); ide_remove_drive_from_hwgroup(drive); kfree(drive->id); drive->id = NULL; drive->dev_flags &= ~IDE_DFLAG_PRESENT; /* Messed up locking ... */ - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); blk_cleanup_queue(drive->queue); - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); drive->queue = NULL; - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); complete(&drive->gendev_rel_comp); } @@ -1352,7 +1312,7 @@ static void hwif_register_devices(ide_hwif_t *hwif) if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; - snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); + dev_set_name(dev, "%u.%u", hwif->index, i); dev->parent = &hwif->gendev; dev->bus = &ide_bus_type; dev->driver_data = drive; @@ -1436,13 +1396,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, } if ((d->host_flags & IDE_HFLAG_SERIALIZE) || - ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) { - if (hwif->mate) - hwif->mate->serialized = hwif->serialized = 1; - } + ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) + hwif->host->host_flags |= IDE_HFLAG_SERIALIZE; - if (d->host_flags & IDE_HFLAG_RQSIZE_256) - hwif->rqsize = 256; + if (d->max_sectors) + hwif->rqsize = d->max_sectors; /* call chipset specific routine for each enabled port */ if (d->init_hwif) @@ -1794,59 +1752,3 @@ void ide_port_scan(ide_hwif_t *hwif) ide_proc_port_register_devices(hwif); } EXPORT_SYMBOL_GPL(ide_port_scan); - -static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, - u8 port_no, const struct ide_port_info *d, - unsigned long config) -{ - unsigned long base, ctl; - int irq; - - if (port_no == 0) { - base = 0x1f0; - ctl = 0x3f6; - irq = 14; - } else { - base = 0x170; - ctl = 0x376; - irq = 15; - } - - if (!request_region(base, 8, d->name)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - d->name, base, base + 7); - return; - } - - if (!request_region(ctl, 1, d->name)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - d->name, ctl); - release_region(base, 8); - return; - } - - ide_std_init_ports(hw, base, ctl); - hw->irq = irq; - hw->chipset = d->chipset; - hw->config = config; - - hws[port_no] = hw; -} - -int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) -{ - hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; - - memset(&hw, 0, sizeof(hw)); - - if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) - ide_legacy_init_one(hws, &hw[0], 0, d, config); - ide_legacy_init_one(hws, &hw[1], 1, d, config); - - if (hws[0] == NULL && hws[1] == NULL && - (d->host_flags & IDE_HFLAG_SINGLE)) - return -ENOENT; - - return ide_host_add(d, hws, NULL); -} -EXPORT_SYMBOL_GPL(ide_legacy_device_add); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index f3cddd1b2f8f..a14e2938e4f3 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -46,10 +46,6 @@ static int proc_ide_read_imodel case ide_qd65xx: name = "qd65xx"; break; case ide_umc8672: name = "umc8672"; break; case ide_ht6560b: name = "ht6560b"; break; - case ide_rz1000: name = "rz1000"; break; - case ide_trm290: name = "trm290"; break; - case ide_cmd646: name = "cmd646"; break; - case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; case ide_pmac: name = "mac-io"; break; case ide_au1xxx: name = "au1xxx"; break; @@ -155,13 +151,8 @@ static int ide_read_setting(ide_drive_t *drive, const struct ide_devset *ds = setting->setting; int val = -EINVAL; - if (ds->get) { - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); + if (ds->get) val = ds->get(drive); - spin_unlock_irqrestore(&ide_lock, flags); - } return val; } @@ -583,31 +574,19 @@ EXPORT_SYMBOL(ide_proc_register_driver); * Clean up the driver specific /proc files and IDE settings * for a given drive. * - * Takes ide_setting_mtx and ide_lock. - * Caller must hold none of the locks. + * Takes ide_setting_mtx. */ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { - unsigned long flags; - ide_remove_proc_entries(drive->proc, driver->proc_entries(drive)); mutex_lock(&ide_setting_mtx); - spin_lock_irqsave(&ide_lock, flags); /* - * ide_setting_mtx protects the settings list - * ide_lock protects the use of settings - * - * so we need to hold both, ide_settings_sem because we want to - * modify the settings list, and ide_lock because we cannot take - * a setting out that is being used. - * - * OTOH both ide_{read,write}_setting are only ever used under - * ide_setting_mtx. + * ide_setting_mtx protects both the settings list and the use + * of settings (we cannot take a setting out that is being used). */ drive->settings = NULL; - spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); } EXPORT_SYMBOL(ide_proc_unregister_driver); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 04f8f13cb9d7..f0f09f702e9c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -74,9 +74,6 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, DEFINE_MUTEX(ide_cfg_mtx); -__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -EXPORT_SYMBOL(ide_lock); - static void ide_port_init_devices_data(ide_hwif_t *); /* @@ -130,7 +127,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) } } -/* Called with ide_lock held. */ static void __ide_port_unregister_devices(ide_hwif_t *hwif) { int i; @@ -139,10 +135,8 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif) ide_drive_t *drive = &hwif->drives[i]; if (drive->dev_flags & IDE_DFLAG_PRESENT) { - spin_unlock_irq(&ide_lock); device_unregister(&drive->gendev); wait_for_completion(&drive->gendev_rel_comp); - spin_lock_irq(&ide_lock); } } } @@ -150,11 +144,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif) void ide_port_unregister_devices(ide_hwif_t *hwif) { mutex_lock(&ide_cfg_mtx); - spin_lock_irq(&ide_lock); __ide_port_unregister_devices(hwif); hwif->present = 0; ide_port_init_devices_data(hwif); - spin_unlock_irq(&ide_lock); mutex_unlock(&ide_cfg_mtx); } EXPORT_SYMBOL_GPL(ide_port_unregister_devices); @@ -192,12 +184,10 @@ void ide_unregister(ide_hwif_t *hwif) mutex_lock(&ide_cfg_mtx); - spin_lock_irq(&ide_lock); if (hwif->present) { __ide_port_unregister_devices(hwif); hwif->present = 0; } - spin_unlock_irq(&ide_lock); ide_proc_unregister_port(hwif); @@ -340,6 +330,7 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) static int set_pio_mode(ide_drive_t *drive, int arg) { ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; const struct ide_port_ops *port_ops = hwif->port_ops; if (arg < 0 || arg > 255) @@ -354,9 +345,9 @@ static int set_pio_mode(ide_drive_t *drive, int arg) unsigned long flags; /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); port_ops->set_pio_mode(drive, arg); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); } else port_ops->set_pio_mode(drive, arg); } else { @@ -397,80 +388,6 @@ ide_ext_devset_rw_sync(unmaskirq, unmaskirq); ide_ext_devset_rw_sync(using_dma, using_dma); __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); -static int generic_ide_suspend(struct device *dev, pm_message_t mesg) -{ - ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - struct request_pm_state rqpm; - ide_task_t args; - int ret; - - /* call ACPI _GTM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) - ide_acpi_get_timing(hwif); - - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_PM_SUSPEND; - rq->special = &args; - rq->data = &rqpm; - rqpm.pm_step = IDE_PM_START_SUSPEND; - if (mesg.event == PM_EVENT_PRETHAW) - mesg.event = PM_EVENT_FREEZE; - rqpm.pm_state = mesg.event; - - ret = blk_execute_rq(drive->queue, NULL, rq, 0); - blk_put_request(rq); - - /* call ACPI _PS3 only after both devices are suspended */ - if (ret == 0 && ((drive->dn & 1) || pair == NULL)) - ide_acpi_set_state(hwif, 0); - - return ret; -} - -static int generic_ide_resume(struct device *dev) -{ - ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - struct request_pm_state rqpm; - ide_task_t args; - int err; - - /* call ACPI _PS0 / _STM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) { - ide_acpi_set_state(hwif, 1); - ide_acpi_push_timing(hwif); - } - - ide_acpi_exec_tfs(drive); - - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_PM_RESUME; - rq->cmd_flags |= REQ_PREEMPT; - rq->special = &args; - rq->data = &rqpm; - rqpm.pm_step = IDE_PM_START_RESUME; - rqpm.pm_state = PM_EVENT_ON; - - err = blk_execute_rq(drive->queue, NULL, rq, 1); - blk_put_request(rq); - - if (err == 0 && dev->driver) { - ide_driver_t *drv = to_ide_driver(dev->driver); - - if (drv->resume) - drv->resume(drive); - } - - return err; -} - /** * ide_device_get - get an additional reference to a ide_drive_t * @drive: device to get a reference to diff --git a/drivers/ide/ide_arm.c b/drivers/ide/ide_arm.c index f728f2927b5a..bdcac94d7c1f 100644 --- a/drivers/ide/ide_arm.c +++ b/drivers/ide/ide_arm.c @@ -15,15 +15,8 @@ #define DRV_NAME "ide_arm" -#ifdef CONFIG_ARCH_CLPS7500 -# include <mach/hardware.h> -# -# define IDE_ARM_IO (ISASLOT_IO + 0x1f0) -# define IDE_ARM_IRQ IRQ_ISA_14 -#else -# define IDE_ARM_IO 0x1f0 -# define IDE_ARM_IRQ IRQ_HARDDISK -#endif +#define IDE_ARM_IO 0x1f0 +#define IDE_ARM_IRQ IRQ_HARDDISK static int __init ide_arm_init(void) { diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 799557c25eef..624e62e5cc9a 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c @@ -350,16 +350,17 @@ static const struct ide_dma_ops pdc2026x_dma_ops = { .dma_timeout = pdc202xx_dma_timeout, }; -#define DECLARE_PDC2026X_DEV(udma, extra_flags) \ +#define DECLARE_PDC2026X_DEV(udma, sectors) \ { \ .name = DRV_NAME, \ .init_chipset = init_chipset_pdc202xx, \ .port_ops = &pdc2026x_port_ops, \ .dma_ops = &pdc2026x_dma_ops, \ - .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \ + .host_flags = IDE_HFLAGS_PDC202XX, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = udma, \ + .max_sectors = sectors, \ } static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { @@ -376,8 +377,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { /* 1: PDC2026{2,3} */ DECLARE_PDC2026X_DEV(ATA_UDMA4, 0), - /* 2: PDC2026{5,7} */ - DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256), + /* 2: PDC2026{5,7}: UDMA5, limit LBA48 requests to 256 sectors */ + DECLARE_PDC2026X_DEV(ATA_UDMA5, 256), }; /** diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c index 7daf0135cbac..a6414a884eb1 100644 --- a/drivers/ide/rz1000.c +++ b/drivers/ide/rz1000.c @@ -22,34 +22,48 @@ #define DRV_NAME "rz1000" -static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) +static int __devinit rz1000_disable_readahead(struct pci_dev *dev) { - struct pci_dev *dev = to_pci_dev(hwif->dev); u16 reg; if (!pci_read_config_word (dev, 0x40, ®) && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { printk(KERN_INFO "%s: disabled chipset read-ahead " - "(buggy RZ1000/RZ1001)\n", hwif->name); + "(buggy RZ1000/RZ1001)\n", pci_name(dev)); + return 0; } else { - if (hwif->mate) - hwif->mate->serialized = hwif->serialized = 1; - hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS; printk(KERN_INFO "%s: serialized, disabled unmasking " - "(buggy RZ1000/RZ1001)\n", hwif->name); + "(buggy RZ1000/RZ1001)\n", pci_name(dev)); + return 1; } } static const struct ide_port_info rz1000_chipset __devinitdata = { .name = DRV_NAME, - .init_hwif = init_hwif_rz1000, - .chipset = ide_rz1000, .host_flags = IDE_HFLAG_NO_DMA, }; static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_pci_init_one(dev, &rz1000_chipset, NULL); + struct ide_port_info d = rz1000_chipset; + int rc; + + rc = pci_enable_device(dev); + if (rc) + return rc; + + if (rz1000_disable_readahead(dev)) { + d.host_flags |= IDE_HFLAG_SERIALIZE; + d.host_flags |= IDE_HFLAG_NO_UNMASK_IRQS; + } + + return ide_pci_init_one(dev, &d, NULL); +} + +static void rz1000_remove(struct pci_dev *dev) +{ + ide_pci_remove(dev); + pci_disable_device(dev); } static const struct pci_device_id rz1000_pci_tbl[] = { @@ -63,7 +77,7 @@ static struct pci_driver rz1000_pci_driver = { .name = "RZ1000_IDE", .id_table = rz1000_pci_tbl, .probe = rz1000_init_one, - .remove = ide_pci_remove, + .remove = rz1000_remove, }; static int __init rz1000_ide_init(void) diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index 75ea61526566..2a5ea90cf8b8 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -328,10 +328,10 @@ static struct ide_dma_ops trm290_dma_ops = { static const struct ide_port_info trm290_chipset __devinitdata = { .name = DRV_NAME, .init_hwif = init_hwif_trm290, - .chipset = ide_trm290, .port_ops = &trm290_port_ops, .dma_ops = &trm290_dma_ops, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | + .host_flags = IDE_HFLAG_TRM290 | + IDE_HFLAG_NO_ATAPI_DMA | #if 0 /* play it safe for now */ IDE_HFLAG_TRUST_BIOS_FOR_DMA | #endif diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 9120063e8f87..13b63e7fa353 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -181,7 +181,7 @@ static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq, while (count--) *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port)); - __ide_flush_dcache_range((unsigned long)buf, count * 2); + __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); } static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq, @@ -195,7 +195,7 @@ static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq, __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port); ptr++; } - __ide_flush_dcache_range((unsigned long)buf, count * 2); + __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); } static const struct ide_tp_ops tx4938ide_tp_ops = { diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index bafb7d1a22e2..97cd9e0f66f6 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c @@ -259,6 +259,12 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq) bcount = 0x10000 - (cur_addr & 0xffff); if (bcount > cur_len) bcount = cur_len; + /* + * This workaround for zero count seems required. + * (standard ide_build_dmatable do it too) + */ + if ((bcount & 0xffff) == 0x0000) + bcount = 0x8000; *table++ = bcount & 0xffff; *table++ = cur_addr; cur_addr += bcount; @@ -558,7 +564,7 @@ static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq, while (count--) *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port)); - __ide_flush_dcache_range((unsigned long)buf, count * 2); + __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); } static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq, @@ -572,7 +578,7 @@ static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq, __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port); ptr++; } - __ide_flush_dcache_range((unsigned long)buf, count * 2); + __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); } static const struct ide_tp_ops tx4939ide_tp_ops = { diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index 1da076e0c917..e29978cf6197 100644 --- a/drivers/ide/umc8672.c +++ b/drivers/ide/umc8672.c @@ -107,18 +107,21 @@ static void umc_set_speeds(u8 speeds[]) static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = drive->hwif; - unsigned long flags; + ide_hwgroup_t *mate_hwgroup = hwif->mate ? hwif->mate->hwgroup : NULL; + unsigned long uninitialized_var(flags); printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - spin_lock_irqsave(&ide_lock, flags); - if (hwif->mate && hwif->mate->hwgroup->handler) { + if (mate_hwgroup) + spin_lock_irqsave(&mate_hwgroup->lock, flags); + if (mate_hwgroup && mate_hwgroup->handler) { printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); } else { current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; umc_set_speeds(current_speeds); } - spin_unlock_irqrestore(&ide_lock, flags); + if (mate_hwgroup) + spin_unlock_irqrestore(&mate_hwgroup->lock, flags); } static const struct ide_port_ops umc8672_port_ops = { diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 69e674ecf19a..db22fd9b4cf2 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -101,7 +101,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) if (cpu_is_omap24xx()) { int i; for (i = 0; i < omap_kp->rows; i++) - disable_irq(OMAP_GPIO_IRQ(row_gpios[i])); + disable_irq(gpio_to_irq(row_gpios[i])); } else /* disable keyboard interrupt and schedule for handling */ omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); @@ -224,7 +224,7 @@ static void omap_kp_tasklet(unsigned long data) if (cpu_is_omap24xx()) { int i; for (i = 0; i < omap_kp_data->rows; i++) - enable_irq(OMAP_GPIO_IRQ(row_gpios[i])); + enable_irq(gpio_to_irq(row_gpios[i])); } else { omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); kp_cur_group = -1; @@ -397,7 +397,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); } else { for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { - if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), + if (request_irq(gpio_to_irq(row_gpios[irq_idx]), omap_kp_interrupt, IRQF_TRIGGER_FALLING, "omap-keypad", omap_kp) < 0) @@ -438,7 +438,7 @@ static int omap_kp_remove(struct platform_device *pdev) gpio_free(col_gpios[i]); for (i = 0; i < omap_kp->rows; i++) { gpio_free(row_gpios[i]); - free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); + free_irq(gpio_to_irq(row_gpios[i]), 0); } } else { omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 6d30c6d334c3..0d2fc64a5e1c 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -475,7 +475,7 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) goto failed_free_mem; } - keypad->clk = clk_get(&pdev->dev, "KBDCLK"); + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get keypad clock\n"); error = PTR_ERR(keypad->clk); diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 27d70d326ff3..da3c3a5d2689 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -79,7 +79,7 @@ config SERIO_PARKBD config SERIO_RPCKBD tristate "Acorn RiscPC keyboard controller" - depends on ARCH_ACORN || ARCH_CLPS7500 + depends on ARCH_ACORN default y help Say Y here if you have the Acorn RiscPC and want to use an AT diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index b9b7fc6ff1eb..e1ece89fe922 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -697,7 +697,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) struct ads7846 *ts = container_of(handle, struct ads7846, timer); int status = 0; - spin_lock_irq(&ts->lock); + spin_lock(&ts->lock); if (unlikely(!get_pendown_state(ts) || device_suspended(&ts->spi->dev))) { @@ -728,7 +728,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) dev_err(&ts->spi->dev, "spi_async --> %d\n", status); } - spin_unlock_irq(&ts->lock); + spin_unlock(&ts->lock); return HRTIMER_NORESTART; } diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index ba648750a8d9..1d11e2be9ef8 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -31,7 +31,7 @@ #include <linux/interrupt.h> #include <linux/wm97xx.h> #include <linux/io.h> -#include <mach/pxa-regs.h> +#include <mach/regs-ac97.h> #define VERSION "0.13" diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 5faefeaf6790..f2c641e0bdde 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -164,7 +164,7 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt); void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); /* page_tables.c: */ -int init_guest_pagetable(struct lguest *lg, unsigned long pgtable); +int init_guest_pagetable(struct lguest *lg); void free_guest_pagetable(struct lguest *lg); void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable); void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i); diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index a661bbdae3d6..915da6b8c924 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -250,7 +250,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, /* Figure out how many pages the ring will take, and map that memory */ lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, DIV_ROUND_UP(vring_size(lvq->config.num, - PAGE_SIZE), + LGUEST_VRING_ALIGN), PAGE_SIZE)); if (!lvq->pages) { err = -ENOMEM; @@ -259,8 +259,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, /* OK, tell virtio_ring.c to set up a virtqueue now we know its size * and we've got a pointer to its pages. */ - vq = vring_new_virtqueue(lvq->config.num, vdev, lvq->pages, - lg_notify, callback); + vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, + vdev, lvq->pages, lg_notify, callback); if (!vq) { err = -ENOMEM; goto unmap; @@ -272,7 +272,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, * the interrupt as a source of randomness: it'd be nice to have that * back.. */ err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED, - vdev->dev.bus_id, vq); + dev_name(&vdev->dev), vq); if (err) goto destroy_vring; diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index e73a000473cc..34bc017b8b3c 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -146,7 +146,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) return 0; } -/*L:020 The initialization write supplies 4 pointer sized (32 or 64 bit) +/*L:020 The initialization write supplies 3 pointer sized (32 or 64 bit) * values (in addition to the LHREQ_INITIALIZE value). These are: * * base: The start of the Guest-physical memory inside the Launcher memory. @@ -155,9 +155,6 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) * allowed to access. The Guest memory lives inside the Launcher, so it sets * this to ensure the Guest can only reach its own memory. * - * pgdir: The (Guest-physical) address of the top of the initial Guest - * pagetables (which are set up by the Launcher). - * * start: The first instruction to execute ("eip" in x86-speak). */ static int initialize(struct file *file, const unsigned long __user *input) @@ -166,7 +163,7 @@ static int initialize(struct file *file, const unsigned long __user *input) * Guest. */ struct lguest *lg; int err; - unsigned long args[4]; + unsigned long args[3]; /* We grab the Big Lguest lock, which protects against multiple * simultaneous initializations. */ @@ -192,14 +189,14 @@ static int initialize(struct file *file, const unsigned long __user *input) lg->mem_base = (void __user *)args[0]; lg->pfn_limit = args[1]; - /* This is the first cpu (cpu 0) and it will start booting at args[3] */ - err = lg_cpu_start(&lg->cpus[0], 0, args[3]); + /* This is the first cpu (cpu 0) and it will start booting at args[2] */ + err = lg_cpu_start(&lg->cpus[0], 0, args[2]); if (err) goto release_guest; /* Initialize the Guest's shadow page tables, using the toplevel * address the Launcher gave us. This allocates memory, so can fail. */ - err = init_guest_pagetable(lg, args[2]); + err = init_guest_pagetable(lg); if (err) goto free_regs; diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 81d0c6053447..576a8318221c 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -14,6 +14,7 @@ #include <linux/percpu.h> #include <asm/tlbflush.h> #include <asm/uaccess.h> +#include <asm/bootparam.h> #include "lg.h" /*M:008 We hold reference to pages, which prevents them from being swapped. @@ -581,15 +582,82 @@ void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 idx) release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx); } +/* Once we know how much memory we have we can construct simple identity + * (which set virtual == physical) and linear mappings + * which will get the Guest far enough into the boot to create its own. + * + * We lay them out of the way, just below the initrd (which is why we need to + * know its size here). */ +static unsigned long setup_pagetables(struct lguest *lg, + unsigned long mem, + unsigned long initrd_size) +{ + pgd_t __user *pgdir; + pte_t __user *linear; + unsigned int mapped_pages, i, linear_pages, phys_linear; + unsigned long mem_base = (unsigned long)lg->mem_base; + + /* We have mapped_pages frames to map, so we need + * linear_pages page tables to map them. */ + mapped_pages = mem / PAGE_SIZE; + linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE; + + /* We put the toplevel page directory page at the top of memory. */ + pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE); + + /* Now we use the next linear_pages pages as pte pages */ + linear = (void *)pgdir - linear_pages * PAGE_SIZE; + + /* Linear mapping is easy: put every page's address into the + * mapping in order. */ + for (i = 0; i < mapped_pages; i++) { + pte_t pte; + pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER)); + if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0) + return -EFAULT; + } + + /* The top level points to the linear page table pages above. + * We setup the identity and linear mappings here. */ + phys_linear = (unsigned long)linear - mem_base; + for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) { + pgd_t pgd; + pgd = __pgd((phys_linear + i * sizeof(pte_t)) | + (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); + + if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd)) + || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET) + + i / PTRS_PER_PTE], + &pgd, sizeof(pgd))) + return -EFAULT; + } + + /* We return the top level (guest-physical) address: remember where + * this is. */ + return (unsigned long)pgdir - mem_base; +} + /*H:500 (vii) Setting up the page tables initially. * * When a Guest is first created, the Launcher tells us where the toplevel of * its first page table is. We set some things up here: */ -int init_guest_pagetable(struct lguest *lg, unsigned long pgtable) +int init_guest_pagetable(struct lguest *lg) { + u64 mem; + u32 initrd_size; + struct boot_params __user *boot = (struct boot_params *)lg->mem_base; + + /* Get the Guest memory size and the ramdisk size from the boot header + * located at lg->mem_base (Guest address 0). */ + if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem)) + || get_user(initrd_size, &boot->hdr.ramdisk_size)) + return -EFAULT; + /* We start on the first shadow page table, and give it a blank PGD * page. */ - lg->pgdirs[0].gpgdir = pgtable; + lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size); + if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir)) + return lg->pgdirs[0].gpgdir; lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL); if (!lg->pgdirs[0].pgdir) return -ENOMEM; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ce26c84af064..3326750ec02c 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1060,7 +1060,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_page_pool; } - cc->bs = bioset_create(MIN_IOS, MIN_IOS); + cc->bs = bioset_create(MIN_IOS, 0); if (!cc->bs) { ti->error = "Cannot allocate crypt bioset"; goto bad_bs; diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 2fd6d4450637..a34338567a2a 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -56,7 +56,7 @@ struct dm_io_client *dm_io_client_create(unsigned num_pages) if (!client->pool) goto bad; - client->bios = bioset_create(16, 16); + client->bios = bioset_create(16, 0); if (!client->bios) goto bad; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 343094c3feeb..421c9f02d8ca 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1093,7 +1093,7 @@ static struct mapped_device *alloc_dev(int minor) if (!md->tio_pool) goto bad_tio_pool; - md->bs = bioset_create(16, 16); + md->bs = bioset_create(16, 0); if (!md->bs) goto bad_no_bioset; diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index b2d9fe5dfd61..9d33de22cc48 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -38,6 +38,8 @@ #include <mach/pxa-regs.h> #include <mach/camera.h> +#include "pxa_camera.h" + #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) #define PXA_CAM_DRV_NAME "pxa27x-camera" @@ -1402,7 +1404,7 @@ static int pxa_camera_probe(struct platform_device *pdev) goto exit; } - pcdev->clk = clk_get(&pdev->dev, "CAMCLK"); + pcdev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(pcdev->clk)) { err = PTR_ERR(pcdev->clk); goto exit_kfree; diff --git a/drivers/media/video/pxa_camera.h b/drivers/media/video/pxa_camera.h new file mode 100644 index 000000000000..89cbfc9a35c5 --- /dev/null +++ b/drivers/media/video/pxa_camera.h @@ -0,0 +1,95 @@ +/* Camera Interface */ +#define CICR0 __REG(0x50000000) +#define CICR1 __REG(0x50000004) +#define CICR2 __REG(0x50000008) +#define CICR3 __REG(0x5000000C) +#define CICR4 __REG(0x50000010) +#define CISR __REG(0x50000014) +#define CIFR __REG(0x50000018) +#define CITOR __REG(0x5000001C) +#define CIBR0 __REG(0x50000028) +#define CIBR1 __REG(0x50000030) +#define CIBR2 __REG(0x50000038) + +#define CICR0_DMAEN (1 << 31) /* DMA request enable */ +#define CICR0_PAR_EN (1 << 30) /* Parity enable */ +#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ +#define CICR0_ENB (1 << 28) /* Camera interface enable */ +#define CICR0_DIS (1 << 27) /* Camera interface disable */ +#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ +#define CICR0_TOM (1 << 9) /* Time-out mask */ +#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ +#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ +#define CICR0_EOLM (1 << 6) /* End-of-line mask */ +#define CICR0_PERRM (1 << 5) /* Parity-error mask */ +#define CICR0_QDM (1 << 4) /* Quick-disable mask */ +#define CICR0_CDM (1 << 3) /* Disable-done mask */ +#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ +#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ +#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ + +#define CICR1_TBIT (1 << 31) /* Transparency bit */ +#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ +#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ +#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ +#define CICR1_RGB_F (1 << 11) /* RGB format */ +#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ +#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ +#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ +#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ +#define CICR1_DW (0x7 << 0) /* Data width mask */ + +#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock + wait count mask */ +#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock + wait count mask */ +#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ +#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR2_FSW (0x7 << 0) /* Frame stabilization + wait count mask */ + +#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock + wait count mask */ +#define CICR3_EFW (0xff << 16) /* End-of-frame line clock + wait count mask */ +#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ +#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ + +#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ +#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ +#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ +#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ +#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ +#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ +#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ +#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ + +#define CISR_FTO (1 << 15) /* FIFO time-out */ +#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ +#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ +#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ +#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ +#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ +#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ +#define CISR_EOL (1 << 8) /* End of line */ +#define CISR_PAR_ERR (1 << 7) /* Parity error */ +#define CISR_CQD (1 << 6) /* Camera interface quick disable */ +#define CISR_CDD (1 << 5) /* Camera interface disable done */ +#define CISR_SOF (1 << 4) /* Start of frame */ +#define CISR_EOF (1 << 3) /* End of frame */ +#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ +#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ +#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ + +#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ +#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ +#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ +#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ +#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ +#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ +#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ +#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ + diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index e4c0db4dc7b1..9e485459f63b 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -474,9 +474,9 @@ static __init int asic3_gpio_probe(struct platform_device *pdev, u16 dir_reg[ASIC3_NUM_GPIO_BANKS]; int i; - memzero(alt_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); - memzero(out_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); - memzero(dir_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); + memset(alt_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); + memset(out_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); + memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); /* Enable all GPIOs */ asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff); diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index b4ed57e02729..6063dc2b52e8 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -18,7 +18,7 @@ #include <linux/slab.h> #include <linux/string.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <asm/system.h> #include "mcp.h" diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 28380b20bc70..62b32dabf629 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -20,7 +20,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/system.h> diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c index 61aeaf79640d..86fed4870f93 100644 --- a/drivers/mfd/ucb1x00-assabet.c +++ b/drivers/mfd/ucb1x00-assabet.c @@ -15,7 +15,7 @@ #include <linux/proc_fs.h> #include <linux/device.h> -#include <asm/dma.h> +#include <mach/dma.h> #include "ucb1x00.h" diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index a316f1b75933..6860c924f364 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -25,7 +25,7 @@ #include <linux/device.h> #include <linux/mutex.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/hardware.h> #include "ucb1x00.h" diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 44762ca86a8d..61b7d3eb9a2f 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -31,7 +31,7 @@ #include <linux/slab.h> #include <linux/kthread.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/collie.h> #include <asm/mach-types.h> diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 2f0fcdb869b7..eb29b1d933ac 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -10,20 +10,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz> - * Changed to conform redesigned i.MX scatter gather DMA interface - * - * 2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz> - * Updated for 2.6.14 kernel - * - * 2005-12-13 Jay Monkman <jtm@smoothsmoothie.com> - * Found and corrected problems in the write path - * - * 2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz> - * The event handling rewritten right way in softirq. - * Added many ugly hacks and delays to overcome SDHC - * deficiencies - * */ #include <linux/module.h> @@ -37,9 +23,9 @@ #include <linux/mmc/card.h> #include <linux/delay.h> #include <linux/clk.h> +#include <linux/io.h> #include <asm/dma.h> -#include <asm/io.h> #include <asm/irq.h> #include <asm/sizes.h> #include <mach/mmc.h> @@ -50,17 +36,16 @@ #define DRIVER_NAME "imx-mmc" #define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \ - INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \ - INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO) + INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \ + INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO) struct imxmci_host { struct mmc_host *mmc; spinlock_t lock; struct resource *res; + void __iomem *base; int irq; imx_dmach_t dma; - unsigned int clkrt; - unsigned int cmdat; volatile unsigned int imask; unsigned int power_mode; unsigned int present; @@ -74,7 +59,7 @@ struct imxmci_host { struct tasklet_struct tasklet; unsigned int status_reg; unsigned long pending_events; - /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */ + /* Next two fields are there for CPU driven transfers to overcome SDHC deficiencies */ u16 *data_ptr; unsigned int data_cnt; atomic_t stuck_timeout; @@ -114,14 +99,22 @@ struct imxmci_host { static void imxmci_stop_clock(struct imxmci_host *host) { int i = 0; - MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK; - while(i < 0x1000) { - if(!(i & 0x7f)) - MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK; + u16 reg; + + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg & ~STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); + while (i < 0x1000) { + if (!(i & 0x7f)) { + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg | STR_STP_CLK_STOP_CLK, + host->base + MMC_REG_STR_STP_CLK); + } - if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) { + reg = readw(host->base + MMC_REG_STATUS); + if (!(reg & STATUS_CARD_BUS_CLK_RUN)) { /* Check twice before cut */ - if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) + reg = readw(host->base + MMC_REG_STATUS); + if (!(reg & STATUS_CARD_BUS_CLK_RUN)) return; } @@ -135,8 +128,10 @@ static int imxmci_start_clock(struct imxmci_host *host) unsigned int trials = 0; unsigned int delay_limit = 128; unsigned long flags; + u16 reg; - MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg & ~STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK); clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events); @@ -145,18 +140,21 @@ static int imxmci_start_clock(struct imxmci_host *host) * then 6 delay loops, but during card detection (low clockrate) * it takes up to 5000 delay loops and sometimes fails for the first time */ - MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg | STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); do { unsigned int delay = delay_limit; - while(delay--){ - if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) + while (delay--) { + reg = readw(host->base + MMC_REG_STATUS); + if (reg & STATUS_CARD_BUS_CLK_RUN) /* Check twice before cut */ - if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) + reg = readw(host->base + MMC_REG_STATUS); + if (reg & STATUS_CARD_BUS_CLK_RUN) return 0; - if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) + if (test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) return 0; } @@ -167,58 +165,59 @@ static int imxmci_start_clock(struct imxmci_host *host) * IRQ or schedule delays this function execution and the clocks has * been already stopped by other means (response processing, SDHC HW) */ - if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) - MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; + if (!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) { + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg | STR_STP_CLK_START_CLK, + host->base + MMC_REG_STR_STP_CLK); + } local_irq_restore(flags); - } while(++trials<256); + } while (++trials < 256); dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); return -1; } -static void imxmci_softreset(void) +static void imxmci_softreset(struct imxmci_host *host) { + int i; + /* reset sequence */ - MMC_STR_STP_CLK = 0x8; - MMC_STR_STP_CLK = 0xD; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - MMC_STR_STP_CLK = 0x5; - - MMC_RES_TO = 0xff; - MMC_BLK_LEN = 512; - MMC_NOB = 1; + writew(0x08, host->base + MMC_REG_STR_STP_CLK); + writew(0x0D, host->base + MMC_REG_STR_STP_CLK); + + for (i = 0; i < 8; i++) + writew(0x05, host->base + MMC_REG_STR_STP_CLK); + + writew(0xff, host->base + MMC_REG_RES_TO); + writew(512, host->base + MMC_REG_BLK_LEN); + writew(1, host->base + MMC_REG_NOB); } static int imxmci_busy_wait_for_status(struct imxmci_host *host, - unsigned int *pstat, unsigned int stat_mask, - int timeout, const char *where) + unsigned int *pstat, unsigned int stat_mask, + int timeout, const char *where) { - int loops=0; - while(!(*pstat & stat_mask)) { - loops+=2; - if(loops >= timeout) { + int loops = 0; + + while (!(*pstat & stat_mask)) { + loops += 2; + if (loops >= timeout) { dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n", where, *pstat, stat_mask); return -1; } udelay(2); - *pstat |= MMC_STATUS; + *pstat |= readw(host->base + MMC_REG_STATUS); } - if(!loops) + if (!loops) return 0; /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */ - if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000)) + if (!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock >= 8000000)) dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", - loops, where, *pstat, stat_mask); + loops, where, *pstat, stat_mask); return loops; } @@ -235,8 +234,8 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) host->data = data; data->bytes_xfered = 0; - MMC_NOB = nob; - MMC_BLK_LEN = blksz; + writew(nob, host->base + MMC_REG_NOB); + writew(blksz, host->base + MMC_REG_BLK_LEN); /* * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise. @@ -252,14 +251,14 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) host->dma_dir = DMA_FROM_DEVICE; /* Hack to enable read SCR */ - MMC_NOB = 1; - MMC_BLK_LEN = 512; + writew(1, host->base + MMC_REG_NOB); + writew(512, host->base + MMC_REG_BLK_LEN); } else { host->dma_dir = DMA_TO_DEVICE; } /* Convert back to virtual address */ - host->data_ptr = (u16*)sg_virt(data->sg); + host->data_ptr = (u16 *)sg_virt(data->sg); host->data_cnt = 0; clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); @@ -271,10 +270,11 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) if (data->flags & MMC_DATA_READ) { host->dma_dir = DMA_FROM_DEVICE; host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, host->dma_dir); + data->sg_len, host->dma_dir); imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz, - host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ); + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_READ); /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/ CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN; @@ -282,10 +282,11 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) host->dma_dir = DMA_TO_DEVICE; host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, host->dma_dir); + data->sg_len, host->dma_dir); imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz, - host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE); + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_WRITE); /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/ CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN; @@ -293,12 +294,12 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) #if 1 /* This code is there only for consistency checking and can be disabled in future */ host->dma_size = 0; - for(i=0; i<host->dma_nents; i++) - host->dma_size+=data->sg[i].length; + for (i = 0; i < host->dma_nents; i++) + host->dma_size += data->sg[i].length; if (datasz > host->dma_size) { dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n", - datasz, host->dma_size); + datasz, host->dma_size); } #endif @@ -306,7 +307,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) wmb(); - if(host->actual_bus_width == MMC_BUS_WIDTH_4) + if (host->actual_bus_width == MMC_BUS_WIDTH_4) BLR(host->dma) = 0; /* burst 64 byte read / 64 bytes write */ else BLR(host->dma) = 16; /* burst 16 byte read / 16 bytes write */ @@ -317,9 +318,8 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events); /* start DMA engine for read, write is delayed after initial response */ - if (host->dma_dir == DMA_FROM_DEVICE) { + if (host->dma_dir == DMA_FROM_DEVICE) imx_dma_enable(host->dma); - } } static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat) @@ -351,16 +351,16 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, break; } - if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) ) + if (test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events)) cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */ - if ( host->actual_bus_width == MMC_BUS_WIDTH_4 ) + if (host->actual_bus_width == MMC_BUS_WIDTH_4) cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; - MMC_CMD = cmd->opcode; - MMC_ARGH = cmd->arg >> 16; - MMC_ARGL = cmd->arg & 0xffff; - MMC_CMD_DAT_CONT = cmdat; + writew(cmd->opcode, host->base + MMC_REG_CMD); + writew(cmd->arg >> 16, host->base + MMC_REG_ARGH); + writew(cmd->arg & 0xffff, host->base + MMC_REG_ARGL); + writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT); atomic_set(&host->stuck_timeout, 0); set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events); @@ -368,18 +368,18 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, imask = IMXMCI_INT_MASK_DEFAULT; imask &= ~INT_MASK_END_CMD_RES; - if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) { - /*imask &= ~INT_MASK_BUF_READY;*/ + if (cmdat & CMD_DAT_CONT_DATA_ENABLE) { + /* imask &= ~INT_MASK_BUF_READY; */ imask &= ~INT_MASK_DATA_TRAN; - if ( cmdat & CMD_DAT_CONT_WRITE ) + if (cmdat & CMD_DAT_CONT_WRITE) imask &= ~INT_MASK_WRITE_OP_DONE; - if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) + if (test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) imask &= ~INT_MASK_BUF_READY; } spin_lock_irqsave(&host->lock, flags); host->imask = imask; - MMC_INT_MASK = host->imask; + writew(host->imask, host->base + MMC_REG_INT_MASK); spin_unlock_irqrestore(&host->lock, flags); dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n", @@ -395,14 +395,14 @@ static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request * spin_lock_irqsave(&host->lock, flags); host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m | - IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m); + IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m); host->imask = IMXMCI_INT_MASK_DEFAULT; - MMC_INT_MASK = host->imask; + writew(host->imask, host->base + MMC_REG_INT_MASK); spin_unlock_irqrestore(&host->lock, flags); - if(req && req->cmd) + if (req && req->cmd) host->prev_cmd_code = req->cmd->opcode; host->req = NULL; @@ -416,17 +416,17 @@ static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat) struct mmc_data *data = host->data; int data_error; - if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){ + if (test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { imx_dma_disable(host->dma); dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, host->dma_dir); } - if ( stat & STATUS_ERR_MASK ) { - dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat); - if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR)) + if (stat & STATUS_ERR_MASK) { + dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", stat); + if (stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR)) data->error = -EILSEQ; - else if(stat & STATUS_TIME_OUT_READ) + else if (stat & STATUS_TIME_OUT_READ) data->error = -ETIMEDOUT; else data->error = -EIO; @@ -445,7 +445,7 @@ static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat) { struct mmc_command *cmd = host->cmd; int i; - u32 a,b,c; + u32 a, b, c; struct mmc_data *data = host->data; if (!cmd) @@ -461,18 +461,18 @@ static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat) cmd->error = -EILSEQ; } - if(cmd->flags & MMC_RSP_PRESENT) { - if(cmd->flags & MMC_RSP_136) { + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { for (i = 0; i < 4; i++) { - u32 a = MMC_RES_FIFO & 0xffff; - u32 b = MMC_RES_FIFO & 0xffff; - cmd->resp[i] = a<<16 | b; + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[i] = a << 16 | b; } } else { - a = MMC_RES_FIFO & 0xffff; - b = MMC_RES_FIFO & 0xffff; - c = MMC_RES_FIFO & 0xffff; - cmd->resp[0] = a<<24 | b<<8 | c>>8; + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + c = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[0] = a << 24 | b << 8 | c >> 8; } } @@ -484,36 +484,34 @@ static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat) /* Wait for FIFO to be empty before starting DMA write */ - stat = MMC_STATUS; - if(imxmci_busy_wait_for_status(host, &stat, - STATUS_APPL_BUFF_FE, - 40, "imxmci_cmd_done DMA WR") < 0) { + stat = readw(host->base + MMC_REG_STATUS); + if (imxmci_busy_wait_for_status(host, &stat, + STATUS_APPL_BUFF_FE, + 40, "imxmci_cmd_done DMA WR") < 0) { cmd->error = -EIO; imxmci_finish_data(host, stat); - if(host->req) + if (host->req) imxmci_finish_request(host, host->req); dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n", - stat); + stat); return 0; } - if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { + if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) imx_dma_enable(host->dma); - } } } else { struct mmc_request *req; imxmci_stop_clock(host); req = host->req; - if(data) + if (data) imxmci_finish_data(host, stat); - if( req ) { + if (req) imxmci_finish_request(host, req); - } else { + else dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n"); - } } return 1; @@ -535,11 +533,10 @@ static int imxmci_data_done(struct imxmci_host *host, unsigned int stat) } else { struct mmc_request *req; req = host->req; - if( req ) { + if (req) imxmci_finish_request(host, req); - } else { + else dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n"); - } } return 1; @@ -552,7 +549,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) int trans_done = 0; unsigned int stat = *pstat; - if(host->actual_bus_width != MMC_BUS_WIDTH_4) + if (host->actual_bus_width != MMC_BUS_WIDTH_4) burst_len = 16; else burst_len = 64; @@ -563,44 +560,44 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) udelay(20); /* required for clocks < 8MHz*/ - if(host->dma_dir == DMA_FROM_DEVICE) { + if (host->dma_dir == DMA_FROM_DEVICE) { imxmci_busy_wait_for_status(host, &stat, - STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE | - STATUS_TIME_OUT_READ, - 50, "imxmci_cpu_driven_data read"); + STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE | + STATUS_TIME_OUT_READ, + 50, "imxmci_cpu_driven_data read"); - while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && - !(stat & STATUS_TIME_OUT_READ) && - (host->data_cnt < 512)) { + while ((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && + !(stat & STATUS_TIME_OUT_READ) && + (host->data_cnt < 512)) { udelay(20); /* required for clocks < 8MHz*/ - for(i = burst_len; i>=2 ; i-=2) { + for (i = burst_len; i >= 2 ; i -= 2) { u16 data; - data = MMC_BUFFER_ACCESS; + data = readw(host->base + MMC_REG_BUFFER_ACCESS); udelay(10); /* required for clocks < 8MHz*/ - if(host->data_cnt+2 <= host->dma_size) { + if (host->data_cnt+2 <= host->dma_size) { *(host->data_ptr++) = data; } else { - if(host->data_cnt < host->dma_size) - *(u8*)(host->data_ptr) = data; + if (host->data_cnt < host->dma_size) + *(u8 *)(host->data_ptr) = data; } host->data_cnt += 2; } - stat = MMC_STATUS; + stat = readw(host->base + MMC_REG_STATUS); dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n", host->data_cnt, burst_len, stat); } - if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512)) + if ((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512)) trans_done = 1; - if(host->dma_size & 0x1ff) + if (host->dma_size & 0x1ff) stat &= ~STATUS_CRC_READ_ERR; - if(stat & STATUS_TIME_OUT_READ) { + if (stat & STATUS_TIME_OUT_READ) { dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read timeout STATUS = 0x%x\n", stat); trans_done = -1; @@ -608,12 +605,12 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) } else { imxmci_busy_wait_for_status(host, &stat, - STATUS_APPL_BUFF_FE, - 20, "imxmci_cpu_driven_data write"); + STATUS_APPL_BUFF_FE, + 20, "imxmci_cpu_driven_data write"); - while((stat & STATUS_APPL_BUFF_FE) && - (host->data_cnt < host->dma_size)) { - if(burst_len >= host->dma_size - host->data_cnt) { + while ((stat & STATUS_APPL_BUFF_FE) && + (host->data_cnt < host->dma_size)) { + if (burst_len >= host->dma_size - host->data_cnt) { burst_len = host->dma_size - host->data_cnt; host->data_cnt = host->dma_size; trans_done = 1; @@ -621,10 +618,10 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) host->data_cnt += burst_len; } - for(i = burst_len; i>0 ; i-=2) - MMC_BUFFER_ACCESS = *(host->data_ptr++); + for (i = burst_len; i > 0 ; i -= 2) + writew(*(host->data_ptr++), host->base + MMC_REG_BUFFER_ACCESS); - stat = MMC_STATUS; + stat = readw(host->base + MMC_REG_STATUS); dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n", burst_len, stat); @@ -639,7 +636,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) static void imxmci_dma_irq(int dma, void *devid) { struct imxmci_host *host = devid; - uint32_t stat = MMC_STATUS; + u32 stat = readw(host->base + MMC_REG_STATUS); atomic_set(&host->stuck_timeout, 0); host->status_reg = stat; @@ -650,10 +647,11 @@ static void imxmci_dma_irq(int dma, void *devid) static irqreturn_t imxmci_irq(int irq, void *devid) { struct imxmci_host *host = devid; - uint32_t stat = MMC_STATUS; + u32 stat = readw(host->base + MMC_REG_STATUS); int handled = 1; - MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT; + writew(host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT, + host->base + MMC_REG_INT_MASK); atomic_set(&host->stuck_timeout, 0); host->status_reg = stat; @@ -671,10 +669,10 @@ static void imxmci_tasklet_fnc(unsigned long data) unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */ int timeout = 0; - if(atomic_read(&host->stuck_timeout) > 4) { + if (atomic_read(&host->stuck_timeout) > 4) { char *what; timeout = 1; - stat = MMC_STATUS; + stat = readw(host->base + MMC_REG_STATUS); host->status_reg = stat; if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) @@ -683,29 +681,37 @@ static void imxmci_tasklet_fnc(unsigned long data) what = "RESP"; else if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) - if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events)) + if (test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events)) what = "DATA"; else what = "DMA"; else what = "???"; - dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n", - what, stat, MMC_INT_MASK); - dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", - MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); + dev_err(mmc_dev(host->mmc), + "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n", + what, stat, + readw(host->base + MMC_REG_INT_MASK)); + dev_err(mmc_dev(host->mmc), + "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", + readw(host->base + MMC_REG_CMD_DAT_CONT), + readw(host->base + MMC_REG_BLK_LEN), + readw(host->base + MMC_REG_NOB), + CCR(host->dma)); dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n", - host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size); + host->cmd ? host->cmd->opcode : 0, + host->prev_cmd_code, + 1 << host->actual_bus_width, host->dma_size); } - if(!host->present || timeout) + if (!host->present || timeout) host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ | - STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR; + STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR; - if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) { + if (test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) { clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); - stat = MMC_STATUS; + stat = readw(host->base + MMC_REG_STATUS); /* * This is not required in theory, but there is chance to miss some flag * which clears automatically by mask write, FreeScale original code keeps @@ -713,63 +719,62 @@ static void imxmci_tasklet_fnc(unsigned long data) */ stat |= host->status_reg; - if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) + if (test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) stat &= ~STATUS_CRC_READ_ERR; - if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { + if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { imxmci_busy_wait_for_status(host, &stat, - STATUS_END_CMD_RESP | STATUS_ERR_MASK, - 20, "imxmci_tasklet_fnc resp (ERRATUM #4)"); + STATUS_END_CMD_RESP | STATUS_ERR_MASK, + 20, "imxmci_tasklet_fnc resp (ERRATUM #4)"); } - if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) { - if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) + if (stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) { + if (test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) imxmci_cmd_done(host, stat); - if(host->data && (stat & STATUS_ERR_MASK)) + if (host->data && (stat & STATUS_ERR_MASK)) imxmci_data_done(host, stat); } - if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) { - stat |= MMC_STATUS; - if(imxmci_cpu_driven_data(host, &stat)){ - if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) + if (test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) { + stat |= readw(host->base + MMC_REG_STATUS); + if (imxmci_cpu_driven_data(host, &stat)) { + if (test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) imxmci_cmd_done(host, stat); atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m, - &host->pending_events); + &host->pending_events); imxmci_data_done(host, stat); } } } - if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) && - !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { + if (test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) && + !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { - stat = MMC_STATUS; + stat = readw(host->base + MMC_REG_STATUS); /* Same as above */ stat |= host->status_reg; - if(host->dma_dir == DMA_TO_DEVICE) { + if (host->dma_dir == DMA_TO_DEVICE) data_dir_mask = STATUS_WRITE_OP_DONE; - } else { + else data_dir_mask = STATUS_DATA_TRANS_DONE; - } - if(stat & data_dir_mask) { + if (stat & data_dir_mask) { clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); imxmci_data_done(host, stat); } } - if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) { + if (test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) { - if(host->cmd) + if (host->cmd) imxmci_cmd_done(host, STATUS_TIME_OUT_RESP); - if(host->data) + if (host->data) imxmci_data_done(host, STATUS_TIME_OUT_READ | STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR); - if(host->req) + if (host->req) imxmci_finish_request(host, host->req); mmc_detect_change(host->mmc, msecs_to_jiffies(100)); @@ -796,9 +801,8 @@ static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data->flags & MMC_DATA_WRITE) cmdat |= CMD_DAT_CONT_WRITE; - if (req->data->flags & MMC_DATA_STREAM) { + if (req->data->flags & MMC_DATA_STREAM) cmdat |= CMD_DAT_CONT_STREAM_BLOCK; - } } imxmci_start_cmd(host, req->cmd, cmdat); @@ -811,36 +815,37 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct imxmci_host *host = mmc_priv(mmc); int prescaler; - if( ios->bus_width==MMC_BUS_WIDTH_4 ) { + if (ios->bus_width == MMC_BUS_WIDTH_4) { host->actual_bus_width = MMC_BUS_WIDTH_4; imx_gpio_mode(PB11_PF_SD_DAT3); - }else{ + } else { host->actual_bus_width = MMC_BUS_WIDTH_1; imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11); } - if ( host->power_mode != ios->power_mode ) { + if (host->power_mode != ios->power_mode) { switch (ios->power_mode) { case MMC_POWER_OFF: - break; + break; case MMC_POWER_UP: set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events); - break; + break; case MMC_POWER_ON: - break; + break; } host->power_mode = ios->power_mode; } - if ( ios->clock ) { + if (ios->clock) { unsigned int clk; + u16 reg; /* The prescaler is 5 for PERCLK2 equal to 96MHz * then 96MHz / 5 = 19.2 MHz */ clk = clk_get_rate(host->clk); - prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE; - switch(prescaler) { + prescaler = (clk + (CLK_RATE * 7) / 8) / CLK_RATE; + switch (prescaler) { case 0: case 1: prescaler = 0; break; @@ -858,24 +863,29 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n", clk, prescaler); - for(clk=0; clk<8; clk++) { + for (clk = 0; clk < 8; clk++) { int x; - x = CLK_RATE / (1<<clk); - if( x <= ios->clock) + x = CLK_RATE / (1 << clk); + if (x <= ios->clock) break; } - MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */ + /* enable controller */ + reg = readw(host->base + MMC_REG_STR_STP_CLK); + writew(reg | STR_STP_CLK_ENABLE, + host->base + MMC_REG_STR_STP_CLK); imxmci_stop_clock(host); - MMC_CLK_RATE = (prescaler<<3) | clk; + writew((prescaler << 3) | clk, host->base + MMC_REG_CLK_RATE); /* * Under my understanding, clock should not be started there, because it would * initiate SDHC sequencer and send last or random command into card */ - /*imxmci_start_clock(host);*/ + /* imxmci_start_clock(host); */ - dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE); + dev_dbg(mmc_dev(host->mmc), + "MMC_CLK_RATE: 0x%08x\n", + readw(host->base + MMC_REG_CLK_RATE)); } else { imxmci_stop_clock(host); } @@ -915,10 +925,10 @@ static void imxmci_check_status(unsigned long data) tasklet_schedule(&host->tasklet); } - if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) || - test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { + if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) || + test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { atomic_inc(&host->stuck_timeout); - if(atomic_read(&host->stuck_timeout) > 4) + if (atomic_read(&host->stuck_timeout) > 4) tasklet_schedule(&host->tasklet); } else { atomic_set(&host->stuck_timeout, 0); @@ -934,6 +944,7 @@ static int imxmci_probe(struct platform_device *pdev) struct imxmci_host *host = NULL; struct resource *r; int ret = 0, irq; + u16 rev_no; printk(KERN_INFO "i.MX mmc driver\n"); @@ -942,7 +953,8 @@ static int imxmci_probe(struct platform_device *pdev) if (!r || irq < 0) return -ENXIO; - if (!request_mem_region(r->start, 0x100, pdev->name)) + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) return -EBUSY; mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev); @@ -966,6 +978,12 @@ static int imxmci_probe(struct platform_device *pdev) mmc->max_blk_count = 65535; host = mmc_priv(mmc); + host->base = ioremap(r->start, resource_size(r)); + if (!host->base) { + ret = -ENOMEM; + goto out; + } + host->mmc = mmc; host->dma_allocated = 0; host->pdata = pdev->dev.platform_data; @@ -993,18 +1011,20 @@ static int imxmci_probe(struct platform_device *pdev) imx_gpio_mode(PB12_PF_SD_CLK); imx_gpio_mode(PB13_PF_SD_CMD); - imxmci_softreset(); + imxmci_softreset(host); - if ( MMC_REV_NO != 0x390 ) { + rev_no = readw(host->base + MMC_REG_REV_NO); + if (rev_no != 0x390) { dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", - MMC_REV_NO); + readw(host->base + MMC_REG_REV_NO)); goto out; } - MMC_READ_TO = 0x2db4; /* recommended in data sheet */ + /* recommended in data sheet */ + writew(0x2db4, host->base + MMC_REG_READ_TO); host->imask = IMXMCI_INT_MASK_DEFAULT; - MMC_INT_MASK = host->imask; + writew(host->imask, host->base + MMC_REG_INT_MASK); host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); if(host->dma < 0) { @@ -1012,7 +1032,7 @@ static int imxmci_probe(struct platform_device *pdev) ret = -EBUSY; goto out; } - host->dma_allocated=1; + host->dma_allocated = 1; imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host); tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host); @@ -1032,7 +1052,7 @@ static int imxmci_probe(struct platform_device *pdev) host->timer.data = (unsigned long)host; host->timer.function = imxmci_check_status; add_timer(&host->timer); - mod_timer(&host->timer, jiffies + (HZ>>1)); + mod_timer(&host->timer, jiffies + (HZ >> 1)); platform_set_drvdata(pdev, mmc); @@ -1042,18 +1062,20 @@ static int imxmci_probe(struct platform_device *pdev) out: if (host) { - if(host->dma_allocated){ + if (host->dma_allocated) { imx_dma_free(host->dma); - host->dma_allocated=0; + host->dma_allocated = 0; } if (host->clk) { clk_disable(host->clk); clk_put(host->clk); } + if (host->base) + iounmap(host->base); } if (mmc) mmc_free_host(mmc); - release_mem_region(r->start, 0x100); + release_mem_region(r->start, resource_size(r)); return ret; } @@ -1072,9 +1094,10 @@ static int imxmci_remove(struct platform_device *pdev) mmc_remove_host(mmc); free_irq(host->irq, host); - if(host->dma_allocated){ + iounmap(host->base); + if (host->dma_allocated) { imx_dma_free(host->dma); - host->dma_allocated=0; + host->dma_allocated = 0; } tasklet_kill(&host->tasklet); @@ -1082,7 +1105,7 @@ static int imxmci_remove(struct platform_device *pdev) clk_disable(host->clk); clk_put(host->clk); - release_mem_region(host->res->start, 0x100); + release_mem_region(host->res->start, resource_size(host->res)); mmc_free_host(mmc); } @@ -1109,7 +1132,7 @@ static int imxmci_resume(struct platform_device *dev) if (mmc) { host = mmc_priv(mmc); - if(host) + if (host) set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events); ret = mmc_resume_host(mmc); } diff --git a/drivers/mmc/host/imxmmc.h b/drivers/mmc/host/imxmmc.h index e5339e334dbb..09d5d4ee3a77 100644 --- a/drivers/mmc/host/imxmmc.h +++ b/drivers/mmc/host/imxmmc.h @@ -1,24 +1,21 @@ +#define MMC_REG_STR_STP_CLK 0x00 +#define MMC_REG_STATUS 0x04 +#define MMC_REG_CLK_RATE 0x08 +#define MMC_REG_CMD_DAT_CONT 0x0C +#define MMC_REG_RES_TO 0x10 +#define MMC_REG_READ_TO 0x14 +#define MMC_REG_BLK_LEN 0x18 +#define MMC_REG_NOB 0x1C +#define MMC_REG_REV_NO 0x20 +#define MMC_REG_INT_MASK 0x24 +#define MMC_REG_CMD 0x28 +#define MMC_REG_ARGH 0x2C +#define MMC_REG_ARGL 0x30 +#define MMC_REG_RES_FIFO 0x34 +#define MMC_REG_BUFFER_ACCESS 0x38 -# define __REG16(x) (*((volatile u16 *)IO_ADDRESS(x))) - -#define MMC_STR_STP_CLK __REG16(IMX_MMC_BASE + 0x00) -#define MMC_STATUS __REG16(IMX_MMC_BASE + 0x04) -#define MMC_CLK_RATE __REG16(IMX_MMC_BASE + 0x08) -#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C) -#define MMC_RES_TO __REG16(IMX_MMC_BASE + 0x10) -#define MMC_READ_TO __REG16(IMX_MMC_BASE + 0x14) -#define MMC_BLK_LEN __REG16(IMX_MMC_BASE + 0x18) -#define MMC_NOB __REG16(IMX_MMC_BASE + 0x1C) -#define MMC_REV_NO __REG16(IMX_MMC_BASE + 0x20) -#define MMC_INT_MASK __REG16(IMX_MMC_BASE + 0x24) -#define MMC_CMD __REG16(IMX_MMC_BASE + 0x28) -#define MMC_ARGH __REG16(IMX_MMC_BASE + 0x2C) -#define MMC_ARGL __REG16(IMX_MMC_BASE + 0x30) -#define MMC_RES_FIFO __REG16(IMX_MMC_BASE + 0x34) -#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38) -#define MMC_BUFFER_ACCESS_OFS 0x38 - - +#define STR_STP_CLK_IPG_CLK_GATE_DIS (1<<15) +#define STR_STP_CLK_IPG_PERCLK_GATE_DIS (1<<14) #define STR_STP_CLK_ENDIAN (1<<5) #define STR_STP_CLK_RESET (1<<3) #define STR_STP_CLK_ENABLE (1<<2) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2fadf323c696..1bcbdd6763ac 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -500,7 +500,7 @@ static int mmci_probe(struct amba_device *dev, void *id) } host = mmc_priv(mmc); - host->clk = clk_get(&dev->dev, "MCLK"); + host->clk = clk_get(&dev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); host->clk = NULL; diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 1b9fc3c6b875..67d7b7fef084 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1015,7 +1015,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data } if (is_read) { - if (host->id == 1) { + if (host->id == 0) { sync_dev = OMAP_DMA_MMC_RX; dma_dev_name = "MMC1 read"; } else { @@ -1023,7 +1023,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data dma_dev_name = "MMC2 read"; } } else { - if (host->id == 1) { + if (host->id == 0) { sync_dev = OMAP_DMA_MMC_TX; dma_dev_name = "MMC1 write"; } else { @@ -1317,7 +1317,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) host->slots[id] = slot; mmc->caps = 0; - if (host->pdata->conf.wire4) + if (host->pdata->slots[id].wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; mmc->ops = &mmc_omap_ops; @@ -1451,6 +1451,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->irq = irq; host->use_dma = 1; + host->dev->dma_mask = &pdata->dma_mask; host->dma_ch = -1; host->irq = irq; diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index ebfaa9960939..f88cc7406354 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -26,11 +26,12 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/mmc/host.h> +#include <linux/io.h> -#include <asm/dma.h> -#include <asm/io.h> #include <asm/sizes.h> +#include <mach/dma.h> +#include <mach/hardware.h> #include <mach/pxa-regs.h> #include <mach/mmc.h> @@ -533,7 +534,7 @@ static int pxamci_probe(struct platform_device *pdev) host->pdata = pdev->dev.platform_data; host->clkrt = CLKRT_OFF; - host->clk = clk_get(&pdev->dev, "MMCCLK"); + host->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); host->clk = NULL; diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 3b2085b57769..fcc98a4cce3c 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -25,7 +25,7 @@ #include <mach/regs-sdi.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c24xx/mci.h> +#include <plat/mci.h> #include "s3cmci.h" diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index 3aa018c092f8..42969fe051b2 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -32,16 +32,15 @@ static struct mtd_info *dc21285_mtd; */ static void nw_en_write(void) { - extern spinlock_t gpio_lock; unsigned long flags; /* * we want to write a bit pattern XXX1 to Xilinx to enable * the write gate, which will be open for about the next 2ms. */ - spin_lock_irqsave(&gpio_lock, flags); - cpld_modify(1, 1); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); + spin_unlock_irqrestore(&nw_gpio_lock, flags); /* * let the ISA bus to catch on... diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index dcdb1f17577d..3ea1de9be720 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -170,7 +170,7 @@ static int ixp2000_flash_probe(struct platform_device *dev) err = -ENOMEM; goto Error; } - memzero(info, sizeof(struct ixp2000_flash_info)); + memset(info, 0, sizeof(struct ixp2000_flash_info)); platform_set_drvdata(dev, info); diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 9c7a5fbd4e51..16555cbeaea4 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -201,7 +201,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev) err = -ENOMEM; goto Error; } - memzero(info, sizeof(struct ixp4xx_flash_info)); + memset(info, 0, sizeof(struct ixp4xx_flash_info)); platform_set_drvdata(dev, info); diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1c2e9450d663..f8ae0400c49c 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -408,7 +408,7 @@ config MTD_NAND_FSL_UPM config MTD_NAND_MXC tristate "MXC NAND support" - depends on ARCH_MX2 + depends on ARCH_MX2 || ARCH_MX3 help This enables the driver for the NAND flash controller on the MXC processors. diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 15f0a26730ae..fc4144495610 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -20,8 +20,8 @@ #include <linux/mtd/partitions.h> #include <linux/io.h> #include <linux/irq.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/pxa-regs.h> #include <mach/pxa3xx_nand.h> @@ -1080,7 +1080,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) this = &info->nand_chip; mtd->priv = info; - info->clk = clk_get(&pdev->dev, "NANDCLK"); + info->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); ret = PTR_ERR(info->clk); diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 556139ed1fdf..8e375d5fe231 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -45,8 +45,8 @@ #include <asm/io.h> -#include <asm/plat-s3c/regs-nand.h> -#include <asm/plat-s3c/nand.h> +#include <plat/regs-nand.h> +#include <plat/nand.h> #ifdef CONFIG_MTD_NAND_S3C2410_HWECC static int hardware_ecc = 1; @@ -818,7 +818,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, goto exit_error; } - memzero(info, sizeof(*info)); + memset(info, 0, sizeof(*info)); platform_set_drvdata(pdev, info); spin_lock_init(&info->controller.lock); @@ -883,7 +883,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, goto exit_error; } - memzero(info->mtds, size); + memset(info->mtds, 0, size); /* initialise all possible chips */ diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index a7e4d985f5ef..d1e0b8e7224b 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -149,7 +149,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) INIT_COMPLETION(c->irq_done); if (c->gpio_irq) { - result = omap_get_gpio_datain(c->gpio_irq); + result = gpio_get_value(c->gpio_irq); if (result == -1) { ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); intr = read_reg(c, ONENAND_REG_INTERRUPT); @@ -634,9 +634,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) "OneNAND\n", c->gpio_irq); goto err_iounmap; } - omap_set_gpio_direction(c->gpio_irq, 1); + gpio_direction_input(c->gpio_irq); - if ((r = request_irq(OMAP_GPIO_IRQ(c->gpio_irq), + if ((r = request_irq(gpio_to_irq(c->gpio_irq), omap2_onenand_interrupt, IRQF_TRIGGER_RISING, pdev->dev.driver->name, c)) < 0) goto err_release_gpio; @@ -723,7 +723,7 @@ err_release_dma: if (c->dma_channel != -1) omap_free_dma(c->dma_channel); if (c->gpio_irq) - free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c); + free_irq(gpio_to_irq(c->gpio_irq), c); err_release_gpio: if (c->gpio_irq) omap_free_gpio(c->gpio_irq); @@ -760,7 +760,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) omap2_onenand_shutdown(pdev); platform_set_drvdata(pdev, NULL); if (c->gpio_irq) { - free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c); + free_irq(gpio_to_irq(c->gpio_irq), c); omap_free_gpio(c->gpio_irq); } iounmap(c->onenand.base); diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 6ecc600c1bcc..3ec20cc18b0c 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -307,7 +307,7 @@ poll_some_more: } spin_unlock_irq(&ep->rx_lock); - if (more && netif_rx_reschedule(dev, napi)) + if (more && netif_rx_reschedule(napi)) goto poll_some_more; } diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 26af411fc428..5fce1d5c1a1a 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -504,7 +504,7 @@ static int eth_poll(struct napi_struct *napi, int budget) netif_rx_complete(napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && - netif_rx_reschedule(dev, napi)) { + netif_rx_reschedule(napi)) { #if DEBUG_RX printk(KERN_DEBUG "%s: eth_poll" " netif_rx_reschedule successed\n", diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 592daee9dc28..9ad22d1b00fd 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -29,7 +29,6 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/irq.h> -#include <linux/delay.h> #include <linux/io.h> #include <asm/irq.h> diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index d548a45d59d5..ff6497658a45 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -170,11 +170,7 @@ static char version[] __initdata = /* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps them to system IRQ numbers. This mapping is card specific and is set to the configuration of the Cirrus Eval board for this chip. */ -#ifdef CONFIG_ARCH_CLPS7500 -static unsigned int netcard_portlist[] __used __initdata = - { 0x80090303, 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; -static unsigned int cs8900_irq_map[] = {12,0,0,0}; -#elif defined(CONFIG_SH_HICOSH4) +#if defined(CONFIG_SH_HICOSH4) static unsigned int netcard_portlist[] __used __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; diff --git a/drivers/net/eexpress.h b/drivers/net/eexpress.h index 707df3fcfe40..dc9c6ea289e9 100644 --- a/drivers/net/eexpress.h +++ b/drivers/net/eexpress.h @@ -68,17 +68,17 @@ */ /* these functions take the SCB status word and test the relevant status bit */ -#define SCB_complete(s) ((s&0x8000)!=0) -#define SCB_rxdframe(s) ((s&0x4000)!=0) -#define SCB_CUdead(s) ((s&0x2000)!=0) -#define SCB_RUdead(s) ((s&0x1000)!=0) -#define SCB_ack(s) (s & 0xf000) +#define SCB_complete(s) (((s) & 0x8000) != 0) +#define SCB_rxdframe(s) (((s) & 0x4000) != 0) +#define SCB_CUdead(s) (((s) & 0x2000) != 0) +#define SCB_RUdead(s) (((s) & 0x1000) != 0) +#define SCB_ack(s) ((s) & 0xf000) /* Command unit status: 0=idle, 1=suspended, 2=active */ -#define SCB_CUstat(s) ((s&0x0300)>>8) +#define SCB_CUstat(s) (((s)&0x0300)>>8) /* Receive unit status: 0=idle, 1=suspended, 2=out of resources, 4=ready */ -#define SCB_RUstat(s) ((s&0x0070)>>4) +#define SCB_RUstat(s) (((s)&0x0070)>>4) /* SCB commands */ #define SCB_CUnop 0x0000 @@ -98,18 +98,18 @@ * Command block defines */ -#define Stat_Done(s) ((s&0x8000)!=0) -#define Stat_Busy(s) ((s&0x4000)!=0) -#define Stat_OK(s) ((s&0x2000)!=0) -#define Stat_Abort(s) ((s&0x1000)!=0) -#define Stat_STFail ((s&0x0800)!=0) -#define Stat_TNoCar(s) ((s&0x0400)!=0) -#define Stat_TNoCTS(s) ((s&0x0200)!=0) -#define Stat_TNoDMA(s) ((s&0x0100)!=0) -#define Stat_TDefer(s) ((s&0x0080)!=0) -#define Stat_TColl(s) ((s&0x0040)!=0) -#define Stat_TXColl(s) ((s&0x0020)!=0) -#define Stat_NoColl(s) (s&0x000f) +#define Stat_Done(s) (((s) & 0x8000) != 0) +#define Stat_Busy(s) (((s) & 0x4000) != 0) +#define Stat_OK(s) (((s) & 0x2000) != 0) +#define Stat_Abort(s) (((s) & 0x1000) != 0) +#define Stat_STFail (((s) & 0x0800) != 0) +#define Stat_TNoCar(s) (((s) & 0x0400) != 0) +#define Stat_TNoCTS(s) (((s) & 0x0200) != 0) +#define Stat_TNoDMA(s) (((s) & 0x0100) != 0) +#define Stat_TDefer(s) (((s) & 0x0080) != 0) +#define Stat_TColl(s) (((s) & 0x0040) != 0) +#define Stat_TXColl(s) (((s) & 0x0020) != 0) +#define Stat_NoColl(s) ((s) & 0x000f) /* Cmd_END will end AFTER the command if this is the first * command block after an SCB_CUstart, but BEFORE the command @@ -136,16 +136,16 @@ * Frame Descriptor (Receive block) defines */ -#define FD_Done(s) ((s&0x8000)!=0) -#define FD_Busy(s) ((s&0x4000)!=0) -#define FD_OK(s) ((s&0x2000)!=0) +#define FD_Done(s) (((s) & 0x8000) != 0) +#define FD_Busy(s) (((s) & 0x4000) != 0) +#define FD_OK(s) (((s) & 0x2000) != 0) -#define FD_CRC(s) ((s&0x0800)!=0) -#define FD_Align(s) ((s&0x0400)!=0) -#define FD_Resrc(s) ((s&0x0200)!=0) -#define FD_DMA(s) ((s&0x0100)!=0) -#define FD_Short(s) ((s&0x0080)!=0) -#define FD_NoEOF(s) ((s&0x0040)!=0) +#define FD_CRC(s) (((s) & 0x0800) != 0) +#define FD_Align(s) (((s) & 0x0400) != 0) +#define FD_Resrc(s) (((s) & 0x0200) != 0) +#define FD_DMA(s) (((s) & 0x0100) != 0) +#define FD_Short(s) (((s) & 0x0080) != 0) +#define FD_NoEOF(s) (((s) & 0x0040) != 0) struct rfd_header { volatile unsigned long flags; diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index a0ee05318155..004a9aab3a50 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -22,9 +22,53 @@ #include <net/irda/wrapper.h> #include <net/irda/irda_device.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/irda.h> +#include <mach/hardware.h> #include <mach/pxa-regs.h> +#include <mach/regs-uart.h> + +#define FICP __REG(0x40800000) /* Start of FICP area */ +#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */ +#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */ +#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */ +#define ICDR __REG(0x4080000c) /* ICP Data Register */ +#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */ +#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */ + +#define ICCR0_AME (1 << 7) /* Address match enable */ +#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */ +#define ICCR0_RIE (1 << 5) /* Recieve FIFO interrupt enable */ +#define ICCR0_RXE (1 << 4) /* Receive enable */ +#define ICCR0_TXE (1 << 3) /* Transmit enable */ +#define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */ +#define ICCR0_LBM (1 << 1) /* Loopback mode */ +#define ICCR0_ITR (1 << 0) /* IrDA transmission */ + +#define ICCR2_RXP (1 << 3) /* Receive Pin Polarity select */ +#define ICCR2_TXP (1 << 2) /* Transmit Pin Polarity select */ +#define ICCR2_TRIG (3 << 0) /* Receive FIFO Trigger threshold */ +#define ICCR2_TRIG_8 (0 << 0) /* >= 8 bytes */ +#define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */ +#define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */ + +#ifdef CONFIG_PXA27x +#define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */ +#endif +#define ICSR0_FRE (1 << 5) /* Framing error */ +#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */ +#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */ +#define ICSR0_RAB (1 << 2) /* Receiver abort */ +#define ICSR0_TUR (1 << 1) /* Trunsmit FIFO underun */ +#define ICSR0_EIF (1 << 0) /* End/Error in FIFO */ + +#define ICSR1_ROR (1 << 6) /* Receiver FIFO underrun */ +#define ICSR1_CRE (1 << 5) /* CRC error */ +#define ICSR1_EOF (1 << 4) /* End of frame */ +#define ICSR1_TNF (1 << 3) /* Transmit FIFO not full */ +#define ICSR1_RNE (1 << 2) /* Receive FIFO not empty */ +#define ICSR1_TBY (1 << 1) /* Tramsmiter busy flag */ +#define ICSR1_RSY (1 << 0) /* Recevier synchronized flag */ #define IrSR_RXPL_NEG_IS_ZERO (1<<4) #define IrSR_RXPL_POS_IS_ZERO 0x0 diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index ccde5829ba21..d302bcf4c148 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -36,7 +36,7 @@ #include <net/irda/irda_device.h> #include <asm/irq.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/hardware.h> #include <asm/mach/irda.h> diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index c1c05852a95e..eda72dd2120f 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -169,13 +169,10 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { mlx4_info(mdev, "Using %d tx rings for port:%d\n", mdev->profile.prof[i].tx_ring_num, i); - if (!mdev->profile.prof[i].rx_ring_num) { - mdev->profile.prof[i].rx_ring_num = dev->caps.num_comp_vectors; - mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", - mdev->profile.prof[i].rx_ring_num, i); - } else - mlx4_info(mdev, "Using %d rx rings for port:%d\n", - mdev->profile.prof[i].rx_ring_num, i); + mdev->profile.prof[i].rx_ring_num = + min_t(int, dev->caps.num_comp_vectors, MAX_RX_RINGS); + mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", + mdev->profile.prof[i].rx_ring_num, i); } /* Create our own workqueue for reset/multicast tasks diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index ebada3c7aff2..15bb38d99304 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -552,7 +552,7 @@ static void mlx4_en_linkstate(struct work_struct *work) } -static int mlx4_en_start_port(struct net_device *dev) +int mlx4_en_start_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -707,7 +707,7 @@ cq_err: } -static void mlx4_en_stop_port(struct net_device *dev) +void mlx4_en_stop_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -826,7 +826,7 @@ static int mlx4_en_close(struct net_device *dev) return 0; } -static void mlx4_en_free_resources(struct mlx4_en_priv *priv) +void mlx4_en_free_resources(struct mlx4_en_priv *priv) { int i; @@ -845,7 +845,7 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv) } } -static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) +int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_port_profile *prof = priv->prof; diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c index 047b37f5a747..cfeef0f1bacc 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_params.c @@ -65,15 +65,6 @@ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]." " Per priority bit mask"); -MLX4_EN_PARM_INT(rx_ring_num1, 0, "Number or Rx rings for port 1 (0 = #cores)"); -MLX4_EN_PARM_INT(rx_ring_num2, 0, "Number or Rx rings for port 2 (0 = #cores)"); - -MLX4_EN_PARM_INT(tx_ring_size1, MLX4_EN_AUTO_CONF, "Tx ring size for port 1"); -MLX4_EN_PARM_INT(tx_ring_size2, MLX4_EN_AUTO_CONF, "Tx ring size for port 2"); -MLX4_EN_PARM_INT(rx_ring_size1, MLX4_EN_AUTO_CONF, "Rx ring size for port 1"); -MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); - - int mlx4_en_get_profile(struct mlx4_en_dev *mdev) { struct mlx4_en_profile *params = &mdev->profile; @@ -87,6 +78,8 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[i].rx_ppp = pfcrx; params->prof[i].tx_pause = 1; params->prof[i].tx_ppp = pfctx; + params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; + params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; } if (pfcrx || pfctx) { params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; @@ -95,32 +88,7 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[1].tx_ring_num = 1; params->prof[2].tx_ring_num = 1; } - params->prof[1].rx_ring_num = min_t(int, rx_ring_num1, MAX_RX_RINGS); - params->prof[2].rx_ring_num = min_t(int, rx_ring_num2, MAX_RX_RINGS); - - if (tx_ring_size1 == MLX4_EN_AUTO_CONF) - tx_ring_size1 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[1].tx_ring_size = - (tx_ring_size1 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size1); - - if (tx_ring_size2 == MLX4_EN_AUTO_CONF) - tx_ring_size2 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[2].tx_ring_size = - (tx_ring_size2 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size2); - - if (rx_ring_size1 == MLX4_EN_AUTO_CONF) - rx_ring_size1 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[1].rx_ring_size = - (rx_ring_size1 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size1); - - if (rx_ring_size2 == MLX4_EN_AUTO_CONF) - rx_ring_size2 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[2].rx_ring_size = - (rx_ring_size2 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size2); + return 0; } @@ -417,6 +385,54 @@ static void mlx4_en_get_pauseparam(struct net_device *dev, pause->rx_pause = priv->prof->rx_pause; } +static int mlx4_en_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + u32 rx_size, tx_size; + int port_up = 0; + int err = 0; + + if (param->rx_jumbo_pending || param->rx_mini_pending) + return -EINVAL; + + rx_size = roundup_pow_of_two(param->rx_pending); + rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE); + tx_size = roundup_pow_of_two(param->tx_pending); + tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE); + + if (rx_size == priv->prof->rx_ring_size && + tx_size == priv->prof->tx_ring_size) + return 0; + + mutex_lock(&mdev->state_lock); + if (priv->port_up) { + port_up = 1; + mlx4_en_stop_port(dev); + } + + mlx4_en_free_resources(priv); + + priv->prof->tx_ring_size = tx_size; + priv->prof->rx_ring_size = rx_size; + + err = mlx4_en_alloc_resources(priv); + if (err) { + mlx4_err(mdev, "Failed reallocating port resources\n"); + goto out; + } + if (port_up) { + err = mlx4_en_start_port(dev); + if (err) + mlx4_err(mdev, "Failed starting port\n"); + } + +out: + mutex_unlock(&mdev->state_lock); + return err; +} + static void mlx4_en_get_ringparam(struct net_device *dev, struct ethtool_ringparam *param) { @@ -456,6 +472,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_pauseparam = mlx4_en_get_pauseparam, .set_pauseparam = mlx4_en_set_pauseparam, .get_ringparam = mlx4_en_get_ringparam, + .set_ringparam = mlx4_en_set_ringparam, .get_flags = ethtool_op_get_flags, .set_flags = ethtool_op_set_flags, }; diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index e78209768def..2e96c7b2180a 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -489,6 +489,12 @@ void mlx4_en_destroy_netdev(struct net_device *dev); int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, struct mlx4_en_port_profile *prof); +int mlx4_en_start_port(struct net_device *dev); +void mlx4_en_stop_port(struct net_device *dev); + +void mlx4_en_free_resources(struct mlx4_en_priv *priv); +int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); + int mlx4_en_get_profile(struct mlx4_en_dev *mdev); int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index dcd199045613..5b7a574ce571 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -954,7 +954,6 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) { const struct pasemi_mac_rxring *rxring = data; struct pasemi_mac *mac = rxring->mac; - struct net_device *dev = mac->netdev; const struct pasemi_dmachan *chan = &rxring->chan; unsigned int reg; @@ -1634,7 +1633,6 @@ static void pasemi_mac_set_rx_mode(struct net_device *dev) static int pasemi_mac_poll(struct napi_struct *napi, int budget) { struct pasemi_mac *mac = container_of(napi, struct pasemi_mac, napi); - struct net_device *dev = mac->netdev; int pkts; pasemi_mac_clean_tx(tx_ring(mac)); diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index cc7d85bdfb3e..870b4c33f108 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -200,6 +200,9 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg, #ifdef SMC_USE_PXA_DMA + +#include <mach/dma.h> + /* * Define the request and free functions * These are unfortunately architecture specific as no generic allocation diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 3e7c6a3cbc65..c4ccd121bc9c 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -493,7 +493,8 @@ struct smc_local { * as RX which can overrun memory and lose packets. */ #include <linux/dma-mapping.h> -#include <asm/dma.h> +#include <mach/dma.h> +#include <mach/hardware.h> #include <mach/pxa-regs.h> #ifdef SMC_insl diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 5e989d884ddd..dc3f1108884d 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1484,13 +1484,13 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) } if (likely(intsts & inten & INT_STS_RSFL_)) { - if (likely(netif_rx_schedule_prep(dev, &pdata->napi))) { + if (likely(netif_rx_schedule_prep(&pdata->napi))) { /* Disable Rx interrupts */ temp = smsc911x_reg_read(pdata, INT_EN); temp &= (~INT_EN_RSFL_EN_); smsc911x_reg_write(pdata, INT_EN, temp); /* Schedule a NAPI poll */ - __netif_rx_schedule(dev, &pdata->napi); + __netif_rx_schedule(&pdata->napi); } else { SMSC_WARNING(RX_ERR, "netif_rx_schedule_prep failed"); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index c5c123d3af57..88d2c67788df 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1277,7 +1277,6 @@ bad_desc: static int spider_net_poll(struct napi_struct *napi, int budget) { struct spider_net_card *card = container_of(napi, struct spider_net_card, napi); - struct net_device *netdev = card->netdev; int packets_done = 0; while (packets_done < budget) { diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 666c1d98cdaf..69f9a0ec764d 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -343,7 +343,7 @@ static void tun_net_init(struct net_device *dev) break; case TUN_TAP_DEV: - dev->netdev_ops = &tun_netdev_ops; + dev->netdev_ops = &tap_netdev_ops; /* Ethernet TAP Device */ ether_setup(dev); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 198ce3cf378a..9f7896a25f1b 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2831,7 +2831,7 @@ static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf, for (i = 0; i < iface->desc.bNumEndpoints; i++) { endp = &iface->endpoint[i].desc; if (((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir) && - ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type)) + (usb_endpoint_type(endp) == type)) return endp; } diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 0c6802507a79..2dc241689d37 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -654,7 +654,7 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget) netif_rx_complete(dev, napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && - netif_rx_reschedule(dev, napi)) { + netif_rx_reschedule(napi)) { #if DEBUG_RX printk(KERN_DEBUG "%s: hss_hdlc_poll" " netif_rx_reschedule succeeded\n", diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 04c139666965..b5db57d2fcf5 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1065,8 +1065,7 @@ static int eject_installer(struct usb_interface *intf) /* Find bulk out endpoint */ endpoint = &iface_desc->endpoint[1].desc; if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && - (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK) { + usb_endpoint_xfer_bulk(endpoint)) { bulk_out_ep = endpoint->bEndpointAddress; } else { dev_err(&udev->dev, diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index b55cd23ffdef..737bd9484822 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -268,18 +268,6 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) return cookie; } -static void increment_tail(struct oprofile_cpu_buffer *b) -{ - unsigned long new_tail = b->tail_pos + 1; - - rmb(); /* be sure fifo pointers are synchromized */ - - if (new_tail < b->buffer_size) - b->tail_pos = new_tail; - else - b->tail_pos = 0; -} - static unsigned long last_cookie = INVALID_COOKIE; static void add_cpu_switch(int i) @@ -331,28 +319,25 @@ static void add_trace_begin(void) #define IBS_FETCH_CODE_SIZE 2 #define IBS_OP_CODE_SIZE 5 -#define IBS_EIP(offset) \ - (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip) -#define IBS_EVENT(offset) \ - (((struct op_sample *)&cpu_buf->buffer[(offset)])->event) /* * Add IBS fetch and op entries to event buffer */ -static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, - struct mm_struct *mm) +static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) { unsigned long rip; int i, count; unsigned long ibs_cookie = 0; off_t offset; + struct op_sample *sample; - increment_tail(cpu_buf); /* move to RIP entry */ - - rip = IBS_EIP(cpu_buf->tail_pos); + sample = cpu_buffer_read_entry(cpu); + if (!sample) + goto Error; + rip = sample->eip; #ifdef __LP64__ - rip += IBS_EVENT(cpu_buf->tail_pos) << 32; + rip += sample->event << 32; #endif if (mm) { @@ -376,8 +361,8 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, add_event_entry(offset); /* Offset from Dcookie */ /* we send the Dcookie offset, but send the raw Linear Add also*/ - add_event_entry(IBS_EIP(cpu_buf->tail_pos)); - add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); + add_event_entry(sample->eip); + add_event_entry(sample->event); if (code == IBS_FETCH_CODE) count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ @@ -385,10 +370,17 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ for (i = 0; i < count; i++) { - increment_tail(cpu_buf); - add_event_entry(IBS_EIP(cpu_buf->tail_pos)); - add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); + sample = cpu_buffer_read_entry(cpu); + if (!sample) + goto Error; + add_event_entry(sample->eip); + add_event_entry(sample->event); } + + return; + +Error: + return; } #endif @@ -466,33 +458,6 @@ static inline int is_code(unsigned long val) } -/* "acquire" as many cpu buffer slots as we can */ -static unsigned long get_slots(struct oprofile_cpu_buffer *b) -{ - unsigned long head = b->head_pos; - unsigned long tail = b->tail_pos; - - /* - * Subtle. This resets the persistent last_task - * and in_kernel values used for switching notes. - * BUT, there is a small window between reading - * head_pos, and this call, that means samples - * can appear at the new head position, but not - * be prefixed with the notes for switching - * kernel mode or a task switch. This small hole - * can lead to mis-attribution or samples where - * we don't know if it's in the kernel or not, - * at the start of an event buffer. - */ - cpu_buffer_reset(b); - - if (head >= tail) - return head - tail; - - return head + (b->buffer_size - tail); -} - - /* Move tasks along towards death. Any tasks on dead_tasks * will definitely have no remaining references in any * CPU buffers at this point, because we use two lists, @@ -559,61 +524,61 @@ typedef enum { */ void sync_buffer(int cpu) { - struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); struct mm_struct *mm = NULL; + struct mm_struct *oldmm; struct task_struct *new; unsigned long cookie = 0; int in_kernel = 1; sync_buffer_state state = sb_buffer_start; -#ifndef CONFIG_OPROFILE_IBS unsigned int i; unsigned long available; -#endif mutex_lock(&buffer_mutex); add_cpu_switch(cpu); - /* Remember, only we can modify tail_pos */ - -#ifndef CONFIG_OPROFILE_IBS - available = get_slots(cpu_buf); + cpu_buffer_reset(cpu); + available = cpu_buffer_entries(cpu); for (i = 0; i < available; ++i) { -#else - while (get_slots(cpu_buf)) { -#endif - struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos]; + struct op_sample *s = cpu_buffer_read_entry(cpu); + if (!s) + break; if (is_code(s->eip)) { - if (s->event <= CPU_IS_KERNEL) { + switch (s->event) { + case 0: + case CPU_IS_KERNEL: /* kernel/userspace switch */ in_kernel = s->event; if (state == sb_buffer_start) state = sb_sample_start; add_kernel_ctx_switch(s->event); - } else if (s->event == CPU_TRACE_BEGIN) { + break; + case CPU_TRACE_BEGIN: state = sb_bt_start; add_trace_begin(); + break; #ifdef CONFIG_OPROFILE_IBS - } else if (s->event == IBS_FETCH_BEGIN) { + case IBS_FETCH_BEGIN: state = sb_bt_start; - add_ibs_begin(cpu_buf, IBS_FETCH_CODE, mm); - } else if (s->event == IBS_OP_BEGIN) { + add_ibs_begin(cpu, IBS_FETCH_CODE, mm); + break; + case IBS_OP_BEGIN: state = sb_bt_start; - add_ibs_begin(cpu_buf, IBS_OP_CODE, mm); + add_ibs_begin(cpu, IBS_OP_CODE, mm); + break; #endif - } else { - struct mm_struct *oldmm = mm; - + default: /* userspace context switch */ + oldmm = mm; new = (struct task_struct *)s->event; - release_mm(oldmm); mm = take_tasks_mm(new); if (mm != oldmm) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); + break; } } else if (state >= sb_bt_start && !add_sample(mm, s, in_kernel)) { @@ -622,8 +587,6 @@ void sync_buffer(int cpu) atomic_inc(&oprofile_stats.bt_lost_no_mapping); } } - - increment_tail(cpu_buf); } release_mm(mm); diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 01d38e78cde1..61090969158f 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -28,6 +28,25 @@ #include "buffer_sync.h" #include "oprof.h" +#define OP_BUFFER_FLAGS 0 + +/* + * Read and write access is using spin locking. Thus, writing to the + * buffer by NMI handler (x86) could occur also during critical + * sections when reading the buffer. To avoid this, there are 2 + * buffers for independent read and write access. Read access is in + * process context only, write access only in the NMI handler. If the + * read buffer runs empty, both buffers are swapped atomically. There + * is potentially a small window during swapping where the buffers are + * disabled and samples could be lost. + * + * Using 2 buffers is a little bit overhead, but the solution is clear + * and does not require changes in the ring buffer implementation. It + * can be changed to a single buffer solution when the ring buffer + * access is implemented as non-locking atomic code. + */ +struct ring_buffer *op_ring_buffer_read; +struct ring_buffer *op_ring_buffer_write; DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); static void wq_sync_buffer(struct work_struct *work); @@ -37,12 +56,12 @@ static int work_enabled; void free_cpu_buffers(void) { - int i; - - for_each_possible_cpu(i) { - vfree(per_cpu(cpu_buffer, i).buffer); - per_cpu(cpu_buffer, i).buffer = NULL; - } + if (op_ring_buffer_read) + ring_buffer_free(op_ring_buffer_read); + op_ring_buffer_read = NULL; + if (op_ring_buffer_write) + ring_buffer_free(op_ring_buffer_write); + op_ring_buffer_write = NULL; } unsigned long oprofile_get_cpu_buffer_size(void) @@ -64,14 +83,16 @@ int alloc_cpu_buffers(void) unsigned long buffer_size = fs_cpu_buffer_size; + op_ring_buffer_read = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS); + if (!op_ring_buffer_read) + goto fail; + op_ring_buffer_write = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS); + if (!op_ring_buffer_write) + goto fail; + for_each_possible_cpu(i) { struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); - b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size, - cpu_to_node(i)); - if (!b->buffer) - goto fail; - b->last_task = NULL; b->last_is_kernel = -1; b->tracing = 0; @@ -124,57 +145,31 @@ void end_cpu_work(void) flush_scheduled_work(); } -/* Resets the cpu buffer to a sane state. */ -void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf) -{ - /* reset these to invalid values; the next sample - * collected will populate the buffer with proper - * values to initialize the buffer - */ - cpu_buf->last_is_kernel = -1; - cpu_buf->last_task = NULL; -} - -/* compute number of available slots in cpu_buffer queue */ -static unsigned long nr_available_slots(struct oprofile_cpu_buffer const *b) +static inline int +add_sample(struct oprofile_cpu_buffer *cpu_buf, + unsigned long pc, unsigned long event) { - unsigned long head = b->head_pos; - unsigned long tail = b->tail_pos; + struct op_entry entry; + int ret; - if (tail > head) - return (tail - head) - 1; + ret = cpu_buffer_write_entry(&entry); + if (ret) + return ret; - return tail + (b->buffer_size - head) - 1; -} + entry.sample->eip = pc; + entry.sample->event = event; -static void increment_head(struct oprofile_cpu_buffer *b) -{ - unsigned long new_head = b->head_pos + 1; - - /* Ensure anything written to the slot before we - * increment is visible */ - wmb(); - - if (new_head < b->buffer_size) - b->head_pos = new_head; - else - b->head_pos = 0; -} + ret = cpu_buffer_write_commit(&entry); + if (ret) + return ret; -static inline void -add_sample(struct oprofile_cpu_buffer *cpu_buf, - unsigned long pc, unsigned long event) -{ - struct op_sample *entry = &cpu_buf->buffer[cpu_buf->head_pos]; - entry->eip = pc; - entry->event = event; - increment_head(cpu_buf); + return 0; } -static inline void +static inline int add_code(struct oprofile_cpu_buffer *buffer, unsigned long value) { - add_sample(buffer, ESCAPE_CODE, value); + return add_sample(buffer, ESCAPE_CODE, value); } /* This must be safe from any context. It's safe writing here @@ -198,11 +193,6 @@ static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, return 0; } - if (nr_available_slots(cpu_buf) < 3) { - cpu_buf->sample_lost_overflow++; - return 0; - } - is_kernel = !!is_kernel; task = current; @@ -210,26 +200,29 @@ static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, /* notice a switch from user->kernel or vice versa */ if (cpu_buf->last_is_kernel != is_kernel) { cpu_buf->last_is_kernel = is_kernel; - add_code(cpu_buf, is_kernel); + if (add_code(cpu_buf, is_kernel)) + goto fail; } /* notice a task switch */ if (cpu_buf->last_task != task) { cpu_buf->last_task = task; - add_code(cpu_buf, (unsigned long)task); + if (add_code(cpu_buf, (unsigned long)task)) + goto fail; } - add_sample(cpu_buf, pc, event); + if (add_sample(cpu_buf, pc, event)) + goto fail; + return 1; + +fail: + cpu_buf->sample_lost_overflow++; + return 0; } static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) { - if (nr_available_slots(cpu_buf) < 4) { - cpu_buf->sample_lost_overflow++; - return 0; - } - add_code(cpu_buf, CPU_TRACE_BEGIN); cpu_buf->tracing = 1; return 1; @@ -253,8 +246,10 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, if (!oprofile_begin_trace(cpu_buf)) return; - /* if log_sample() fail we can't backtrace since we lost the source - * of this event */ + /* + * if log_sample() fail we can't backtrace since we lost the + * source of this event + */ if (log_sample(cpu_buf, pc, is_kernel, event)) oprofile_ops.backtrace(regs, backtrace_depth); oprofile_end_trace(cpu_buf); @@ -272,49 +267,55 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) #define MAX_IBS_SAMPLE_SIZE 14 -void oprofile_add_ibs_sample(struct pt_regs *const regs, - unsigned int *const ibs_sample, int ibs_code) +void oprofile_add_ibs_sample(struct pt_regs * const regs, + unsigned int * const ibs_sample, int ibs_code) { int is_kernel = !user_mode(regs); struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); struct task_struct *task; + int fail = 0; cpu_buf->sample_received++; - if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) { - /* we can't backtrace since we lost the source of this event */ - cpu_buf->sample_lost_overflow++; - return; - } - /* notice a switch from user->kernel or vice versa */ if (cpu_buf->last_is_kernel != is_kernel) { + if (add_code(cpu_buf, is_kernel)) + goto fail; cpu_buf->last_is_kernel = is_kernel; - add_code(cpu_buf, is_kernel); } /* notice a task switch */ if (!is_kernel) { task = current; if (cpu_buf->last_task != task) { + if (add_code(cpu_buf, (unsigned long)task)) + goto fail; cpu_buf->last_task = task; - add_code(cpu_buf, (unsigned long)task); } } - add_code(cpu_buf, ibs_code); - add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); - add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); - add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); + fail = fail || add_code(cpu_buf, ibs_code); + fail = fail || add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); + fail = fail || add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); + fail = fail || add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); if (ibs_code == IBS_OP_BEGIN) { - add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); - add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); - add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); + fail = fail || add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); + fail = fail || add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); + fail = fail || add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); } + if (fail) + goto fail; + if (backtrace_depth) oprofile_ops.backtrace(regs, backtrace_depth); + + return; + +fail: + cpu_buf->sample_lost_overflow++; + return; } #endif @@ -332,21 +333,21 @@ void oprofile_add_trace(unsigned long pc) if (!cpu_buf->tracing) return; - if (nr_available_slots(cpu_buf) < 1) { - cpu_buf->tracing = 0; - cpu_buf->sample_lost_overflow++; - return; - } + /* + * broken frame can give an eip with the same value as an + * escape code, abort the trace if we get it + */ + if (pc == ESCAPE_CODE) + goto fail; - /* broken frame can give an eip with the same value as an escape code, - * abort the trace if we get it */ - if (pc == ESCAPE_CODE) { - cpu_buf->tracing = 0; - cpu_buf->backtrace_aborted++; - return; - } + if (add_sample(cpu_buf, pc, 0)) + goto fail; - add_sample(cpu_buf, pc, 0); + return; +fail: + cpu_buf->tracing = 0; + cpu_buf->backtrace_aborted++; + return; } /* diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index d3cc26264db5..aacb0f0bc566 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -15,6 +15,7 @@ #include <linux/workqueue.h> #include <linux/cache.h> #include <linux/sched.h> +#include <linux/ring_buffer.h> struct task_struct; @@ -32,6 +33,12 @@ struct op_sample { unsigned long event; }; +struct op_entry { + struct ring_buffer_event *event; + struct op_sample *sample; + unsigned long irq_flags; +}; + struct oprofile_cpu_buffer { volatile unsigned long head_pos; volatile unsigned long tail_pos; @@ -39,7 +46,6 @@ struct oprofile_cpu_buffer { struct task_struct *last_task; int last_is_kernel; int tracing; - struct op_sample *buffer; unsigned long sample_received; unsigned long sample_lost_overflow; unsigned long backtrace_aborted; @@ -48,9 +54,68 @@ struct oprofile_cpu_buffer { struct delayed_work work; }; +extern struct ring_buffer *op_ring_buffer_read; +extern struct ring_buffer *op_ring_buffer_write; DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); -void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf); +/* + * Resets the cpu buffer to a sane state. + * + * reset these to invalid values; the next sample collected will + * populate the buffer with proper values to initialize the buffer + */ +static inline void cpu_buffer_reset(int cpu) +{ + struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); + + cpu_buf->last_is_kernel = -1; + cpu_buf->last_task = NULL; +} + +static inline int cpu_buffer_write_entry(struct op_entry *entry) +{ + entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, + sizeof(struct op_sample), + &entry->irq_flags); + if (entry->event) + entry->sample = ring_buffer_event_data(entry->event); + else + entry->sample = NULL; + + if (!entry->sample) + return -ENOMEM; + + return 0; +} + +static inline int cpu_buffer_write_commit(struct op_entry *entry) +{ + return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event, + entry->irq_flags); +} + +static inline struct op_sample *cpu_buffer_read_entry(int cpu) +{ + struct ring_buffer_event *e; + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + if (e) + return ring_buffer_event_data(e); + if (ring_buffer_swap_cpu(op_ring_buffer_read, + op_ring_buffer_write, + cpu)) + return NULL; + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + if (e) + return ring_buffer_event_data(e); + return NULL; +} + +/* "acquire" as many cpu buffer slots as we can */ +static inline unsigned long cpu_buffer_entries(int cpu) +{ + return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) + + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); +} /* transient events for the CPU buffer -> event buffer */ #define CPU_IS_KERNEL 1 diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index cc106d503ace..d8201998b0b7 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -14,9 +14,13 @@ #include "oprofile_stats.h" #include "oprof.h" -unsigned long fs_buffer_size = 131072; -unsigned long fs_cpu_buffer_size = 8192; -unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */ +#define FS_BUFFER_SIZE_DEFAULT 131072 +#define FS_CPU_BUFFER_SIZE_DEFAULT 8192 +#define FS_BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */ + +unsigned long fs_buffer_size; +unsigned long fs_cpu_buffer_size; +unsigned long fs_buffer_watershed; static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -120,6 +124,11 @@ static const struct file_operations dump_fops = { void oprofile_create_files(struct super_block *sb, struct dentry *root) { + /* reinitialize default values */ + fs_buffer_size = FS_BUFFER_SIZE_DEFAULT; + fs_cpu_buffer_size = FS_CPU_BUFFER_SIZE_DEFAULT; + fs_buffer_watershed = FS_BUFFER_WATERSHED_DEFAULT; + oprofilefs_create_file(sb, root, "enable", &enable_fops); oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 2de5a3238c94..f78371b22529 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -5,6 +5,7 @@ #include <linux/pci.h> #include <linux/irq.h> #include <asm/io_apic.h> +#include <asm/smp.h> #include <linux/intel-iommu.h> #include "intr_remapping.h" @@ -19,17 +20,75 @@ struct irq_2_iommu { u8 irte_mask; }; -static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; +#ifdef CONFIG_SPARSE_IRQ +static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu) +{ + struct irq_2_iommu *iommu; + int node; + + node = cpu_to_node(cpu); + + iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); + printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node); + + return iommu; +} static struct irq_2_iommu *irq_2_iommu(unsigned int irq) { - return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL; + struct irq_desc *desc; + + desc = irq_to_desc(irq); + + if (WARN_ON_ONCE(!desc)) + return NULL; + + return desc->irq_2_iommu; +} + +static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu) +{ + struct irq_desc *desc; + struct irq_2_iommu *irq_iommu; + + /* + * alloc irq desc if not allocated already. + */ + desc = irq_to_desc_alloc_cpu(irq, cpu); + if (!desc) { + printk(KERN_INFO "can not get irq_desc for %d\n", irq); + return NULL; + } + + irq_iommu = desc->irq_2_iommu; + + if (!irq_iommu) + desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu); + + return desc->irq_2_iommu; } static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) { + return irq_2_iommu_alloc_cpu(irq, boot_cpu_id); +} + +#else /* !CONFIG_SPARSE_IRQ */ + +static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; + +static struct irq_2_iommu *irq_2_iommu(unsigned int irq) +{ + if (irq < nr_irqs) + return &irq_2_iommuX[irq]; + + return NULL; +} +static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) +{ return irq_2_iommu(irq); } +#endif static DEFINE_SPINLOCK(irq_2_ir_lock); @@ -86,9 +145,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) if (!count) return -1; +#ifndef CONFIG_SPARSE_IRQ /* protect irq_2_iommu_alloc later */ if (irq >= nr_irqs) return -1; +#endif /* * start the IRTE search from index 0. @@ -130,6 +191,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) table->base[i].present = 1; irq_iommu = irq_2_iommu_alloc(irq); + if (!irq_iommu) { + spin_unlock(&irq_2_ir_lock); + printk(KERN_ERR "can't allocate irq_2_iommu\n"); + return -1; + } + irq_iommu->iommu = iommu; irq_iommu->irte_index = index; irq_iommu->sub_handle = 0; @@ -177,6 +244,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) irq_iommu = irq_2_iommu_alloc(irq); + if (!irq_iommu) { + spin_unlock(&irq_2_ir_lock); + printk(KERN_ERR "can't allocate irq_2_iommu\n"); + return -1; + } + irq_iommu->iommu = iommu; irq_iommu->irte_index = index; irq_iommu->sub_handle = subhandle; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 74801f7df9c9..11a51f8ed3b3 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -103,11 +103,11 @@ static void msix_set_enable(struct pci_dev *dev, int enable) } } -static void msix_flush_writes(unsigned int irq) +static void msix_flush_writes(struct irq_desc *desc) { struct msi_desc *entry; - entry = get_irq_msi(irq); + entry = get_irq_desc_msi(desc); BUG_ON(!entry || !entry->dev); switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: @@ -135,11 +135,11 @@ static void msix_flush_writes(unsigned int irq) * Returns 1 if it succeeded in masking the interrupt and 0 if the device * doesn't support MSI masking. */ -static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) +static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag) { struct msi_desc *entry; - entry = get_irq_msi(irq); + entry = get_irq_desc_msi(desc); BUG_ON(!entry || !entry->dev); switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: @@ -172,9 +172,9 @@ static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) return 1; } -void read_msi_msg(unsigned int irq, struct msi_msg *msg) +void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) { - struct msi_desc *entry = get_irq_msi(irq); + struct msi_desc *entry = get_irq_desc_msi(desc); switch(entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { @@ -211,9 +211,16 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) } } -void write_msi_msg(unsigned int irq, struct msi_msg *msg) +void read_msi_msg(unsigned int irq, struct msi_msg *msg) { - struct msi_desc *entry = get_irq_msi(irq); + struct irq_desc *desc = irq_to_desc(irq); + + read_msi_msg_desc(desc, msg); +} + +void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) +{ + struct msi_desc *entry = get_irq_desc_msi(desc); switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { @@ -252,21 +259,31 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) entry->msg = *msg; } +void write_msi_msg(unsigned int irq, struct msi_msg *msg) +{ + struct irq_desc *desc = irq_to_desc(irq); + + write_msi_msg_desc(desc, msg); +} + void mask_msi_irq(unsigned int irq) { - msi_set_mask_bits(irq, 1, 1); - msix_flush_writes(irq); + struct irq_desc *desc = irq_to_desc(irq); + + msi_set_mask_bits(desc, 1, 1); + msix_flush_writes(desc); } void unmask_msi_irq(unsigned int irq) { - msi_set_mask_bits(irq, 1, 0); - msix_flush_writes(irq); + struct irq_desc *desc = irq_to_desc(irq); + + msi_set_mask_bits(desc, 1, 0); + msix_flush_writes(desc); } static int msi_free_irqs(struct pci_dev* dev); - static struct msi_desc* alloc_msi_entry(void) { struct msi_desc *entry; @@ -303,9 +320,11 @@ static void __pci_restore_msi_state(struct pci_dev *dev) pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); write_msi_msg(dev->irq, &entry->msg); - if (entry->msi_attrib.maskbit) - msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask, + if (entry->msi_attrib.maskbit) { + struct irq_desc *desc = irq_to_desc(dev->irq); + msi_set_mask_bits(desc, entry->msi_attrib.maskbits_mask, entry->msi_attrib.masked); + } pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); control &= ~PCI_MSI_FLAGS_QSIZE; @@ -327,8 +346,9 @@ static void __pci_restore_msix_state(struct pci_dev *dev) msix_set_enable(dev, 0); list_for_each_entry(entry, &dev->msi_list, list) { + struct irq_desc *desc = irq_to_desc(entry->irq); write_msi_msg(entry->irq, &entry->msg); - msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked); + msi_set_mask_bits(desc, 1, entry->msi_attrib.masked); } BUG_ON(list_empty(&dev->msi_list)); @@ -596,7 +616,8 @@ void pci_msi_shutdown(struct pci_dev* dev) /* Return the the pci reset with msi irqs unmasked */ if (entry->msi_attrib.maskbit) { u32 mask = entry->msi_attrib.maskbits_mask; - msi_set_mask_bits(dev->irq, mask, ~mask); + struct irq_desc *desc = irq_to_desc(dev->irq); + msi_set_mask_bits(desc, mask, ~mask); } if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) return; diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 222904411a13..276473543982 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -217,7 +217,7 @@ config PCMCIA_PXA2XX depends on ARM && ARCH_PXA && PCMCIA depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ - || ARCH_VIPER) + || ARCH_VIPER || ARCH_PXA_ESERIES) help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 238629ad7f7c..bbac46327227 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -72,5 +72,6 @@ pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o +pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c new file mode 100644 index 000000000000..f663a011bf4a --- /dev/null +++ b/drivers/pcmcia/pxa2xx_e740.c @@ -0,0 +1,176 @@ +/* + * Toshiba e740 PCMCIA specific routines. + * + * (c) 2004 Ian Molton <spyro@f2s.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> + +#include <mach/hardware.h> +#include <mach/pxa-regs.h> +#include <mach/eseries-gpio.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include "soc_common.h" + +static struct pcmcia_irqs cd_irqs[] = { + { + .sock = 0, + .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD0), + .str = "CF card detect" + }, + { + .sock = 1, + .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD1), + .str = "Wifi switch" + }, +}; + +static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + skt->irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) : + IRQ_GPIO(GPIO_E740_PCMCIA_RDY1); + + return soc_pcmcia_request_irqs(skt, &cd_irqs[skt->nr], 1); +} + +/* + * Release all resources. + */ +static void e740_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +{ + soc_pcmcia_free_irqs(skt, &cd_irqs[skt->nr], 1); +} + +static void e740_pcmcia_socket_state(struct soc_pcmcia_socket *skt, + struct pcmcia_state *state) +{ + if (skt->nr == 0) { + state->detect = gpio_get_value(GPIO_E740_PCMCIA_CD0) ? 0 : 1; + state->ready = gpio_get_value(GPIO_E740_PCMCIA_RDY0) ? 1 : 0; + } else { + state->detect = gpio_get_value(GPIO_E740_PCMCIA_CD1) ? 0 : 1; + state->ready = gpio_get_value(GPIO_E740_PCMCIA_RDY1) ? 1 : 0; + } + + state->vs_3v = 1; + state->bvd1 = 1; + state->bvd2 = 1; + state->wrprot = 0; + state->vs_Xv = 0; +} + +static int e740_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, + const socket_state_t *state) +{ + if (state->flags & SS_RESET) { + if (skt->nr == 0) + gpio_set_value(GPIO_E740_PCMCIA_RST0, 1); + else + gpio_set_value(GPIO_E740_PCMCIA_RST1, 1); + } else { + if (skt->nr == 0) + gpio_set_value(GPIO_E740_PCMCIA_RST0, 0); + else + gpio_set_value(GPIO_E740_PCMCIA_RST1, 0); + } + + switch (state->Vcc) { + case 0: /* Socket off */ + if (skt->nr == 0) + gpio_set_value(GPIO_E740_PCMCIA_PWR0, 0); + else + gpio_set_value(GPIO_E740_PCMCIA_PWR1, 1); + break; + case 50: + case 33: /* socket on */ + if (skt->nr == 0) + gpio_set_value(GPIO_E740_PCMCIA_PWR0, 1); + else + gpio_set_value(GPIO_E740_PCMCIA_PWR1, 0); + break; + default: + printk(KERN_ERR "e740_cs: Unsupported Vcc: %d\n", state->Vcc); + } + + return 0; +} + +/* + * Enable card status IRQs on (re-)initialisation. This can + * be called at initialisation, power management event, or + * pcmcia event. + */ +static void e740_pcmcia_socket_init(struct soc_pcmcia_socket *skt) +{ + soc_pcmcia_enable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs)); +} + +/* + * Disable card status IRQs on suspend. + */ +static void e740_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +{ + soc_pcmcia_disable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs)); +} + +static struct pcmcia_low_level e740_pcmcia_ops = { + .owner = THIS_MODULE, + .hw_init = e740_pcmcia_hw_init, + .hw_shutdown = e740_pcmcia_hw_shutdown, + .socket_state = e740_pcmcia_socket_state, + .configure_socket = e740_pcmcia_configure_socket, + .socket_init = e740_pcmcia_socket_init, + .socket_suspend = e740_pcmcia_socket_suspend, + .nr = 2, +}; + +static struct platform_device *e740_pcmcia_device; + +static int __init e740_pcmcia_init(void) +{ + int ret; + + if (!machine_is_e740()) + return -ENODEV; + + e740_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); + if (!e740_pcmcia_device) + return -ENOMEM; + + ret = platform_device_add_data(e740_pcmcia_device, &e740_pcmcia_ops, + sizeof(e740_pcmcia_ops)); + + if (!ret) + ret = platform_device_add(e740_pcmcia_device); + + if (ret) + platform_device_put(e740_pcmcia_device); + + return ret; +} + +static void __exit e740_pcmcia_exit(void) +{ + platform_device_unregister(e740_pcmcia_device); +} + +module_init(e740_pcmcia_init); +module_exit(e740_pcmcia_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); +MODULE_DESCRIPTION("e740 PCMCIA platform support"); diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 2133f37906f2..d5e4e637ddec 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -21,6 +21,7 @@ #include <mach/board.h> #include <mach/at91_rtt.h> +#include <mach/cpu.h> /* diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f59277bbedaa..7a568beba3f0 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -26,7 +26,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/irq.h> -#include <asm/plat-s3c/regs-rtc.h> +#include <plat/regs-rtc.h> /* I have yet to find an S3C implementation with more than one * of these rtc blocks in */ diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 66a9bb85bbe8..d26a5f82aaba 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -38,11 +38,11 @@ #include <mach/pxa-regs.h> #endif -#define TIMER_FREQ CLOCK_TICK_RATE #define RTC_DEF_DIVIDER 32768 - 1 #define RTC_DEF_TRIM 0 static unsigned long rtc_freq = 1024; +static unsigned long timer_freq; static struct rtc_time rtc_alarm; static DEFINE_SPINLOCK(sa1100_rtc_lock); @@ -157,7 +157,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); if (rtc_timer1_count == 1) - rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); + rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2))); return IRQ_HANDLED; } @@ -166,7 +166,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data) { if (data & RTC_PF) { /* interpolate missed periods and set match for the next */ - unsigned long period = TIMER_FREQ/rtc_freq; + unsigned long period = timer_freq / rtc_freq; unsigned long oscr = OSCR; unsigned long osmr1 = OSMR1; unsigned long missed = (oscr - osmr1)/period; @@ -263,7 +263,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, return 0; case RTC_PIE_ON: spin_lock_irq(&sa1100_rtc_lock); - OSMR1 = TIMER_FREQ/rtc_freq + OSCR; + OSMR1 = timer_freq / rtc_freq + OSCR; OIER |= OIER_E1; rtc_timer1_count = 1; spin_unlock_irq(&sa1100_rtc_lock); @@ -271,7 +271,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, case RTC_IRQP_READ: return put_user(rtc_freq, (unsigned long *)arg); case RTC_IRQP_SET: - if (arg < 1 || arg > TIMER_FREQ) + if (arg < 1 || arg > timer_freq) return -EINVAL; rtc_freq = arg; return 0; @@ -352,6 +352,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; + timer_freq = get_clock_tick_rate(); + /* * According to the manual we should be able to let RTTR be zero * and then a default diviser for a 32.768KHz clock is used. diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 3d442444c618..28c90b89f2b4 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -188,11 +188,13 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, config = kvm_vq_config(kdev->desc)+index; err = vmem_add_mapping(config->address, - vring_size(config->num, PAGE_SIZE)); + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); if (err) goto out; - vq = vring_new_virtqueue(config->num, vdev, (void *) config->address, + vq = vring_new_virtqueue(config->num, KVM_S390_VIRTIO_RING_ALIGN, + vdev, (void *) config->address, kvm_notify, callback); if (!vq) { err = -ENOMEM; @@ -209,7 +211,8 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, return vq; unmap: vmem_remove_mapping(config->address, - vring_size(config->num, PAGE_SIZE)); + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); out: return ERR_PTR(err); } @@ -220,7 +223,8 @@ static void kvm_del_vq(struct virtqueue *vq) vring_del_virtqueue(vq); vmem_remove_mapping(config->address, - vring_size(config->num, PAGE_SIZE)); + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); } /* @@ -295,13 +299,29 @@ static void scan_devices(void) */ static void kvm_extint_handler(u16 code) { - void *data = (void *) *(long *) __LC_PFAULT_INTPARM; - u16 subcode = S390_lowcore.cpu_addr; + struct virtqueue *vq; + u16 subcode; + int config_changed; + subcode = S390_lowcore.cpu_addr; if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) return; - vring_interrupt(0, data); + /* The LSB might be overloaded, we have to mask it */ + vq = (struct virtqueue *) ((*(long *) __LC_PFAULT_INTPARM) & ~1UL); + + /* We use the LSB of extparam, to decide, if this interrupt is a config + * change or a "standard" interrupt */ + config_changed = (*(int *) __LC_EXT_PARAMS & 1); + + if (config_changed) { + struct virtio_driver *drv; + drv = container_of(vq->vdev->dev.driver, + struct virtio_driver, driver); + if (drv->config_changed) + drv->config_changed(vq->vdev); + } else + vring_interrupt(0, vq); } /* diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 2370fd82ebfe..c24140aff8e7 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -578,6 +578,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) { idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); ide_drive_t *drive = scsi->drive; + ide_hwif_t *hwif; + ide_hwgroup_t *hwgroup; int busy; int ret = FAILED; @@ -594,13 +596,16 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) goto no_drive; } - /* First give it some more time, how much is "right" is hard to say :-( */ + hwif = drive->hwif; + hwgroup = hwif->hwgroup; - busy = ide_wait_not_busy(HWIF(drive), 100); /* FIXME - uses mdelay which causes latency? */ + /* First give it some more time, how much is "right" is hard to say :-( + FIXME - uses mdelay which causes latency? */ + busy = ide_wait_not_busy(hwif, 100); if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":""); - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); /* If there is no pc running we're done (our interrupt took care of it) */ pc = drive->pc; @@ -629,7 +634,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) } ide_unlock: - spin_unlock_irq(&ide_lock); + spin_unlock_irq(&hwgroup->lock); no_drive: if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed"); @@ -642,6 +647,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) struct request *req; idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); ide_drive_t *drive = scsi->drive; + ide_hwgroup_t *hwgroup; int ready = 0; int ret = SUCCESS; @@ -658,14 +664,18 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) return FAILED; } + hwgroup = drive->hwif->hwgroup; + spin_lock_irq(cmd->device->host->host_lock); - spin_lock(&ide_lock); + spin_lock(&hwgroup->lock); pc = drive->pc; + if (pc) + req = pc->rq; - if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) { + if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) { printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); - spin_unlock(&ide_lock); + spin_unlock(&hwgroup->lock); spin_unlock_irq(cmd->device->host->host_lock); return FAILED; } @@ -685,10 +695,10 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) BUG(); } - HWGROUP(drive)->rq = NULL; - HWGROUP(drive)->handler = NULL; - HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */ - spin_unlock(&ide_lock); + hwgroup->rq = NULL; + hwgroup->handler = NULL; + hwgroup->busy = 1; /* will set this to zero when ide reset finished */ + spin_unlock(&hwgroup->lock); ide_do_reset(drive); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 579d63a81aa2..b695ab3142d8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on ARM && PLAT_S3C24XX + depends on ARM && PLAT_S3C select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, @@ -455,6 +455,16 @@ config SERIAL_SAMSUNG provide all of these ports, depending on how the serial port pins are configured. +config SERIAL_SAMSUNG_UARTS + int + depends on SERIAL_SAMSUNG + default 2 if ARCH_S3C2400 + default 4 if ARCH_S3C64XX || CPU_S3C2443 + default 3 + help + Select the number of available UART ports for the Samsung S3C + serial driver + config SERIAL_SAMSUNG_DEBUG bool "Samsung SoC serial debug" depends on SERIAL_SAMSUNG && DEBUG_LL @@ -508,7 +518,20 @@ config SERIAL_S3C2440 help Serial port support for the Samsung S3C2440 and S3C2442 SoC +config SERIAL_S3C24A0 + tristate "Samsung S3C24A0 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C24A0 + default y if CPU_S3C24A0 + help + Serial port support for the Samsung S3C24A0 SoC +config SERIAL_S3C6400 + tristate "Samsung S3C6400/S3C6410 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410) + default y + help + Serial port support for the Samsung S3C6400 and S3C6410 + SoCs config SERIAL_DZ bool "DECstation DZ serial driver" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0c17c8ddb19d..dfe775ac45b2 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -41,6 +41,8 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o +obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o +obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 71562689116f..e3a5ad5ef1d6 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -692,7 +692,7 @@ static int pl010_probe(struct amba_device *dev, void *id) goto free; } - uap->clk = clk_get(&dev->dev, "UARTCLK"); + uap->clk = clk_get(&dev->dev, NULL); if (IS_ERR(uap->clk)) { ret = PTR_ERR(uap->clk); goto unmap; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index b7180046f8db..8b2b9700f3e4 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -756,7 +756,7 @@ static int pl011_probe(struct amba_device *dev, void *id) goto free; } - uap->clk = clk_get(&dev->dev, "UARTCLK"); + uap->clk = clk_get(&dev->dev, NULL); if (IS_ERR(uap->clk)) { ret = PTR_ERR(uap->clk); goto unmap; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 3f90f1bbbbcd..a50954612b60 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -66,7 +66,7 @@ #define ONEMS 0xb0 /* One Millisecond register */ #define UTS 0xb4 /* UART Test Register */ #endif -#ifdef CONFIG_ARCH_IMX +#if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) #define BIPR1 0xb0 /* Incremental Preset Register 1 */ #define BIPR2 0xb4 /* Incremental Preset Register 2 */ #define BIPR3 0xb8 /* Incremental Preset Register 3 */ @@ -96,7 +96,7 @@ #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ #define UCR1_SNDBRK (1<<4) /* Send break */ #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ -#ifdef CONFIG_ARCH_IMX +#if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ #endif #if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 @@ -187,11 +187,11 @@ #define MAX_INTERNAL_IRQ IMX_IRQS #endif -#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 +#ifdef CONFIG_ARCH_MXC #define SERIAL_IMX_MAJOR 207 #define MINOR_START 16 #define DEV_NAME "ttymxc" -#define MAX_INTERNAL_IRQ MXC_MAX_INT_LINES +#define MAX_INTERNAL_IRQ MXC_INTERNAL_IRQS #endif /* diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index abc00be55433..f6e3b86bb0be 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -48,6 +48,7 @@ #include <mach/hardware.h> #include <asm/irq.h> #include <mach/pxa-regs.h> +#include <mach/regs-uart.h> struct uart_pxa_port { @@ -766,7 +767,7 @@ static int serial_pxa_probe(struct platform_device *dev) if (!sport) return -ENOMEM; - sport->clk = clk_get(&dev->dev, "UARTCLK"); + sport->clk = clk_get(&dev->dev, NULL); if (IS_ERR(sport->clk)) { ret = PTR_ERR(sport->clk); goto err_free; diff --git a/drivers/serial/s3c24a0.c b/drivers/serial/s3c24a0.c new file mode 100644 index 000000000000..ebf2fd3c8f7d --- /dev/null +++ b/drivers/serial/s3c24a0.c @@ -0,0 +1,118 @@ +/* linux/drivers/serial/s3c24a0.c + * + * Driver for Samsung S3C24A0 SoC onboard UARTs. + * + * Based on drivers/serial/s3c2410.c + * + * Author: Sandeep Patil <sandeep.patil@azingo.com> + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/io.h> +#include <linux/irq.h> + +#include <mach/hardware.h> + +#include <plat/regs-serial.h> +#include <mach/regs-gpio.h> + +#include "samsung.h" + +static int s3c24a0_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2410_UCON_UCLK; + else + ucon &= ~S3C2410_UCON_UCLK; + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + +static int s3c24a0_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk"; + + return 0; +} + +static int s3c24a0_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + wr_regl(port, S3C2410_UCON, cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c24a0_uart_inf = { + .name = "Samsung S3C24A0 UART", + .type = PORT_S3C2410, + .fifosize = 16, + .rx_fifomask = S3C24A0_UFSTAT_RXMASK, + .rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT, + .rx_fifofull = S3C24A0_UFSTAT_RXFULL, + .tx_fifofull = S3C24A0_UFSTAT_TXFULL, + .tx_fifomask = S3C24A0_UFSTAT_TXMASK, + .tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT, + .get_clksrc = s3c24a0_serial_getsource, + .set_clksrc = s3c24a0_serial_setsource, + .reset_port = s3c24a0_serial_resetport, +}; + +static int s3c24a0_serial_probe(struct platform_device *dev) +{ + return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf); +} + +static struct platform_driver s3c24a0_serial_drv = { + .probe = s3c24a0_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c24a0-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf); + +static int __init s3c24a0_serial_init(void) +{ + return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf); +} + +static void __exit s3c24a0_serial_exit(void) +{ + platform_driver_unregister(&s3c24a0_serial_drv); +} + +module_init(s3c24a0_serial_init); +module_exit(s3c24a0_serial_exit); + diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c new file mode 100644 index 000000000000..06936d13393f --- /dev/null +++ b/drivers/serial/s3c6400.c @@ -0,0 +1,151 @@ +/* linux/drivers/serial/s3c6400.c + * + * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/irq.h> +#include <mach/hardware.h> + +#include <plat/regs-serial.h> + +#include "samsung.h" + +static int s3c6400_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "uclk0") == 0) { + ucon &= ~S3C6400_UCON_CLKMASK; + ucon |= S3C6400_UCON_UCLK0; + } else if (strcmp(clk->name, "uclk1") == 0) + ucon |= S3C6400_UCON_UCLK1; + else if (strcmp(clk->name, "pclk") == 0) { + /* See notes about transitioning from UCLK to PCLK */ + ucon &= ~S3C6400_UCON_UCLK0; + } else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c6400_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + u32 ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + + switch (ucon & S3C6400_UCON_CLKMASK) { + case S3C6400_UCON_UCLK0: + clk->name = "uclk0"; + break; + + case S3C6400_UCON_UCLK1: + clk->name = "uclk1"; + break; + + case S3C6400_UCON_PCLK: + case S3C6400_UCON_PCLK2: + clk->name = "pclk"; + break; + } + + return 0; +} + +static int s3c6400_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + /* ensure we don't change the clock settings... */ + + ucon &= S3C6400_UCON_CLKMASK; + + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c6400_uart_inf = { + .name = "Samsung S3C6400 UART", + .type = PORT_S3C6400, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c6400_serial_getsource, + .set_clksrc = s3c6400_serial_setsource, + .reset_port = s3c6400_serial_resetport, +}; + +/* device management */ + +static int s3c6400_serial_probe(struct platform_device *dev) +{ + dbg("s3c6400_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c6400_uart_inf); +} + +static struct platform_driver s3c6400_serial_drv = { + .probe = s3c6400_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c6400-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf); + +static int __init s3c6400_serial_init(void) +{ + return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf); +} + +static void __exit s3c6400_serial_exit(void) +{ + platform_driver_unregister(&s3c6400_serial_drv); +} + +module_init(s3c6400_serial_init); +module_exit(s3c6400_serial_exit); + +MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:s3c6400-uart"); diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 1e219d3d0352..41ac94872b8d 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -42,13 +42,14 @@ #include <linux/serial.h> #include <linux/delay.h> #include <linux/clk.h> +#include <linux/cpufreq.h> #include <asm/irq.h> #include <mach/hardware.h> +#include <mach/map.h> #include <plat/regs-serial.h> -#include <mach/regs-gpio.h> #include "samsung.h" @@ -58,19 +59,6 @@ #define S3C24XX_SERIAL_MAJOR 204 #define S3C24XX_SERIAL_MINOR 64 -/* we can support 3 uarts, but not always use them */ - -#ifdef CONFIG_CPU_S3C2400 -#define NR_PORTS (2) -#else -#define NR_PORTS (3) -#endif - -/* port irq numbers */ - -#define TX_IRQ(port) ((port)->irq + 1) -#define RX_IRQ(port) ((port)->irq) - /* macros to change one thing to another */ #define tx_enabled(port) ((port)->unused[0]) @@ -136,8 +124,10 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) static void s3c24xx_serial_stop_tx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (tx_enabled(port)) { - disable_irq(TX_IRQ(port)); + disable_irq(ourport->tx_irq); tx_enabled(port) = 0; if (port->flags & UPF_CONS_FLOW) s3c24xx_serial_rx_enable(port); @@ -146,11 +136,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) static void s3c24xx_serial_start_tx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (!tx_enabled(port)) { if (port->flags & UPF_CONS_FLOW) s3c24xx_serial_rx_disable(port); - enable_irq(TX_IRQ(port)); + enable_irq(ourport->tx_irq); tx_enabled(port) = 1; } } @@ -158,9 +150,11 @@ static void s3c24xx_serial_start_tx(struct uart_port *port) static void s3c24xx_serial_stop_rx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (rx_enabled(port)) { dbg("s3c24xx_serial_stop_rx: port=%p\n", port); - disable_irq(RX_IRQ(port)); + disable_irq(ourport->rx_irq); rx_enabled(port) = 0; } } @@ -384,13 +378,13 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) struct s3c24xx_uart_port *ourport = to_ourport(port); if (ourport->tx_claimed) { - free_irq(TX_IRQ(port), ourport); + free_irq(ourport->tx_irq, ourport); tx_enabled(port) = 0; ourport->tx_claimed = 0; } if (ourport->rx_claimed) { - free_irq(RX_IRQ(port), ourport); + free_irq(ourport->rx_irq, ourport); ourport->rx_claimed = 0; rx_enabled(port) = 0; } @@ -407,12 +401,11 @@ static int s3c24xx_serial_startup(struct uart_port *port) rx_enabled(port) = 1; - ret = request_irq(RX_IRQ(port), - s3c24xx_serial_rx_chars, 0, + ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, s3c24xx_serial_portname(port), ourport); if (ret != 0) { - printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); + printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq); return ret; } @@ -422,12 +415,11 @@ static int s3c24xx_serial_startup(struct uart_port *port) tx_enabled(port) = 1; - ret = request_irq(TX_IRQ(port), - s3c24xx_serial_tx_chars, 0, + ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, s3c24xx_serial_portname(port), ourport); if (ret) { - printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); + printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq); goto err; } @@ -452,6 +444,8 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, { struct s3c24xx_uart_port *ourport = to_ourport(port); + ourport->pm_level = level; + switch (level) { case 3: if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) @@ -661,6 +655,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, ourport->clksrc = clksrc; ourport->baudclk = clk; + ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; } switch (termios->c_cflag & CSIZE) { @@ -752,6 +747,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port) return "S3C2440"; case PORT_S3C2412: return "S3C2412"; + case PORT_S3C6400: + return "S3C6400/10"; default: return NULL; } @@ -827,14 +824,14 @@ static struct uart_ops s3c24xx_serial_ops = { static struct uart_driver s3c24xx_uart_drv = { .owner = THIS_MODULE, .dev_name = "s3c2410_serial", - .nr = 3, + .nr = CONFIG_SERIAL_SAMSUNG_UARTS, .cons = S3C24XX_SERIAL_CONSOLE, .driver_name = S3C24XX_SERIAL_NAME, .major = S3C24XX_SERIAL_MAJOR, .minor = S3C24XX_SERIAL_MINOR, }; -static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { +static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { [0] = { .port = { .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), @@ -859,7 +856,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { .line = 1, } }, -#if NR_PORTS > 2 +#if CONFIG_SERIAL_SAMSUNG_UARTS > 2 [2] = { .port = { @@ -872,6 +869,20 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { .flags = UPF_BOOT_AUTOCONF, .line = 2, } + }, +#endif +#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 + [3] = { + .port = { + .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX3, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 3, + } } #endif }; @@ -890,6 +901,89 @@ static inline int s3c24xx_serial_resetport(struct uart_port *port, return (info->reset_port)(port, cfg); } + +#ifdef CONFIG_CPU_FREQ + +static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct s3c24xx_uart_port *port; + struct uart_port *uport; + + port = container_of(nb, struct s3c24xx_uart_port, freq_transition); + uport = &port->port; + + /* check to see if port is enabled */ + + if (port->pm_level != 0) + return 0; + + /* try and work out if the baudrate is changing, we can detect + * a change in rate, but we do not have support for detecting + * a disturbance in the clock-rate over the change. + */ + + if (IS_ERR(port->clk)) + goto exit; + + if (port->baudclk_rate == clk_get_rate(port->clk)) + goto exit; + + if (val == CPUFREQ_PRECHANGE) { + /* we should really shut the port down whilst the + * frequency change is in progress. */ + + } else if (val == CPUFREQ_POSTCHANGE) { + struct ktermios *termios; + struct tty_struct *tty; + + if (uport->info == NULL) + goto exit; + + tty = uport->info->port.tty; + + if (tty == NULL) + goto exit; + + termios = tty->termios; + + if (termios == NULL) { + printk(KERN_WARNING "%s: no termios?\n", __func__); + goto exit; + } + + s3c24xx_serial_set_termios(uport, termios, NULL); + } + + exit: + return 0; +} + +static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) +{ + port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition; + + return cpufreq_register_notifier(&port->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} + +static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) +{ + cpufreq_unregister_notifier(&port->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} + +#else +static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) +{ + return 0; +} + +static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) +{ +} +#endif + /* s3c24xx_serial_init_port * * initialise a single serial port from the platform device given @@ -914,8 +1008,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, if (port->mapbase != 0) return 0; - if (cfg->hwport > 3) - return -EINVAL; + if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) { + printk(KERN_ERR "%s: port %d bigger than %d\n", __func__, + cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS); + return -ERANGE; + } /* setup info for port */ port->dev = &platdev->dev; @@ -943,18 +1040,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); - port->mapbase = res->start; - port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); + port->mapbase = res->start; + port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); ret = platform_get_irq(platdev, 0); if (ret < 0) port->irq = 0; - else + else { port->irq = ret; + ourport->rx_irq = ret; + ourport->tx_irq = ret + 1; + } + + ret = platform_get_irq(platdev, 1); + if (ret > 0) + ourport->tx_irq = ret; ourport->clk = clk_get(&platdev->dev, "uart"); - dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n", - port->mapbase, port->membase, port->irq, port->uartclk); + dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n", + port->mapbase, port->membase, port->irq, + ourport->rx_irq, ourport->tx_irq, port->uartclk); /* reset the fifos (and setup the uart) */ s3c24xx_serial_resetport(port, cfg); @@ -1002,6 +1107,10 @@ int s3c24xx_serial_probe(struct platform_device *dev, if (ret < 0) printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); + ret = s3c24xx_serial_cpufreq_register(ourport); + if (ret < 0) + dev_err(&dev->dev, "failed to add cpufreq notifier\n"); + return 0; probe_err: @@ -1015,6 +1124,7 @@ int s3c24xx_serial_remove(struct platform_device *dev) struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); if (port) { + s3c24xx_serial_cpufreq_deregister(to_ourport(port)); device_remove_file(&dev->dev, &dev_attr_clock_source); uart_remove_one_port(&s3c24xx_uart_drv, port); } @@ -1219,7 +1329,7 @@ static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) platdev_ptr = s3c24xx_uart_devs; - for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) { + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { s3c24xx_serial_init_port(ptr, info, *platdev_ptr); } @@ -1240,7 +1350,7 @@ s3c24xx_serial_console_setup(struct console *co, char *options) /* is this a valid port */ - if (co->index == -1 || co->index >= NR_PORTS) + if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) co->index = 0; port = &s3c24xx_serial_ports[co->index].port; diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index 5c92ebbe7d9e..571d6b90d206 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h @@ -33,12 +33,21 @@ struct s3c24xx_uart_info { struct s3c24xx_uart_port { unsigned char rx_claimed; unsigned char tx_claimed; + unsigned int pm_level; + unsigned long baudclk_rate; + + unsigned int rx_irq; + unsigned int tx_irq; struct s3c24xx_uart_info *info; struct s3c24xx_uart_clksrc *clksrc; struct clk *clk; struct clk *baudclk; struct uart_port port; + +#ifdef CONFIG_CPU_FREQ + struct notifier_block freq_transition; +#endif }; /* conversion functions */ diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 61dc8b3daa26..a7bf024a8286 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -41,9 +41,10 @@ #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> +#include <linux/io.h> -#include <asm/io.h> #include <asm/irq.h> +#include <mach/hardware.h> #define DEV_MAJOR 204 #define DEV_MINOR 16 diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index cf12f2d84be2..6104f461a3cd 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -32,8 +32,8 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/delay.h> -#include <asm/dma.h> +#include <mach/dma.h> #include <mach/hardware.h> #include <mach/pxa-regs.h> #include <mach/regs-ssp.h> diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index c252cbac00f1..256d18395a23 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -28,7 +28,7 @@ #include <mach/hardware.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c24xx/regs-spi.h> +#include <plat/regs-spi.h> #include <mach/spi.h> struct s3c24xx_spi { diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 2dbc0db0b46c..8c5026be79d4 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2145,7 +2145,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) if (irq < 0) return -ENODEV; - dev->clk = clk_get(&pdev->dev, "UDCCLK"); + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { retval = PTR_ERR(dev->clk); goto err_clk; diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index caa37c95802c..944e4ff641df 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2226,7 +2226,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; - udc->clk = clk_get(&pdev->dev, "UDCCLK"); + udc->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(udc->clk)) { retval = PTR_ERR(udc->clk); goto err_clk; diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 00ba06b44752..8d8d65165983 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -53,8 +53,8 @@ #include <mach/hardware.h> #include <mach/regs-gpio.h> -#include <asm/plat-s3c24xx/regs-udc.h> -#include <asm/plat-s3c24xx/udc.h> +#include <plat/regs-udc.h> +#include <plat/udc.h> #include "s3c2410_udc.h" diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 5416cf969005..9d487908012e 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -33,8 +33,9 @@ /* * Implement Orion USB controller specification guidelines */ -static void orion_usb_setup(struct usb_hcd *hcd) +static void orion_usb_phy_v1_setup(struct usb_hcd *hcd) { + /* The below GLs are according to the Orion Errata document */ /* * Clear interrupt cause and mask */ @@ -258,9 +259,19 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) ehci_orion_conf_mbus_windows(hcd, pd->dram); /* - * setup Orion USB controller + * setup Orion USB controller. */ - orion_usb_setup(hcd); + switch (pd->phy_version) { + case EHCI_PHY_NA: /* dont change USB phy settings */ + break; + case EHCI_PHY_ORION: + orion_usb_phy_v1_setup(hcd); + break; + case EHCI_PHY_DD: + case EHCI_PHY_KW: + default: + printk(KERN_WARNING "Orion ehci -USB phy version isn't supported.\n"); + } err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); if (err) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 91697bdb399f..4bbddb73abd9 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -18,6 +18,7 @@ #include <linux/jiffies.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <asm/io.h> @@ -25,7 +26,6 @@ #include <mach/mux.h> #include <mach/irqs.h> -#include <mach/gpio.h> #include <mach/fpga.h> #include <mach/usb.h> @@ -254,8 +254,8 @@ static int ohci_omap_init(struct usb_hcd *hcd) /* gpio9 for overcurrent detction */ omap_cfg_reg(W8_1610_GPIO9); - omap_request_gpio(9); - omap_set_gpio_direction(9, 1 /* IN */); + gpio_request(9, "OHCI overcurrent"); + gpio_direction_input(9); /* for paranoia's sake: disable USB.PUEN */ omap_cfg_reg(W4_USB_HIGHZ); @@ -407,7 +407,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) put_device(ohci->transceiver->dev); } if (machine_is_omap_osk()) - omap_free_gpio(9); + gpio_free(9); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e294d430733b..e44dc2cbca24 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -296,7 +296,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device return -ENXIO; } - usb_clk = clk_get(&pdev->dev, "USBCLK"); + usb_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_clk)) return PTR_ERR(usb_clk); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d0c821992a99..6372f8b17b45 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -362,7 +362,7 @@ endchoice config FB_ACORN bool "Acorn VIDC support" - depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500) + depends on (FB = y) && ARM && ARCH_ACORN select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1817,6 +1817,11 @@ config FB_PXA If unsure, say N. +config FB_PXA_OVERLAY + bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer" + default n + depends on FB_PXA && (PXA27x || PXA3xx) + config FB_PXA_SMARTPANEL bool "PXA Smartpanel LCD support" default n diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index a7a1c891bfa2..2ac52fd8cc11 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -343,14 +343,14 @@ static int clcdfb_register(struct clcd_fb *fb) { int ret; - fb->clk = clk_get(&fb->dev->dev, "CLCDCLK"); + fb->clk = clk_get(&fb->dev->dev, NULL); if (IS_ERR(fb->clk)) { ret = PTR_ERR(fb->clk); goto out; } fb->fb.fix.mmio_start = fb->dev->res.start; - fb->fb.fix.mmio_len = SZ_4K; + fb->fb.fix.mmio_len = 4096; fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len); if (!fb->regs) { diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 448d209a0bf2..e6210725b9ab 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -112,6 +112,23 @@ static int vga_video_font_height; static int vga_scan_lines __read_mostly; static unsigned int vga_rolled_over; +int vgacon_text_mode_force = 0; + +bool vgacon_text_force(void) +{ + return vgacon_text_mode_force ? true : false; +} +EXPORT_SYMBOL(vgacon_text_force); + +static int __init text_mode(char *str) +{ + vgacon_text_mode_force = 1; + return 1; +} + +/* force text mode - used by kernel modesetting */ +__setup("nomodeset", text_mode); + static int __init no_scroll(char *str) { /* diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 41d62632dcdb..39d5d643a50b 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1513,7 +1513,7 @@ static int cyberpro_pci_enable_mmio(struct cfb_info *cfb) iop = ioremap(0x3000000, 0x5000); if (iop == NULL) { - prom_printf("iga5000: cannot map I/O\n"); + printk(KERN_ERR "iga5000: cannot map I/O\n"); return -ENOMEM; } diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index ccd986140c95..d58c68cd456e 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -1,6 +1,4 @@ /* - * linux/drivers/video/imxfb.c - * * Freescale i.MX Frame Buffer device driver * * Copyright (C) 2004 Sascha Hauer, Pengutronix @@ -16,7 +14,6 @@ * linux-arm-kernel@lists.arm.linux.org.uk */ -//#define DEBUG 1 #include <linux/module.h> #include <linux/kernel.h> @@ -32,9 +29,8 @@ #include <linux/cpufreq.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/io.h> -#include <mach/hardware.h> -#include <asm/io.h> #include <mach/imxfb.h> /* @@ -42,23 +38,150 @@ */ #define DEBUG_VAR 1 -#include "imxfb.h" +#define DRIVER_NAME "imx-fb" + +#define LCDC_SSA 0x00 + +#define LCDC_SIZE 0x04 +#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) +#define SIZE_YMAX(y) ((y) & 0x1ff) + +#define LCDC_VPW 0x08 +#define VPW_VPW(x) ((x) & 0x3ff) + +#define LCDC_CPOS 0x0C +#define CPOS_CC1 (1<<31) +#define CPOS_CC0 (1<<30) +#define CPOS_OP (1<<28) +#define CPOS_CXP(x) (((x) & 3ff) << 16) +#define CPOS_CYP(y) ((y) & 0x1ff) + +#define LCDC_LCWHB 0x10 +#define LCWHB_BK_EN (1<<31) +#define LCWHB_CW(w) (((w) & 0x1f) << 24) +#define LCWHB_CH(h) (((h) & 0x1f) << 16) +#define LCWHB_BD(x) ((x) & 0xff) + +#define LCDC_LCHCC 0x14 +#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11) +#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5) +#define LCHCC_CUR_COL_B(b) ((b) & 0x1f) + +#define LCDC_PCR 0x18 + +#define LCDC_HCR 0x1C +#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26) +#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8) +#define HCR_H_WAIT_2(x) ((x) & 0xff) + +#define LCDC_VCR 0x20 +#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26) +#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8) +#define VCR_V_WAIT_2(x) ((x) & 0xff) + +#define LCDC_POS 0x24 +#define POS_POS(x) ((x) & 1f) + +#define LCDC_LSCR1 0x28 +/* bit fields in imxfb.h */ + +#define LCDC_PWMR 0x2C +/* bit fields in imxfb.h */ + +#define LCDC_DMACR 0x30 +/* bit fields in imxfb.h */ + +#define LCDC_RMCR 0x34 +#define RMCR_LCDC_EN (1<<1) +#define RMCR_SELF_REF (1<<0) + +#define LCDC_LCDICR 0x38 +#define LCDICR_INT_SYN (1<<2) +#define LCDICR_INT_CON (1) + +#define LCDC_LCDISR 0x40 +#define LCDISR_UDR_ERR (1<<3) +#define LCDISR_ERR_RES (1<<2) +#define LCDISR_EOF (1<<1) +#define LCDISR_BOF (1<<0) + +/* + * These are the bitfields for each + * display depth that we support. + */ +struct imxfb_rgb { + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; +}; + +struct imxfb_info { + struct platform_device *pdev; + void __iomem *regs; -static struct imxfb_rgb def_rgb_16 = { - .red = { .offset = 8, .length = 4, }, - .green = { .offset = 4, .length = 4, }, - .blue = { .offset = 0, .length = 4, }, - .transp = { .offset = 0, .length = 0, }, + u_int max_bpp; + u_int max_xres; + u_int max_yres; + + /* + * These are the addresses we mapped + * the framebuffer memory region to. + */ + dma_addr_t map_dma; + u_char *map_cpu; + u_int map_size; + + u_char *screen_cpu; + dma_addr_t screen_dma; + u_int palette_size; + + dma_addr_t dbar1; + dma_addr_t dbar2; + + u_int pcr; + u_int pwmr; + u_int lscr1; + u_int dmacr; + u_int cmap_inverse:1, + cmap_static:1, + unused:30; + + void (*lcd_power)(int); + void (*backlight_power)(int); +}; + +#define IMX_NAME "IMX" + +/* + * Minimum X and Y resolutions + */ +#define MIN_XRES 64 +#define MIN_YRES 64 + +static struct imxfb_rgb def_rgb_16_tft = { + .red = {.offset = 11, .length = 5,}, + .green = {.offset = 5, .length = 6,}, + .blue = {.offset = 0, .length = 5,}, + .transp = {.offset = 0, .length = 0,}, +}; + +static struct imxfb_rgb def_rgb_16_stn = { + .red = {.offset = 8, .length = 4,}, + .green = {.offset = 4, .length = 4,}, + .blue = {.offset = 0, .length = 4,}, + .transp = {.offset = 0, .length = 0,}, }; static struct imxfb_rgb def_rgb_8 = { - .red = { .offset = 0, .length = 8, }, - .green = { .offset = 0, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, - .transp = { .offset = 0, .length = 0, }, + .red = {.offset = 0, .length = 8,}, + .green = {.offset = 0, .length = 8,}, + .blue = {.offset = 0, .length = 8,}, + .transp = {.offset = 0, .length = 0,}, }; -static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info); +static int imxfb_activate_var(struct fb_var_screeninfo *var, + struct fb_info *info); static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) { @@ -67,10 +190,8 @@ static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) return chan << bf->offset; } -#define LCDC_PALETTE(x) __REG2(IMX_LCDC_BASE+0x800, (x)<<2) -static int -imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, - u_int trans, struct fb_info *info) +static int imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, + u_int trans, struct fb_info *info) { struct imxfb_info *fbi = info->par; u_int val, ret = 1; @@ -81,14 +202,13 @@ imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, (CNVT_TOHW(green,4) << 4) | CNVT_TOHW(blue, 4); - LCDC_PALETTE(regno) = val; + writel(val, fbi->regs + 0x800 + (regno << 2)); ret = 0; } return ret; } -static int -imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, +static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info) { struct imxfb_info *fbi = info->par; @@ -148,11 +268,10 @@ imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, * bitfields, horizontal timing, vertical timing. */ -static int -imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct imxfb_info *fbi = info->par; - int rgbidx; + struct imxfb_rgb *rgb; if (var->xres < MIN_XRES) var->xres = MIN_XRES; @@ -168,23 +287,25 @@ imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch (var->bits_per_pixel) { case 16: - rgbidx = RGB_16; + default: + if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) + rgb = &def_rgb_16_tft; + else + rgb = &def_rgb_16_stn; break; case 8: - rgbidx = RGB_8; + rgb = &def_rgb_8; break; - default: - rgbidx = RGB_16; } /* * Copy the RGB parameters for this display * from the machine specific parameters. */ - var->red = fbi->rgb[rgbidx]->red; - var->green = fbi->rgb[rgbidx]->green; - var->blue = fbi->rgb[rgbidx]->blue; - var->transp = fbi->rgb[rgbidx]->transp; + var->red = rgb->red; + var->green = rgb->green; + var->blue = rgb->blue; + var->transp = rgb->transp; pr_debug("RGBT length = %d:%d:%d:%d\n", var->red.length, var->green.length, var->blue.length, @@ -221,8 +342,7 @@ static int imxfb_set_par(struct fb_info *info) info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; } - info->fix.line_length = var->xres_virtual * - var->bits_per_pixel / 8; + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; imxfb_activate_var(var, info); @@ -235,22 +355,27 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) pr_debug("Enabling LCD controller\n"); /* initialize LCDC */ - LCDC_RMCR &= ~RMCR_LCDC_EN; /* just to be safe... */ + writel(readl(fbi->regs + LCDC_RMCR) & ~RMCR_LCDC_EN, + fbi->regs + LCDC_RMCR); /* just to be safe... */ + + writel(fbi->screen_dma, fbi->regs + LCDC_SSA); - LCDC_SSA = fbi->screen_dma; /* physical screen start address */ - LCDC_VPW = VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4); + writel(VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4), + fbi->regs + LCDC_VPW); - LCDC_POS = 0x00000000; /* panning offset 0 (0 pixel offset) */ + /* panning offset 0 (0 pixel offset) */ + writel(0x00000000, fbi->regs + LCDC_POS); /* disable hardware cursor */ - LCDC_CPOS &= ~(CPOS_CC0 | CPOS_CC1); + writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1), + fbi->regs + LCDC_CPOS); - LCDC_RMCR = RMCR_LCDC_EN; + writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); - if(fbi->backlight_power) + if (fbi->backlight_power) fbi->backlight_power(1); - if(fbi->lcd_power) + if (fbi->lcd_power) fbi->lcd_power(1); } @@ -258,12 +383,12 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) { pr_debug("Disabling LCD controller\n"); - if(fbi->backlight_power) + if (fbi->backlight_power) fbi->backlight_power(0); - if(fbi->lcd_power) + if (fbi->lcd_power) fbi->lcd_power(0); - LCDC_RMCR = 0; + writel(0, fbi->regs + LCDC_RMCR); } static int imxfb_blank(int blank, struct fb_info *info) @@ -340,74 +465,26 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf info->fix.id, var->lower_margin); #endif - LCDC_HCR = HCR_H_WIDTH(var->hsync_len) | - HCR_H_WAIT_1(var->left_margin) | - HCR_H_WAIT_2(var->right_margin); + writel(HCR_H_WIDTH(var->hsync_len) | + HCR_H_WAIT_1(var->right_margin) | + HCR_H_WAIT_2(var->left_margin), + fbi->regs + LCDC_HCR); - LCDC_VCR = VCR_V_WIDTH(var->vsync_len) | - VCR_V_WAIT_1(var->upper_margin) | - VCR_V_WAIT_2(var->lower_margin); + writel(VCR_V_WIDTH(var->vsync_len) | + VCR_V_WAIT_1(var->lower_margin) | + VCR_V_WAIT_2(var->upper_margin), + fbi->regs + LCDC_VCR); - LCDC_SIZE = SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres); - LCDC_PCR = fbi->pcr; - LCDC_PWMR = fbi->pwmr; - LCDC_LSCR1 = fbi->lscr1; - LCDC_DMACR = fbi->dmacr; + writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), + fbi->regs + LCDC_SIZE); + writel(fbi->pcr, fbi->regs + LCDC_PCR); + writel(fbi->pwmr, fbi->regs + LCDC_PWMR); + writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); + writel(fbi->dmacr, fbi->regs + LCDC_DMACR); return 0; } -static void imxfb_setup_gpio(struct imxfb_info *fbi) -{ - int width; - - LCDC_RMCR &= ~(RMCR_LCDC_EN | RMCR_SELF_REF); - - if( fbi->pcr & PCR_TFT ) - width = 16; - else - width = 1 << ((fbi->pcr >> 28) & 0x3); - - switch(width) { - case 16: - imx_gpio_mode(PD30_PF_LD15); - imx_gpio_mode(PD29_PF_LD14); - imx_gpio_mode(PD28_PF_LD13); - imx_gpio_mode(PD27_PF_LD12); - imx_gpio_mode(PD26_PF_LD11); - imx_gpio_mode(PD25_PF_LD10); - imx_gpio_mode(PD24_PF_LD9); - imx_gpio_mode(PD23_PF_LD8); - case 8: - imx_gpio_mode(PD22_PF_LD7); - imx_gpio_mode(PD21_PF_LD6); - imx_gpio_mode(PD20_PF_LD5); - imx_gpio_mode(PD19_PF_LD4); - case 4: - imx_gpio_mode(PD18_PF_LD3); - imx_gpio_mode(PD17_PF_LD2); - case 2: - imx_gpio_mode(PD16_PF_LD1); - case 1: - imx_gpio_mode(PD15_PF_LD0); - } - - /* initialize GPIOs */ - imx_gpio_mode(PD6_PF_LSCLK); - imx_gpio_mode(PD11_PF_CONTRAST); - imx_gpio_mode(PD14_PF_FLM_VSYNC); - imx_gpio_mode(PD13_PF_LP_HSYNC); - imx_gpio_mode(PD12_PF_ACD_OE); - - /* These are only needed for Sharp HR TFT displays */ - if (fbi->pcr & PCR_SHARP) { - imx_gpio_mode(PD7_PF_REV); - imx_gpio_mode(PD8_PF_CLS); - imx_gpio_mode(PD9_PF_PS); - imx_gpio_mode(PD10_PF_SPL_SPR); - } -} - #ifdef CONFIG_PM /* * Power management hooks. Note that we won't be called from IRQ context, @@ -416,7 +493,8 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) static int imxfb_suspend(struct platform_device *dev, pm_message_t state) { struct imxfb_info *fbi = platform_get_drvdata(dev); - pr_debug("%s\n",__func__); + + pr_debug("%s\n", __func__); imxfb_disable_controller(fbi); return 0; @@ -425,7 +503,8 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state) static int imxfb_resume(struct platform_device *dev) { struct imxfb_info *fbi = platform_get_drvdata(dev); - pr_debug("%s\n",__func__); + + pr_debug("%s\n", __func__); imxfb_enable_controller(fbi); return 0; @@ -435,149 +514,136 @@ static int imxfb_resume(struct platform_device *dev) #define imxfb_resume NULL #endif -static int __init imxfb_init_fbinfo(struct device *dev) +static int __init imxfb_init_fbinfo(struct platform_device *pdev) { - struct imxfb_mach_info *inf = dev->platform_data; - struct fb_info *info = dev_get_drvdata(dev); + struct imx_fb_platform_data *pdata = pdev->dev.platform_data; + struct fb_info *info = dev_get_drvdata(&pdev->dev); struct imxfb_info *fbi = info->par; pr_debug("%s\n",__func__); - info->pseudo_palette = kmalloc( sizeof(u32) * 16, GFP_KERNEL); + info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); if (!info->pseudo_palette) return -ENOMEM; memset(fbi, 0, sizeof(struct imxfb_info)); - fbi->dev = dev; strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); - info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.type_aux = 0; info->fix.xpanstep = 0; info->fix.ypanstep = 0; info->fix.ywrapstep = 0; - info->fix.accel = FB_ACCEL_NONE; + info->fix.accel = FB_ACCEL_NONE; info->var.nonstd = 0; info->var.activate = FB_ACTIVATE_NOW; info->var.height = -1; info->var.width = -1; info->var.accel_flags = 0; - info->var.vmode = FB_VMODE_NONINTERLACED; + info->var.vmode = FB_VMODE_NONINTERLACED; info->fbops = &imxfb_ops; - info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; - - fbi->rgb[RGB_16] = &def_rgb_16; - fbi->rgb[RGB_8] = &def_rgb_8; - - fbi->max_xres = inf->xres; - info->var.xres = inf->xres; - info->var.xres_virtual = inf->xres; - fbi->max_yres = inf->yres; - info->var.yres = inf->yres; - info->var.yres_virtual = inf->yres; - fbi->max_bpp = inf->bpp; - info->var.bits_per_pixel = inf->bpp; - info->var.nonstd = inf->nonstd; - info->var.pixclock = inf->pixclock; - info->var.hsync_len = inf->hsync_len; - info->var.left_margin = inf->left_margin; - info->var.right_margin = inf->right_margin; - info->var.vsync_len = inf->vsync_len; - info->var.upper_margin = inf->upper_margin; - info->var.lower_margin = inf->lower_margin; - info->var.sync = inf->sync; - info->var.grayscale = inf->cmap_greyscale; - fbi->cmap_inverse = inf->cmap_inverse; - fbi->cmap_static = inf->cmap_static; - fbi->pcr = inf->pcr; - fbi->lscr1 = inf->lscr1; - fbi->dmacr = inf->dmacr; - fbi->pwmr = inf->pwmr; - fbi->lcd_power = inf->lcd_power; - fbi->backlight_power = inf->backlight_power; + info->flags = FBINFO_FLAG_DEFAULT | + FBINFO_READS_FAST; + + fbi->max_xres = pdata->xres; + info->var.xres = pdata->xres; + info->var.xres_virtual = pdata->xres; + fbi->max_yres = pdata->yres; + info->var.yres = pdata->yres; + info->var.yres_virtual = pdata->yres; + fbi->max_bpp = pdata->bpp; + info->var.bits_per_pixel = pdata->bpp; + info->var.nonstd = pdata->nonstd; + info->var.pixclock = pdata->pixclock; + info->var.hsync_len = pdata->hsync_len; + info->var.left_margin = pdata->left_margin; + info->var.right_margin = pdata->right_margin; + info->var.vsync_len = pdata->vsync_len; + info->var.upper_margin = pdata->upper_margin; + info->var.lower_margin = pdata->lower_margin; + info->var.sync = pdata->sync; + info->var.grayscale = pdata->cmap_greyscale; + fbi->cmap_inverse = pdata->cmap_inverse; + fbi->cmap_static = pdata->cmap_static; + fbi->pcr = pdata->pcr; + fbi->lscr1 = pdata->lscr1; + fbi->dmacr = pdata->dmacr; + fbi->pwmr = pdata->pwmr; + fbi->lcd_power = pdata->lcd_power; + fbi->backlight_power = pdata->backlight_power; info->fix.smem_len = fbi->max_xres * fbi->max_yres * fbi->max_bpp / 8; return 0; } -/* - * Allocates the DRAM memory for the frame buffer. This buffer is - * remapped into a non-cached, non-buffered, memory region to - * allow pixel writes to occur without flushing the cache. - * Once this area is remapped, all virtual memory access to the - * video memory should occur at the new region. - */ -static int __init imxfb_map_video_memory(struct fb_info *info) -{ - struct imxfb_info *fbi = info->par; - - fbi->map_size = PAGE_ALIGN(info->fix.smem_len); - fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, - &fbi->map_dma,GFP_KERNEL); - - if (fbi->map_cpu) { - info->screen_base = fbi->map_cpu; - fbi->screen_cpu = fbi->map_cpu; - fbi->screen_dma = fbi->map_dma; - info->fix.smem_start = fbi->screen_dma; - } - - return fbi->map_cpu ? 0 : -ENOMEM; -} - static int __init imxfb_probe(struct platform_device *pdev) { struct imxfb_info *fbi; struct fb_info *info; - struct imxfb_mach_info *inf; + struct imx_fb_platform_data *pdata; struct resource *res; int ret; printk("i.MX Framebuffer driver\n"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if(!res) + if (!res) return -ENODEV; - inf = pdev->dev.platform_data; - if(!inf) { + pdata = pdev->dev.platform_data; + if (!pdata) { dev_err(&pdev->dev,"No platform_data available\n"); return -ENOMEM; } info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev); - if(!info) + if (!info) return -ENOMEM; fbi = info->par; platform_set_drvdata(pdev, info); - ret = imxfb_init_fbinfo(&pdev->dev); - if( ret < 0 ) + ret = imxfb_init_fbinfo(pdev); + if (ret < 0) goto failed_init; - res = request_mem_region(res->start, res->end - res->start + 1, "IMXFB"); + res = request_mem_region(res->start, resource_size(res), + DRIVER_NAME); if (!res) { ret = -EBUSY; - goto failed_regs; + goto failed_req; + } + + fbi->regs = ioremap(res->start, resource_size(res)); + if (fbi->regs == NULL) { + printk(KERN_ERR"Cannot map frame buffer registers\n"); + goto failed_ioremap; } - if (!inf->fixed_screen_cpu) { - ret = imxfb_map_video_memory(info); - if (ret) { + if (!pdata->fixed_screen_cpu) { + fbi->map_size = PAGE_ALIGN(info->fix.smem_len); + fbi->map_cpu = dma_alloc_writecombine(&pdev->dev, + fbi->map_size, &fbi->map_dma, GFP_KERNEL); + + if (!fbi->map_cpu) { dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret); ret = -ENOMEM; goto failed_map; } + + info->screen_base = fbi->map_cpu; + fbi->screen_cpu = fbi->map_cpu; + fbi->screen_dma = fbi->map_dma; + info->fix.smem_start = fbi->screen_dma; } else { /* Fixed framebuffer mapping enables location of the screen in eSRAM */ - fbi->map_cpu = inf->fixed_screen_cpu; - fbi->map_dma = inf->fixed_screen_dma; + fbi->map_cpu = pdata->fixed_screen_cpu; + fbi->map_dma = pdata->fixed_screen_dma; info->screen_base = fbi->map_cpu; fbi->screen_cpu = fbi->map_cpu; fbi->screen_dma = fbi->map_dma; @@ -590,12 +656,10 @@ static int __init imxfb_probe(struct platform_device *pdev) */ imxfb_check_var(&info->var, info); - ret = fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0); + ret = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0); if (ret < 0) goto failed_cmap; - imxfb_setup_gpio(fbi); - imxfb_set_par(info); ret = register_framebuffer(info); if (ret < 0) { @@ -610,20 +674,22 @@ static int __init imxfb_probe(struct platform_device *pdev) failed_register: fb_dealloc_cmap(&info->cmap); failed_cmap: - if (!inf->fixed_screen_cpu) + if (!pdata->fixed_screen_cpu) dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, - fbi->map_dma); + fbi->map_dma); failed_map: - kfree(info->pseudo_palette); -failed_regs: + iounmap(fbi->regs); +failed_ioremap: release_mem_region(res->start, res->end - res->start); +failed_req: + kfree(info->pseudo_palette); failed_init: platform_set_drvdata(pdev, NULL); framebuffer_release(info); return ret; } -static int imxfb_remove(struct platform_device *pdev) +static int __devexit imxfb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); struct imxfb_info *fbi = info->par; @@ -639,6 +705,7 @@ static int imxfb_remove(struct platform_device *pdev) kfree(info->pseudo_palette); framebuffer_release(info); + iounmap(fbi->regs); release_mem_region(res->start, res->end - res->start + 1); platform_set_drvdata(pdev, NULL); @@ -653,19 +720,18 @@ void imxfb_shutdown(struct platform_device * dev) } static struct platform_driver imxfb_driver = { - .probe = imxfb_probe, .suspend = imxfb_suspend, .resume = imxfb_resume, - .remove = imxfb_remove, + .remove = __devexit_p(imxfb_remove), .shutdown = imxfb_shutdown, .driver = { - .name = "imx-fb", + .name = DRIVER_NAME, }, }; int __init imxfb_init(void) { - return platform_driver_register(&imxfb_driver); + return platform_driver_probe(&imxfb_driver, imxfb_probe); } static void __exit imxfb_cleanup(void) diff --git a/drivers/video/imxfb.h b/drivers/video/imxfb.h deleted file mode 100644 index e837a8b48eb8..000000000000 --- a/drivers/video/imxfb.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * linux/drivers/video/imxfb.h - * - * Freescale i.MX Frame Buffer device driver - * - * Copyright (C) 2004 S.Hauer, Pengutronix - * - * Copyright (C) 1999 Eric A. Thomas - * Based on acornfb.c Copyright (C) Russell King. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -/* - * These are the bitfields for each - * display depth that we support. - */ -struct imxfb_rgb { - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; -}; - -#define RGB_16 (0) -#define RGB_8 (1) -#define NR_RGB 2 - -struct imxfb_info { - struct device *dev; - struct imxfb_rgb *rgb[NR_RGB]; - - u_int max_bpp; - u_int max_xres; - u_int max_yres; - - /* - * These are the addresses we mapped - * the framebuffer memory region to. - */ - dma_addr_t map_dma; - u_char * map_cpu; - u_int map_size; - - u_char * screen_cpu; - dma_addr_t screen_dma; - u_int palette_size; - - dma_addr_t dbar1; - dma_addr_t dbar2; - - u_int pcr; - u_int pwmr; - u_int lscr1; - u_int dmacr; - u_int cmap_inverse:1, - cmap_static:1, - unused:30; - - void (*lcd_power)(int); - void (*backlight_power)(int); -}; - -#define IMX_NAME "IMX" - -/* - * Minimum X and Y resolutions - */ -#define MIN_XRES 64 -#define MIN_YRES 64 - diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index cc59c52e1103..48ff701d3a72 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -20,6 +20,16 @@ * * linux-arm-kernel@lists.arm.linux.org.uk * + * Add support for overlay1 and overlay2 based on pxafb_overlay.c: + * + * Copyright (C) 2004, Intel Corporation + * + * 2003/08/27: <yu.tang@intel.com> + * 2004/03/10: <stanley.cai@intel.com> + * 2004/10/28: <yan.yin@intel.com> + * + * Copyright (C) 2006-2008 Marvell International Ltd. + * All Rights Reserved */ #include <linux/module.h> @@ -50,7 +60,6 @@ #include <asm/irq.h> #include <asm/div64.h> #include <mach/pxa-regs.h> -#include <mach/pxa2xx-gpio.h> #include <mach/bitfield.h> #include <mach/pxafb.h> @@ -67,14 +76,16 @@ LCCR0_SFM | LCCR0_LDM | LCCR0_ENB) #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\ - LCCR3_PCD | LCCR3_BPP) - -static void (*pxafb_backlight_power)(int); -static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *); + LCCR3_PCD | LCCR3_BPP(0xf)) static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *); static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); +static void setup_base_frame(struct pxafb_info *fbi, int branch); +static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, + unsigned long offset, size_t size); + +static unsigned long video_mem_size = 0; static inline unsigned long lcd_readl(struct pxafb_info *fbi, unsigned int off) @@ -156,6 +167,12 @@ pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, val |= ((blue >> 8) & 0x000000fc); ((u32 *)(fbi->palette_cpu))[regno] = val; break; + case LCCR4_PAL_FOR_3: + val = ((red << 8) & 0x00ff0000); + val |= ((green >> 0) & 0x0000ff00); + val |= ((blue >> 8) & 0x000000ff); + ((u32 *)(fbi->palette_cpu))[regno] = val; + break; } return 0; @@ -216,37 +233,110 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return ret; } -/* - * pxafb_bpp_to_lccr3(): - * Convert a bits per pixel value to the correct bit pattern for LCCR3 - */ -static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var) +/* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */ +static inline int var_to_depth(struct fb_var_screeninfo *var) { - int ret = 0; + return var->red.length + var->green.length + + var->blue.length + var->transp.length; +} + +/* calculate 4-bit BPP value for LCCR3 and OVLxC1 */ +static int pxafb_var_to_bpp(struct fb_var_screeninfo *var) +{ + int bpp = -EINVAL; + switch (var->bits_per_pixel) { - case 1: ret = LCCR3_1BPP; break; - case 2: ret = LCCR3_2BPP; break; - case 4: ret = LCCR3_4BPP; break; - case 8: ret = LCCR3_8BPP; break; - case 16: ret = LCCR3_16BPP; break; + case 1: bpp = 0; break; + case 2: bpp = 1; break; + case 4: bpp = 2; break; + case 8: bpp = 3; break; + case 16: bpp = 4; break; case 24: - switch (var->red.length + var->green.length + - var->blue.length + var->transp.length) { - case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break; - case 19: ret = LCCR3_19BPP_P; break; + switch (var_to_depth(var)) { + case 18: bpp = 6; break; /* 18-bits/pixel packed */ + case 19: bpp = 8; break; /* 19-bits/pixel packed */ + case 24: bpp = 9; break; } break; case 32: - switch (var->red.length + var->green.length + - var->blue.length + var->transp.length) { - case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break; - case 19: ret = LCCR3_19BPP; break; - case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break; - case 25: ret = LCCR3_25BPP; break; + switch (var_to_depth(var)) { + case 18: bpp = 5; break; /* 18-bits/pixel unpacked */ + case 19: bpp = 7; break; /* 19-bits/pixel unpacked */ + case 25: bpp = 10; break; } break; } - return ret; + return bpp; +} + +/* + * pxafb_var_to_lccr3(): + * Convert a bits per pixel value to the correct bit pattern for LCCR3 + * + * NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an + * implication of the acutal use of transparency bit, which we handle it + * here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel + * Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP. + * + * Transparency for palette pixel formats is not supported at the moment. + */ +static uint32_t pxafb_var_to_lccr3(struct fb_var_screeninfo *var) +{ + int bpp = pxafb_var_to_bpp(var); + uint32_t lccr3; + + if (bpp < 0) + return 0; + + lccr3 = LCCR3_BPP(bpp); + + switch (var_to_depth(var)) { + case 16: lccr3 |= var->transp.length ? LCCR3_PDFOR_3 : 0; break; + case 18: lccr3 |= LCCR3_PDFOR_3; break; + case 24: lccr3 |= var->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3; + break; + case 19: + case 25: lccr3 |= LCCR3_PDFOR_0; break; + } + return lccr3; +} + +#define SET_PIXFMT(v, r, g, b, t) \ +({ \ + (v)->transp.offset = (t) ? (r) + (g) + (b) : 0; \ + (v)->transp.length = (t) ? (t) : 0; \ + (v)->blue.length = (b); (v)->blue.offset = 0; \ + (v)->green.length = (g); (v)->green.offset = (b); \ + (v)->red.length = (r); (v)->red.offset = (b) + (g); \ +}) + +/* set the RGBT bitfields of fb_var_screeninf according to + * var->bits_per_pixel and given depth + */ +static void pxafb_set_pixfmt(struct fb_var_screeninfo *var, int depth) +{ + if (depth == 0) + depth = var->bits_per_pixel; + + if (var->bits_per_pixel < 16) { + /* indexed pixel formats */ + var->red.offset = 0; var->red.length = 8; + var->green.offset = 0; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + var->transp.offset = 0; var->transp.length = 8; + } + + switch (depth) { + case 16: var->transp.length ? + SET_PIXFMT(var, 5, 5, 5, 1) : /* RGBT555 */ + SET_PIXFMT(var, 5, 6, 5, 0); break; /* RGB565 */ + case 18: SET_PIXFMT(var, 6, 6, 6, 0); break; /* RGB666 */ + case 19: SET_PIXFMT(var, 6, 6, 6, 1); break; /* RGBT666 */ + case 24: var->transp.length ? + SET_PIXFMT(var, 8, 8, 7, 1) : /* RGBT887 */ + SET_PIXFMT(var, 8, 8, 8, 0); break; /* RGB888 */ + case 25: SET_PIXFMT(var, 8, 8, 8, 1); break; /* RGBT888 */ + } } #ifdef CONFIG_CPU_FREQ @@ -308,8 +398,49 @@ static void pxafb_setmode(struct fb_var_screeninfo *var, var->lower_margin = mode->lower_margin; var->sync = mode->sync; var->grayscale = mode->cmap_greyscale; - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; + + /* set the initial RGBA bitfields */ + pxafb_set_pixfmt(var, mode->depth); +} + +static int pxafb_adjust_timing(struct pxafb_info *fbi, + struct fb_var_screeninfo *var) +{ + int line_length; + + var->xres = max_t(int, var->xres, MIN_XRES); + var->yres = max_t(int, var->yres, MIN_YRES); + + if (!(fbi->lccr0 & LCCR0_LCDT)) { + clamp_val(var->hsync_len, 1, 64); + clamp_val(var->vsync_len, 1, 64); + clamp_val(var->left_margin, 1, 255); + clamp_val(var->right_margin, 1, 255); + clamp_val(var->upper_margin, 1, 255); + clamp_val(var->lower_margin, 1, 255); + } + + /* make sure each line is aligned on word boundary */ + line_length = var->xres * var->bits_per_pixel / 8; + line_length = ALIGN(line_length, 4); + var->xres = line_length * 8 / var->bits_per_pixel; + + /* we don't support xpan, force xres_virtual to be equal to xres */ + var->xres_virtual = var->xres; + + if (var->accel_flags & FB_ACCELF_TEXT) + var->yres_virtual = fbi->fb.fix.smem_len / line_length; + else + var->yres_virtual = max(var->yres_virtual, var->yres); + + /* check for limits */ + if (var->xres > MAX_XRES || var->yres > MAX_YRES) + return -EINVAL; + + if (var->yres > var->yres_virtual) + return -EINVAL; + + return 0; } /* @@ -325,11 +456,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct pxafb_info *fbi = (struct pxafb_info *)info; struct pxafb_mach_info *inf = fbi->dev->platform_data; - - if (var->xres < MIN_XRES) - var->xres = MIN_XRES; - if (var->yres < MIN_YRES) - var->yres = MIN_YRES; + int err; if (inf->fixed_modes) { struct pxafb_mode_info *mode; @@ -338,74 +465,18 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (!mode) return -EINVAL; pxafb_setmode(var, mode); - } else { - if (var->xres > inf->modes->xres) - return -EINVAL; - if (var->yres > inf->modes->yres) - return -EINVAL; - if (var->bits_per_pixel > inf->modes->bpp) - return -EINVAL; } - var->xres_virtual = - max(var->xres_virtual, var->xres); - var->yres_virtual = - max(var->yres_virtual, var->yres); + /* do a test conversion to BPP fields to check the color formats */ + err = pxafb_var_to_bpp(var); + if (err < 0) + return err; - /* - * Setup the RGB parameters for this display. - * - * The pixel packing format is described on page 7-11 of the - * PXA2XX Developer's Manual. - */ - if (var->bits_per_pixel == 16) { - var->red.offset = 11; var->red.length = 5; - var->green.offset = 5; var->green.length = 6; - var->blue.offset = 0; var->blue.length = 5; - var->transp.offset = var->transp.length = 0; - } else if (var->bits_per_pixel > 16) { - struct pxafb_mode_info *mode; + pxafb_set_pixfmt(var, var_to_depth(var)); - mode = pxafb_getmode(inf, var); - if (!mode) - return -EINVAL; - - switch (mode->depth) { - case 18: /* RGB666 */ - var->transp.offset = var->transp.length = 0; - var->red.offset = 12; var->red.length = 6; - var->green.offset = 6; var->green.length = 6; - var->blue.offset = 0; var->blue.length = 6; - break; - case 19: /* RGBT666 */ - var->transp.offset = 18; var->transp.length = 1; - var->red.offset = 12; var->red.length = 6; - var->green.offset = 6; var->green.length = 6; - var->blue.offset = 0; var->blue.length = 6; - break; - case 24: /* RGB888 */ - var->transp.offset = var->transp.length = 0; - var->red.offset = 16; var->red.length = 8; - var->green.offset = 8; var->green.length = 8; - var->blue.offset = 0; var->blue.length = 8; - break; - case 25: /* RGBT888 */ - var->transp.offset = 24; var->transp.length = 1; - var->red.offset = 16; var->red.length = 8; - var->green.offset = 8; var->green.length = 8; - var->blue.offset = 0; var->blue.length = 8; - break; - default: - return -EINVAL; - } - } else { - var->red.offset = var->green.offset = 0; - var->blue.offset = var->transp.offset = 0; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - var->transp.length = 0; - } + err = pxafb_adjust_timing(fbi, var); + if (err) + return err; #ifdef CONFIG_CPU_FREQ pr_debug("pxafb: dma period = %d ps\n", @@ -415,11 +486,6 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static inline void pxafb_set_truecolor(u_int is_true_color) -{ - /* do your machine-specific setup if needed */ -} - /* * pxafb_set_par(): * Set the user defined part of the display for the specified console @@ -452,11 +518,6 @@ static int pxafb_set_par(struct fb_info *info) fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0]; - /* - * Set (any) board control register to handle new color depth - */ - pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); - if (fbi->fb.var.bits_per_pixel >= 16) fb_dealloc_cmap(&fbi->fb.cmap); else @@ -467,6 +528,24 @@ static int pxafb_set_par(struct fb_info *info) return 0; } +static int pxafb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct pxafb_info *fbi = (struct pxafb_info *)info; + int dma = DMA_MAX + DMA_BASE; + + if (fbi->state != C_ENABLE) + return 0; + + setup_base_frame(fbi, 1); + + if (fbi->lccr0 & LCCR0_SDS) + lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1); + + lcd_writel(fbi, FBR0, fbi->fdadr[dma] | 0x1); + return 0; +} + /* * pxafb_blank(): * Blank the display by setting all palette values to zero. Note, the @@ -502,32 +581,342 @@ static int pxafb_blank(int blank, struct fb_info *info) return 0; } -static int pxafb_mmap(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - unsigned long off = vma->vm_pgoff << PAGE_SHIFT; - - if (off < info->fix.smem_len) { - vma->vm_pgoff += fbi->video_offset / PAGE_SIZE; - return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu, - fbi->map_dma, fbi->map_size); - } - return -EINVAL; -} - static struct fb_ops pxafb_ops = { .owner = THIS_MODULE, .fb_check_var = pxafb_check_var, .fb_set_par = pxafb_set_par, + .fb_pan_display = pxafb_pan_display, .fb_setcolreg = pxafb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = pxafb_blank, - .fb_mmap = pxafb_mmap, }; +#ifdef CONFIG_FB_PXA_OVERLAY +static void overlay1fb_setup(struct pxafb_layer *ofb) +{ + int size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual; + unsigned long start = ofb->video_mem_phys; + setup_frame_dma(ofb->fbi, DMA_OV1, PAL_NONE, start, size); +} + +/* Depending on the enable status of overlay1/2, the DMA should be + * updated from FDADRx (when disabled) or FBRx (when enabled). + */ +static void overlay1fb_enable(struct pxafb_layer *ofb) +{ + int enabled = lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN; + uint32_t fdadr1 = ofb->fbi->fdadr[DMA_OV1] | (enabled ? 0x1 : 0); + + lcd_writel(ofb->fbi, enabled ? FBR1 : FDADR1, fdadr1); + lcd_writel(ofb->fbi, OVL1C2, ofb->control[1]); + lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] | OVLxC1_OEN); +} + +static void overlay1fb_disable(struct pxafb_layer *ofb) +{ + uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); + + lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN); + + lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1)); + lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1)); + lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3); + + if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0) + pr_warning("%s: timeout disabling overlay1\n", __func__); + + lcd_writel(ofb->fbi, LCCR5, lccr5); +} + +static void overlay2fb_setup(struct pxafb_layer *ofb) +{ + int size, div = 1, pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd); + unsigned long start[3] = { ofb->video_mem_phys, 0, 0 }; + + if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) { + size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual; + setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size); + } else { + size = ofb->fb.var.xres_virtual * ofb->fb.var.yres_virtual; + switch (pfor) { + case OVERLAY_FORMAT_YUV444_PLANAR: div = 1; break; + case OVERLAY_FORMAT_YUV422_PLANAR: div = 2; break; + case OVERLAY_FORMAT_YUV420_PLANAR: div = 4; break; + } + start[1] = start[0] + size; + start[2] = start[1] + size / div; + setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size); + setup_frame_dma(ofb->fbi, DMA_OV2_Cb, -1, start[1], size / div); + setup_frame_dma(ofb->fbi, DMA_OV2_Cr, -1, start[2], size / div); + } +} + +static void overlay2fb_enable(struct pxafb_layer *ofb) +{ + int pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd); + int enabled = lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN; + uint32_t fdadr2 = ofb->fbi->fdadr[DMA_OV2_Y] | (enabled ? 0x1 : 0); + uint32_t fdadr3 = ofb->fbi->fdadr[DMA_OV2_Cb] | (enabled ? 0x1 : 0); + uint32_t fdadr4 = ofb->fbi->fdadr[DMA_OV2_Cr] | (enabled ? 0x1 : 0); + + if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) + lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2); + else { + lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2); + lcd_writel(ofb->fbi, enabled ? FBR3 : FDADR3, fdadr3); + lcd_writel(ofb->fbi, enabled ? FBR4 : FDADR4, fdadr4); + } + lcd_writel(ofb->fbi, OVL2C2, ofb->control[1]); + lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] | OVLxC1_OEN); +} + +static void overlay2fb_disable(struct pxafb_layer *ofb) +{ + uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); + + lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN); + + lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2)); + lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2)); + lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y] | 0x3); + lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3); + lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3); + + if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0) + pr_warning("%s: timeout disabling overlay2\n", __func__); +} + +static struct pxafb_layer_ops ofb_ops[] = { + [0] = { + .enable = overlay1fb_enable, + .disable = overlay1fb_disable, + .setup = overlay1fb_setup, + }, + [1] = { + .enable = overlay2fb_enable, + .disable = overlay2fb_disable, + .setup = overlay2fb_setup, + }, +}; + +static int overlayfb_open(struct fb_info *info, int user) +{ + struct pxafb_layer *ofb = (struct pxafb_layer *)info; + + /* no support for framebuffer console on overlay */ + if (user == 0) + return -ENODEV; + + /* allow only one user at a time */ + if (atomic_inc_and_test(&ofb->usage)) + return -EBUSY; + + /* unblank the base framebuffer */ + fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK); + return 0; +} + +static int overlayfb_release(struct fb_info *info, int user) +{ + struct pxafb_layer *ofb = (struct pxafb_layer*) info; + + atomic_dec(&ofb->usage); + ofb->ops->disable(ofb); + + free_pages_exact(ofb->video_mem, ofb->video_mem_size); + ofb->video_mem = NULL; + ofb->video_mem_size = 0; + return 0; +} + +static int overlayfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct pxafb_layer *ofb = (struct pxafb_layer *)info; + struct fb_var_screeninfo *base_var = &ofb->fbi->fb.var; + int xpos, ypos, pfor, bpp; + + xpos = NONSTD_TO_XPOS(var->nonstd); + ypos = NONSTD_TO_XPOS(var->nonstd); + pfor = NONSTD_TO_PFOR(var->nonstd); + + bpp = pxafb_var_to_bpp(var); + if (bpp < 0) + return -EINVAL; + + /* no support for YUV format on overlay1 */ + if (ofb->id == OVERLAY1 && pfor != 0) + return -EINVAL; + + /* for YUV packed formats, bpp = 'minimum bpp of YUV components' */ + switch (pfor) { + case OVERLAY_FORMAT_RGB: + bpp = pxafb_var_to_bpp(var); + if (bpp < 0) + return -EINVAL; + + pxafb_set_pixfmt(var, var_to_depth(var)); + break; + case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break; + case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 8; break; + case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 4; break; + case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 2; break; + default: + return -EINVAL; + } + + /* each line must start at a 32-bit word boundary */ + if ((xpos * bpp) % 32) + return -EINVAL; + + /* xres must align on 32-bit word boundary */ + var->xres = roundup(var->xres * bpp, 32) / bpp; + + if ((xpos + var->xres > base_var->xres) || + (ypos + var->yres > base_var->yres)) + return -EINVAL; + + var->xres_virtual = var->xres; + var->yres_virtual = max(var->yres, var->yres_virtual); + return 0; +} + +static int overlayfb_map_video_memory(struct pxafb_layer *ofb) +{ + struct fb_var_screeninfo *var = &ofb->fb.var; + int pfor = NONSTD_TO_PFOR(var->nonstd); + int size, bpp = 0; + + switch (pfor) { + case OVERLAY_FORMAT_RGB: bpp = var->bits_per_pixel; break; + case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break; + case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 24; break; + case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 16; break; + case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 12; break; + } + + ofb->fb.fix.line_length = var->xres_virtual * bpp / 8; + + size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual); + + /* don't re-allocate if the original video memory is enough */ + if (ofb->video_mem) { + if (ofb->video_mem_size >= size) + return 0; + + free_pages_exact(ofb->video_mem, ofb->video_mem_size); + } + + ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); + if (ofb->video_mem == NULL) + return -ENOMEM; + + ofb->video_mem_phys = virt_to_phys(ofb->video_mem); + ofb->video_mem_size = size; + + ofb->fb.fix.smem_start = ofb->video_mem_phys; + ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; + ofb->fb.screen_base = ofb->video_mem; + return 0; +} + +static int overlayfb_set_par(struct fb_info *info) +{ + struct pxafb_layer *ofb = (struct pxafb_layer *)info; + struct fb_var_screeninfo *var = &info->var; + int xpos, ypos, pfor, bpp, ret; + + ret = overlayfb_map_video_memory(ofb); + if (ret) + return ret; + + bpp = pxafb_var_to_bpp(var); + xpos = NONSTD_TO_XPOS(var->nonstd); + ypos = NONSTD_TO_XPOS(var->nonstd); + pfor = NONSTD_TO_PFOR(var->nonstd); + + ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) | + OVLxC1_BPP(bpp); + ofb->control[1] = OVLxC2_XPOS(xpos) | OVLxC2_YPOS(ypos); + + if (ofb->id == OVERLAY2) + ofb->control[1] |= OVL2C2_PFOR(pfor); + + ofb->ops->setup(ofb); + ofb->ops->enable(ofb); + return 0; +} + +static struct fb_ops overlay_fb_ops = { + .owner = THIS_MODULE, + .fb_open = overlayfb_open, + .fb_release = overlayfb_release, + .fb_check_var = overlayfb_check_var, + .fb_set_par = overlayfb_set_par, +}; + +static void __devinit init_pxafb_overlay(struct pxafb_info *fbi, + struct pxafb_layer *ofb, int id) +{ + sprintf(ofb->fb.fix.id, "overlay%d", id + 1); + + ofb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + ofb->fb.fix.xpanstep = 0; + ofb->fb.fix.ypanstep = 1; + + ofb->fb.var.activate = FB_ACTIVATE_NOW; + ofb->fb.var.height = -1; + ofb->fb.var.width = -1; + ofb->fb.var.vmode = FB_VMODE_NONINTERLACED; + + ofb->fb.fbops = &overlay_fb_ops; + ofb->fb.flags = FBINFO_FLAG_DEFAULT; + ofb->fb.node = -1; + ofb->fb.pseudo_palette = NULL; + + ofb->id = id; + ofb->ops = &ofb_ops[id]; + atomic_set(&ofb->usage, 0); + ofb->fbi = fbi; + init_completion(&ofb->branch_done); +} + +static int __devinit pxafb_overlay_init(struct pxafb_info *fbi) +{ + int i, ret; + + for (i = 0; i < 2; i++) { + init_pxafb_overlay(fbi, &fbi->overlay[i], i); + ret = register_framebuffer(&fbi->overlay[i].fb); + if (ret) { + dev_err(fbi->dev, "failed to register overlay %d\n", i); + return ret; + } + } + + /* mask all IU/BS/EOF/SOF interrupts */ + lcd_writel(fbi, LCCR5, ~0); + + /* place overlay(s) on top of base */ + fbi->lccr0 |= LCCR0_OUC; + pr_info("PXA Overlay driver loaded successfully!\n"); + return 0; +} + +static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi) +{ + int i; + + for (i = 0; i < 2; i++) + unregister_framebuffer(&fbi->overlay[i].fb); +} +#else +static inline void pxafb_overlay_init(struct pxafb_info *fbi) {} +static inline void pxafb_overlay_exit(struct pxafb_info *fbi) {} +#endif /* CONFIG_FB_PXA_OVERLAY */ + /* * Calculate the PCD value from the clock rate (in picoseconds). * We take account of the PPCR clock setting. @@ -607,22 +996,22 @@ unsigned long pxafb_get_hsync_time(struct device *dev) EXPORT_SYMBOL(pxafb_get_hsync_time); static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, - unsigned int offset, size_t size) + unsigned long start, size_t size) { struct pxafb_dma_descriptor *dma_desc, *pal_desc; unsigned int dma_desc_off, pal_desc_off; - if (dma < 0 || dma >= DMA_MAX) + if (dma < 0 || dma >= DMA_MAX * 2) return -EINVAL; dma_desc = &fbi->dma_buff->dma_desc[dma]; dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]); - dma_desc->fsadr = fbi->screen_dma + offset; + dma_desc->fsadr = start; dma_desc->fidr = 0; dma_desc->ldcmd = size; - if (pal < 0 || pal >= PAL_MAX) { + if (pal < 0 || pal >= PAL_MAX * 2) { dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off; fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off; } else { @@ -648,6 +1037,27 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, return 0; } +static void setup_base_frame(struct pxafb_info *fbi, int branch) +{ + struct fb_var_screeninfo *var = &fbi->fb.var; + struct fb_fix_screeninfo *fix = &fbi->fb.fix; + int nbytes, dma, pal, bpp = var->bits_per_pixel; + unsigned long offset; + + dma = DMA_BASE + (branch ? DMA_MAX : 0); + pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0); + + nbytes = fix->line_length * var->yres; + offset = fix->line_length * var->yoffset + fbi->video_mem_phys; + + if (fbi->lccr0 & LCCR0_SDS) { + nbytes = nbytes / 2; + setup_frame_dma(fbi, dma + 1, PAL_NONE, offset + nbytes, nbytes); + } + + setup_frame_dma(fbi, dma, pal, offset, nbytes); +} + #ifdef CONFIG_FB_PXA_SMARTPANEL static int setup_smart_dma(struct pxafb_info *fbi) { @@ -701,6 +1111,7 @@ int pxafb_smart_flush(struct fb_info *info) lcd_writel(fbi, LCCR1, fbi->reg_lccr1); lcd_writel(fbi, LCCR2, fbi->reg_lccr2); lcd_writel(fbi, LCCR3, fbi->reg_lccr3); + lcd_writel(fbi, LCCR4, fbi->reg_lccr4); lcd_writel(fbi, FDADR0, fbi->fdadr[0]); lcd_writel(fbi, FDADR6, fbi->fdadr[6]); @@ -727,12 +1138,19 @@ int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds) int i; struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb); - /* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */ - for (i = 0; i < n_cmds; i++) { + for (i = 0; i < n_cmds; i++, cmds++) { + /* if it is a software delay, flush and delay */ + if ((*cmds & 0xff00) == SMART_CMD_DELAY) { + pxafb_smart_flush(info); + mdelay(*cmds & 0xff); + continue; + } + + /* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */ if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8) pxafb_smart_flush(info); - fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds++; + fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds; } return 0; @@ -764,7 +1182,9 @@ static void setup_smart_timing(struct pxafb_info *fbi, LCCR1_HorSnchWdth(__smart_timing(t3, lclk)); fbi->reg_lccr2 = LCCR2_DisHght(var->yres); - fbi->reg_lccr3 = LCCR3_PixClkDiv(__smart_timing(t4, lclk)); + fbi->reg_lccr3 = fbi->lccr3 | LCCR3_PixClkDiv(__smart_timing(t4, lclk)); + fbi->reg_lccr3 |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HSP : 0; + fbi->reg_lccr3 |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VSP : 0; /* FIXME: make this configurable */ fbi->reg_cmdcr = 1; @@ -789,11 +1209,15 @@ static int pxafb_smart_thread(void *arg) if (try_to_freeze()) continue; + mutex_lock(&fbi->ctrlr_lock); + if (fbi->state == C_ENABLE) { inf->smart_update(&fbi->fb); complete(&fbi->refresh_done); } + mutex_unlock(&fbi->ctrlr_lock); + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(30 * HZ / 1000); } @@ -804,16 +1228,22 @@ static int pxafb_smart_thread(void *arg) static int pxafb_smart_init(struct pxafb_info *fbi) { - if (!(fbi->lccr0 | LCCR0_LCDT)) + if (!(fbi->lccr0 & LCCR0_LCDT)) return 0; + fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; + fbi->n_smart_cmds = 0; + + init_completion(&fbi->command_done); + init_completion(&fbi->refresh_done); + fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi, "lcd_refresh"); if (IS_ERR(fbi->smart_thread)) { - printk(KERN_ERR "%s: unable to create kernel thread\n", - __func__); + pr_err("%s: unable to create kernel thread\n", __func__); return PTR_ERR(fbi->smart_thread); } + return 0; } #else @@ -826,7 +1256,9 @@ int pxafb_smart_flush(struct fb_info *info) { return 0; } -#endif /* CONFIG_FB_SMART_PANEL */ + +static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; } +#endif /* CONFIG_FB_PXA_SMARTPANEL */ static void setup_parallel_timing(struct pxafb_info *fbi, struct fb_var_screeninfo *var) @@ -874,51 +1306,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi) { u_long flags; - size_t nbytes; - -#if DEBUG_VAR - if (!(fbi->lccr0 & LCCR0_LCDT)) { - if (var->xres < 16 || var->xres > 1024) - printk(KERN_ERR "%s: invalid xres %d\n", - fbi->fb.fix.id, var->xres); - switch (var->bits_per_pixel) { - case 1: - case 2: - case 4: - case 8: - case 16: - case 24: - case 32: - break; - default: - printk(KERN_ERR "%s: invalid bit depth %d\n", - fbi->fb.fix.id, var->bits_per_pixel); - break; - } - if (var->hsync_len < 1 || var->hsync_len > 64) - printk(KERN_ERR "%s: invalid hsync_len %d\n", - fbi->fb.fix.id, var->hsync_len); - if (var->left_margin < 1 || var->left_margin > 255) - printk(KERN_ERR "%s: invalid left_margin %d\n", - fbi->fb.fix.id, var->left_margin); - if (var->right_margin < 1 || var->right_margin > 255) - printk(KERN_ERR "%s: invalid right_margin %d\n", - fbi->fb.fix.id, var->right_margin); - if (var->yres < 1 || var->yres > 1024) - printk(KERN_ERR "%s: invalid yres %d\n", - fbi->fb.fix.id, var->yres); - if (var->vsync_len < 1 || var->vsync_len > 64) - printk(KERN_ERR "%s: invalid vsync_len %d\n", - fbi->fb.fix.id, var->vsync_len); - if (var->upper_margin < 0 || var->upper_margin > 255) - printk(KERN_ERR "%s: invalid upper_margin %d\n", - fbi->fb.fix.id, var->upper_margin); - if (var->lower_margin < 0 || var->lower_margin > 255) - printk(KERN_ERR "%s: invalid lower_margin %d\n", - fbi->fb.fix.id, var->lower_margin); - } -#endif /* Update shadow copy atomically */ local_irq_save(flags); @@ -929,23 +1317,13 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, #endif setup_parallel_timing(fbi, var); + setup_base_frame(fbi, 0); + fbi->reg_lccr0 = fbi->lccr0 | (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM | LCCR0_OUM); - fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var); - - nbytes = var->yres * fbi->fb.fix.line_length; - - if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) { - nbytes = nbytes / 2; - setup_frame_dma(fbi, DMA_LOWER, PAL_NONE, nbytes, nbytes); - } - - if ((var->bits_per_pixel >= 16) || (fbi->lccr0 & LCCR0_LCDT)) - setup_frame_dma(fbi, DMA_BASE, PAL_NONE, 0, nbytes); - else - setup_frame_dma(fbi, DMA_BASE, PAL_BASE, 0, nbytes); + fbi->reg_lccr3 |= pxafb_var_to_lccr3(var); fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK; fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK); @@ -959,6 +1337,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) || (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) || (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) || + (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) || (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) || (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])) pxafb_schedule_work(fbi, C_REENABLE); @@ -976,67 +1355,16 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) { pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff"); - if (pxafb_backlight_power) - pxafb_backlight_power(on); + if (fbi->backlight_power) + fbi->backlight_power(on); } static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on) { pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff"); - if (pxafb_lcd_power) - pxafb_lcd_power(on, &fbi->fb.var); -} - -static void pxafb_setup_gpio(struct pxafb_info *fbi) -{ - int gpio, ldd_bits; - unsigned int lccr0 = fbi->lccr0; - - /* - * setup is based on type of panel supported - */ - - /* 4 bit interface */ - if ((lccr0 & LCCR0_CMS) == LCCR0_Mono && - (lccr0 & LCCR0_SDS) == LCCR0_Sngl && - (lccr0 & LCCR0_DPD) == LCCR0_4PixMono) - ldd_bits = 4; - - /* 8 bit interface */ - else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono && - ((lccr0 & LCCR0_SDS) == LCCR0_Dual || - (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) || - ((lccr0 & LCCR0_CMS) == LCCR0_Color && - (lccr0 & LCCR0_PAS) == LCCR0_Pas && - (lccr0 & LCCR0_SDS) == LCCR0_Sngl)) - ldd_bits = 8; - - /* 16 bit interface */ - else if ((lccr0 & LCCR0_CMS) == LCCR0_Color && - ((lccr0 & LCCR0_SDS) == LCCR0_Dual || - (lccr0 & LCCR0_PAS) == LCCR0_Act)) - ldd_bits = 16; - - else { - printk(KERN_ERR "pxafb_setup_gpio: unable to determine " - "bits per pixel\n"); - return; - } - - for (gpio = 58; ldd_bits; gpio++, ldd_bits--) - pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT); - /* 18 bit interface */ - if (fbi->fb.var.bits_per_pixel > 16) { - pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT); - pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT); - } - pxa_gpio_mode(GPIO74_LCD_FCLK_MD); - pxa_gpio_mode(GPIO75_LCD_LCLK_MD); - pxa_gpio_mode(GPIO76_LCD_PCLK_MD); - - if ((lccr0 & LCCR0_PAS) == 0) - pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); + if (fbi->lcd_power) + fbi->lcd_power(on, &fbi->fb.var); } static void pxafb_enable_controller(struct pxafb_info *fbi) @@ -1056,6 +1384,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) return; /* Sequence from 11.7.10 */ + lcd_writel(fbi, LCCR4, fbi->reg_lccr4); lcd_writel(fbi, LCCR3, fbi->reg_lccr3); lcd_writel(fbi, LCCR2, fbi->reg_lccr2); lcd_writel(fbi, LCCR1, fbi->reg_lccr1); @@ -1097,8 +1426,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) { struct pxafb_info *fbi = dev_id; - unsigned int lccr0, lcsr = lcd_readl(fbi, LCSR); + unsigned int lccr0, lcsr, lcsr1; + lcsr = lcd_readl(fbi, LCSR); if (lcsr & LCSR_LDD) { lccr0 = lcd_readl(fbi, LCCR0); lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM); @@ -1109,8 +1439,18 @@ static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) if (lcsr & LCSR_CMD_INT) complete(&fbi->command_done); #endif - lcd_writel(fbi, LCSR, lcsr); + +#ifdef CONFIG_FB_PXA_OVERLAY + lcsr1 = lcd_readl(fbi, LCSR1); + if (lcsr1 & LCSR1_BS(1)) + complete(&fbi->overlay[0].branch_done); + + if (lcsr1 & LCSR1_BS(2)) + complete(&fbi->overlay[1].branch_done); + + lcd_writel(fbi, LCSR1, lcsr1); +#endif return IRQ_HANDLED; } @@ -1181,7 +1521,6 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) if (old_state == C_ENABLE) { __pxafb_lcd_power(fbi, 0); pxafb_disable_controller(fbi); - pxafb_setup_gpio(fbi); pxafb_enable_controller(fbi); __pxafb_lcd_power(fbi, 1); } @@ -1204,7 +1543,6 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) */ if (old_state != C_ENABLE) { fbi->state = C_ENABLE; - pxafb_setup_gpio(fbi); pxafb_enable_controller(fbi); __pxafb_lcd_power(fbi, 1); __pxafb_backlight_power(fbi, 1); @@ -1303,77 +1641,34 @@ static int pxafb_resume(struct platform_device *dev) #define pxafb_resume NULL #endif -/* - * pxafb_map_video_memory(): - * Allocates the DRAM memory for the frame buffer. This buffer is - * remapped into a non-cached, non-buffered, memory region to - * allow palette and pixel writes to occur without flushing the - * cache. Once this area is remapped, all virtual memory - * access to the video memory should occur at the new region. - */ -static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi) +static int __devinit pxafb_init_video_memory(struct pxafb_info *fbi) { - /* - * We reserve one page for the palette, plus the size - * of the framebuffer. - */ - fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff)); - fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset); - fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, - &fbi->map_dma, GFP_KERNEL); - - if (fbi->map_cpu) { - /* prevent initial garbage on screen */ - memset(fbi->map_cpu, 0, fbi->map_size); - fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset; - fbi->screen_dma = fbi->map_dma + fbi->video_offset; - - /* - * FIXME: this is actually the wrong thing to place in - * smem_start. But fbdev suffers from the problem that - * it needs an API which doesn't exist (in this case, - * dma_writecombine_mmap) - */ - fbi->fb.fix.smem_start = fbi->screen_dma; - fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16; - - fbi->dma_buff = (void *) fbi->map_cpu; - fbi->dma_buff_phys = fbi->map_dma; - fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; + int size = PAGE_ALIGN(fbi->video_mem_size); - pr_debug("pxafb: palette_mem_size = 0x%08x\n", fbi->palette_size*sizeof(u16)); + fbi->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); + if (fbi->video_mem == NULL) + return -ENOMEM; -#ifdef CONFIG_FB_PXA_SMARTPANEL - fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; - fbi->n_smart_cmds = 0; -#endif - } - - return fbi->map_cpu ? 0 : -ENOMEM; -} + fbi->video_mem_phys = virt_to_phys(fbi->video_mem); + fbi->video_mem_size = size; -static void pxafb_decode_mode_info(struct pxafb_info *fbi, - struct pxafb_mode_info *modes, - unsigned int num_modes) -{ - unsigned int i, smemlen; - - pxafb_setmode(&fbi->fb.var, &modes[0]); + fbi->fb.fix.smem_start = fbi->video_mem_phys; + fbi->fb.fix.smem_len = fbi->video_mem_size; + fbi->fb.screen_base = fbi->video_mem; - for (i = 0; i < num_modes; i++) { - smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8; - if (smemlen > fbi->fb.fix.smem_len) - fbi->fb.fix.smem_len = smemlen; - } + return fbi->video_mem ? 0 : -ENOMEM; } static void pxafb_decode_mach_info(struct pxafb_info *fbi, struct pxafb_mach_info *inf) { unsigned int lcd_conn = inf->lcd_conn; + struct pxafb_mode_info *m; + int i; fbi->cmap_inverse = inf->cmap_inverse; fbi->cmap_static = inf->cmap_static; + fbi->lccr4 = inf->lccr4; switch (lcd_conn & LCD_TYPE_MASK) { case LCD_TYPE_MONO_STN: @@ -1398,7 +1693,6 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, /* fall back to backward compatibility way */ fbi->lccr0 = inf->lccr0; fbi->lccr3 = inf->lccr3; - fbi->lccr4 = inf->lccr4; goto decode_mode; } @@ -1412,7 +1706,22 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; decode_mode: - pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes); + pxafb_setmode(&fbi->fb.var, &inf->modes[0]); + + /* decide video memory size as follows: + * 1. default to mode of maximum resolution + * 2. allow platform to override + * 3. allow module parameter to override + */ + for (i = 0, m = &inf->modes[0]; i < inf->num_modes; i++, m++) + fbi->video_mem_size = max_t(size_t, fbi->video_mem_size, + m->xres * m->yres * m->bpp / 8); + + if (inf->video_mem_size > fbi->video_mem_size) + fbi->video_mem_size = inf->video_mem_size; + + if (video_mem_size > fbi->video_mem_size) + fbi->video_mem_size = video_mem_size; } static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) @@ -1429,7 +1738,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) memset(fbi, 0, sizeof(struct pxafb_info)); fbi->dev = dev; - fbi->clk = clk_get(dev, "LCDCLK"); + fbi->clk = clk_get(dev, NULL); if (IS_ERR(fbi->clk)) { kfree(fbi); return NULL; @@ -1440,7 +1749,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; fbi->fb.fix.type_aux = 0; fbi->fb.fix.xpanstep = 0; - fbi->fb.fix.ypanstep = 0; + fbi->fb.fix.ypanstep = 1; fbi->fb.fix.ywrapstep = 0; fbi->fb.fix.accel = FB_ACCEL_NONE; @@ -1448,7 +1757,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) fbi->fb.var.activate = FB_ACTIVATE_NOW; fbi->fb.var.height = -1; fbi->fb.var.width = -1; - fbi->fb.var.accel_flags = 0; + fbi->fb.var.accel_flags = FB_ACCELF_TEXT; fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; fbi->fb.fbops = &pxafb_ops; @@ -1468,10 +1777,6 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) INIT_WORK(&fbi->task, pxafb_task); mutex_init(&fbi->ctrlr_lock); init_completion(&fbi->disable_done); -#ifdef CONFIG_FB_PXA_SMARTPANEL - init_completion(&fbi->command_done); - init_completion(&fbi->refresh_done); -#endif return fbi; } @@ -1544,7 +1849,9 @@ static int __devinit parse_opt(struct device *dev, char *this_opt) s[0] = '\0'; - if (!strncmp(this_opt, "mode:", 5)) { + if (!strncmp(this_opt, "vmem:", 5)) { + video_mem_size = memparse(this_opt + 5, NULL); + } else if (!strncmp(this_opt, "mode:", 5)) { return parse_opt_mode(dev, this_opt); } else if (!strncmp(this_opt, "pixclock:", 9)) { mode->pixclock = simple_strtoul(this_opt+9, NULL, 0); @@ -1748,8 +2055,7 @@ static int __devinit pxafb_probe(struct platform_device *dev) ret = -EINVAL; goto failed; } - pxafb_backlight_power = inf->pxafb_backlight_power; - pxafb_lcd_power = inf->pxafb_lcd_power; + fbi = pxafb_init_fbinfo(&dev->dev); if (!fbi) { /* only reason for pxafb_init_fbinfo to fail is kmalloc */ @@ -1758,6 +2064,9 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed; } + fbi->backlight_power = inf->pxafb_backlight_power; + fbi->lcd_power = inf->pxafb_lcd_power; + r = platform_get_resource(dev, IORESOURCE_MEM, 0); if (r == NULL) { dev_err(&dev->dev, "no I/O memory resource defined\n"); @@ -1779,12 +2088,20 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed_free_res; } - /* Initialize video memory */ - ret = pxafb_map_video_memory(fbi); + fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff)); + fbi->dma_buff = dma_alloc_coherent(fbi->dev, fbi->dma_buff_size, + &fbi->dma_buff_phys, GFP_KERNEL); + if (fbi->dma_buff == NULL) { + dev_err(&dev->dev, "failed to allocate memory for DMA\n"); + ret = -ENOMEM; + goto failed_free_io; + } + + ret = pxafb_init_video_memory(fbi); if (ret) { dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret); ret = -ENOMEM; - goto failed_free_io; + goto failed_free_dma; } irq = platform_get_irq(dev, 0); @@ -1801,13 +2118,12 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed_free_mem; } -#ifdef CONFIG_FB_PXA_SMARTPANEL ret = pxafb_smart_init(fbi); if (ret) { dev_err(&dev->dev, "failed to initialize smartpanel\n"); goto failed_free_irq; } -#endif + /* * This makes sure that our colour bitfield * descriptors are correctly initialised. @@ -1833,6 +2149,8 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed_free_cmap; } + pxafb_overlay_init(fbi); + #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = pxafb_freq_transition; fbi->freq_policy.notifier_call = pxafb_freq_policy; @@ -1855,8 +2173,10 @@ failed_free_cmap: failed_free_irq: free_irq(irq, fbi); failed_free_mem: - dma_free_writecombine(&dev->dev, fbi->map_size, - fbi->map_cpu, fbi->map_dma); + free_pages_exact(fbi->video_mem, fbi->video_mem_size); +failed_free_dma: + dma_free_coherent(&dev->dev, fbi->dma_buff_size, + fbi->dma_buff, fbi->dma_buff_phys); failed_free_io: iounmap(fbi->mmio_base); failed_free_res: @@ -1881,6 +2201,7 @@ static int __devexit pxafb_remove(struct platform_device *dev) info = &fbi->fb; + pxafb_overlay_exit(fbi); unregister_framebuffer(info); pxafb_disable_controller(fbi); @@ -1891,8 +2212,10 @@ static int __devexit pxafb_remove(struct platform_device *dev) irq = platform_get_irq(dev, 0); free_irq(irq, fbi); - dma_free_writecombine(&dev->dev, fbi->map_size, - fbi->map_cpu, fbi->map_dma); + free_pages_exact(fbi->video_mem, fbi->video_mem_size); + + dma_free_writecombine(&dev->dev, fbi->dma_buff_size, + fbi->dma_buff, fbi->dma_buff_phys); iounmap(fbi->mmio_base); diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 31541b86f13d..2353521c5c8c 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -54,11 +54,55 @@ enum { #define PALETTE_SIZE (256 * 4) #define CMD_BUFF_SIZE (1024 * 50) +/* NOTE: the palette and frame dma descriptors are doubled to allow + * the 2nd set for branch settings (FBRx) + */ struct pxafb_dma_buff { unsigned char palette[PAL_MAX * PALETTE_SIZE]; uint16_t cmd_buff[CMD_BUFF_SIZE]; - struct pxafb_dma_descriptor pal_desc[PAL_MAX]; - struct pxafb_dma_descriptor dma_desc[DMA_MAX]; + struct pxafb_dma_descriptor pal_desc[PAL_MAX * 2]; + struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2]; +}; + +enum { + OVERLAY1, + OVERLAY2, +}; + +enum { + OVERLAY_FORMAT_RGB = 0, + OVERLAY_FORMAT_YUV444_PACKED, + OVERLAY_FORMAT_YUV444_PLANAR, + OVERLAY_FORMAT_YUV422_PLANAR, + OVERLAY_FORMAT_YUV420_PLANAR, +}; + +#define NONSTD_TO_XPOS(x) (((x) >> 0) & 0x3ff) +#define NONSTD_TO_YPOS(x) (((x) >> 10) & 0x3ff) +#define NONSTD_TO_PFOR(x) (((x) >> 20) & 0x7) + +struct pxafb_layer; + +struct pxafb_layer_ops { + void (*enable)(struct pxafb_layer *); + void (*disable)(struct pxafb_layer *); + void (*setup)(struct pxafb_layer *); +}; + +struct pxafb_layer { + struct fb_info fb; + int id; + atomic_t usage; + uint32_t control[2]; + + struct pxafb_layer_ops *ops; + + void __iomem *video_mem; + unsigned long video_mem_phys; + size_t video_mem_size; + struct completion branch_done; + + struct pxafb_info *fbi; }; struct pxafb_info { @@ -69,24 +113,15 @@ struct pxafb_info { void __iomem *mmio_base; struct pxafb_dma_buff *dma_buff; + size_t dma_buff_size; dma_addr_t dma_buff_phys; - dma_addr_t fdadr[DMA_MAX]; - - /* - * These are the addresses we mapped - * the framebuffer memory region to. - */ - /* raw memory addresses */ - dma_addr_t map_dma; /* physical */ - u_char * map_cpu; /* virtual */ - u_int map_size; - - /* addresses of pieces placed in raw buffer */ - u_char * screen_cpu; /* virtual address of frame buffer */ - dma_addr_t screen_dma; /* physical address of frame buffer */ + dma_addr_t fdadr[DMA_MAX * 2]; + + void __iomem *video_mem; /* virtual address of frame buffer */ + unsigned long video_mem_phys; /* physical address of frame buffer */ + size_t video_mem_size; /* size of the frame buffer */ u16 * palette_cpu; /* virtual address of palette memory */ u_int palette_size; - ssize_t video_offset; u_int lccr0; u_int lccr3; @@ -120,10 +155,17 @@ struct pxafb_info { struct task_struct *smart_thread; #endif +#ifdef CONFIG_FB_PXA_OVERLAY + struct pxafb_layer overlay[2]; +#endif + #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; struct notifier_block freq_policy; #endif + + void (*lcd_power)(int, struct fb_var_screeninfo *); + void (*backlight_power)(int); }; #define TO_INF(ptr,member) container_of(ptr,struct pxafb_info,member) @@ -148,4 +190,10 @@ struct pxafb_info { #define MIN_XRES 64 #define MIN_YRES 64 +/* maximum X and Y resolutions - note these are limits from the register + * bits length instead of the real ones + */ +#define MAX_XRES 1024 +#define MAX_YRES 1024 + #endif /* __PXAFB_H__ */ diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index c052bd4c0b06..076f946fa0f5 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -114,7 +114,7 @@ * - convert dma address types to dma_addr_t * - remove unused 'montype' stuff * - remove redundant zero inits of init_var after the initial - * memzero. + * memset. * - remove allow_modeset (acornfb idea does not belong here) * * 2001/05/28: <rmk@arm.linux.org.uk> diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 5b78fd0aff0a..018c070a357f 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -176,7 +176,7 @@ int register_virtio_device(struct virtio_device *dev) /* Assign a unique device index and hence name. */ dev->index = dev_index++; - sprintf(dev->dev.bus_id, "virtio%u", dev->index); + dev_set_name(&dev->dev, "virtio%u", dev->index); /* We always start by resetting the device, in case a previous * driver messed it up. This also tests that code path a little. */ diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 62eab43152d2..59268266b79a 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -56,6 +56,15 @@ static struct virtio_device_id id_table[] = { { 0 }, }; +static u32 page_to_balloon_pfn(struct page *page) +{ + unsigned long pfn = page_to_pfn(page); + + BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); + /* Convert pfn from Linux page size to balloon page size. */ + return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); +} + static void balloon_ack(struct virtqueue *vq) { struct virtio_balloon *vb; @@ -99,7 +108,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) msleep(200); break; } - vb->pfns[vb->num_pfns] = page_to_pfn(page); + vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); totalram_pages--; vb->num_pages++; list_add(&page->lru, &vb->pages); @@ -132,7 +141,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { page = list_first_entry(&vb->pages, struct page, lru); list_del(&page->lru); - vb->pfns[vb->num_pfns] = page_to_pfn(page); + vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); vb->num_pages--; } diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index c7dc37c7cce9..265fdf2d1276 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -75,7 +75,7 @@ MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); * would make more sense for virtio to not insist on having it's own device. */ static struct device virtio_pci_root = { .parent = NULL, - .bus_id = "virtio-pci", + .init_name = "virtio-pci", }; /* Convert a generic virtio device to our structure */ @@ -216,7 +216,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; struct virtqueue *vq; - unsigned long flags; + unsigned long flags, size; u16 num; int err; @@ -237,19 +237,20 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, info->queue_index = index; info->num = num; - info->queue = kzalloc(PAGE_ALIGN(vring_size(num,PAGE_SIZE)), GFP_KERNEL); + size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); + info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); if (info->queue == NULL) { err = -ENOMEM; goto out_info; } /* activate the queue */ - iowrite32(virt_to_phys(info->queue) >> PAGE_SHIFT, + iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); /* create the vring */ - vq = vring_new_virtqueue(info->num, vdev, info->queue, - vp_notify, callback); + vq = vring_new_virtqueue(info->num, VIRTIO_PCI_VRING_ALIGN, + vdev, info->queue, vp_notify, callback); if (!vq) { err = -ENOMEM; goto out_activate_queue; @@ -266,7 +267,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, out_activate_queue: iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - kfree(info->queue); + free_pages_exact(info->queue, size); out_info: kfree(info); return ERR_PTR(err); @@ -277,7 +278,7 @@ static void vp_del_vq(struct virtqueue *vq) { struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); struct virtio_pci_vq_info *info = vq->priv; - unsigned long flags; + unsigned long flags, size; spin_lock_irqsave(&vp_dev->lock, flags); list_del(&info->node); @@ -289,7 +290,8 @@ static void vp_del_vq(struct virtqueue *vq) iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - kfree(info->queue); + size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); + free_pages_exact(info->queue, size); kfree(info); } @@ -305,6 +307,20 @@ static struct virtio_config_ops virtio_pci_config_ops = { .finalize_features = vp_finalize_features, }; +static void virtio_pci_release_dev(struct device *_d) +{ + struct virtio_device *dev = container_of(_d, struct virtio_device, dev); + struct virtio_pci_device *vp_dev = to_vp_device(dev); + struct pci_dev *pci_dev = vp_dev->pci_dev; + + free_irq(pci_dev->irq, vp_dev); + pci_set_drvdata(pci_dev, NULL); + pci_iounmap(pci_dev, vp_dev->ioaddr); + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); + kfree(vp_dev); +} + /* the PCI probing function */ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) @@ -328,6 +344,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, return -ENOMEM; vp_dev->vdev.dev.parent = &virtio_pci_root; + vp_dev->vdev.dev.release = virtio_pci_release_dev; vp_dev->vdev.config = &virtio_pci_config_ops; vp_dev->pci_dev = pci_dev; INIT_LIST_HEAD(&vp_dev->virtqueues); @@ -357,7 +374,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, /* register a handler for the queue with the PCI device's interrupt */ err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, - vp_dev->vdev.dev.bus_id, vp_dev); + dev_name(&vp_dev->vdev.dev), vp_dev); if (err) goto out_set_drvdata; @@ -387,12 +404,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); unregister_virtio_device(&vp_dev->vdev); - free_irq(pci_dev->irq, vp_dev); - pci_set_drvdata(pci_dev, NULL); - pci_iounmap(pci_dev, vp_dev->ioaddr); - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - kfree(vp_dev); } #ifdef CONFIG_PM diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 6eb5303fed11..5777196bf6c9 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -274,6 +274,7 @@ static struct virtqueue_ops vring_vq_ops = { }; struct virtqueue *vring_new_virtqueue(unsigned int num, + unsigned int vring_align, struct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *), @@ -292,7 +293,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, if (!vq) return NULL; - vring_init(&vq->vring, num, pages, PAGE_SIZE); + vring_init(&vq->vring, num, pages, vring_align); vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index f7f6ce82a5e2..e31925ee8346 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -42,7 +42,7 @@ #undef S3C_VA_WATCHDOG #define S3C_VA_WATCHDOG (0) -#include <asm/plat-s3c/regs-watchdog.h> +#include <plat/regs-watchdog.h> #define PFX "s3c2410-wdt: " diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index ed01e4c2beff..e19b45794717 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -27,6 +27,7 @@ #include <linux/init.h> #include <linux/bitops.h> #include <linux/uaccess.h> +#include <linux/timex.h> #ifdef CONFIG_ARCH_PXA #include <mach/pxa-regs.h> @@ -35,8 +36,7 @@ #include <mach/reset.h> #include <mach/hardware.h> -#define OSCR_FREQ CLOCK_TICK_RATE - +static unsigned long oscr_freq; static unsigned long sa1100wdt_users; static int pre_margin; static int boot_status; @@ -123,12 +123,12 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, break; } - pre_margin = OSCR_FREQ * time; + pre_margin = oscr_freq * time; OSMR3 = OSCR + pre_margin; /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, p); + ret = put_user(pre_margin / oscr_freq, p); break; } return ret; @@ -155,6 +155,8 @@ static int __init sa1100dog_init(void) { int ret; + oscr_freq = get_clock_tick_rate(); + /* * Read the reset status, and save it for later. If * we suspend, RCSR will be cleared, and the watchdog @@ -162,7 +164,7 @@ static int __init sa1100dog_init(void) */ boot_status = (reset_status & RESET_STATUS_WATCHDOG) ? WDIOF_CARDRESET : 0; - pre_margin = OSCR_FREQ * margin; + pre_margin = oscr_freq * margin; ret = misc_register(&sa1100dog_miscdev); if (ret == 0) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 1e3b934a4cf7..46625cd38743 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -141,8 +141,12 @@ static void init_evtchn_cpu_bindings(void) int i; /* By default all event channels notify CPU#0. */ - for_each_irq_desc(i, desc) + for_each_irq_desc(i, desc) { + if (!desc) + continue; + desc->affinity = cpumask_of_cpu(0); + } #endif memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); @@ -229,15 +233,20 @@ static void unmask_evtchn(int port) static int find_unbound_irq(void) { int irq; + struct irq_desc *desc; /* Only allocate from dynirq range */ - for_each_irq_nr(irq) + for (irq = 0; irq < nr_irqs; irq++) if (irq_bindcount[irq] == 0) break; if (irq == nr_irqs) panic("No available IRQ to bind to: increase nr_irqs!\n"); + desc = irq_to_desc_alloc_cpu(irq, 0); + if (WARN_ON(desc == NULL)) + return -1; + return irq; } @@ -792,7 +801,7 @@ void xen_irq_resume(void) mask_evtchn(evtchn); /* No IRQ <-> event-channel mappings. */ - for_each_irq_nr(irq) + for (irq = 0; irq < nr_irqs; irq++) irq_info[irq].evtchn = 0; /* zap event-channel binding */ for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) @@ -824,7 +833,7 @@ void __init xen_init_IRQ(void) mask_evtchn(i); /* Dynamic IRQ space is currently unbound. Zero the refcnts. */ - for_each_irq_nr(i) + for (i = 0; i < nr_irqs; i++) irq_bindcount[i] = 0; irq_ctx_init(smp_processor_id()); @@ -191,6 +191,20 @@ static int aio_setup_ring(struct kioctx *ctx) kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \ } while(0) +static void ctx_rcu_free(struct rcu_head *head) +{ + struct kioctx *ctx = container_of(head, struct kioctx, rcu_head); + unsigned nr_events = ctx->max_reqs; + + kmem_cache_free(kioctx_cachep, ctx); + + if (nr_events) { + spin_lock(&aio_nr_lock); + BUG_ON(aio_nr - nr_events > aio_nr); + aio_nr -= nr_events; + spin_unlock(&aio_nr_lock); + } +} /* __put_ioctx * Called when the last user of an aio context has gone away, @@ -198,8 +212,6 @@ static int aio_setup_ring(struct kioctx *ctx) */ static void __put_ioctx(struct kioctx *ctx) { - unsigned nr_events = ctx->max_reqs; - BUG_ON(ctx->reqs_active); cancel_delayed_work(&ctx->wq); @@ -208,14 +220,7 @@ static void __put_ioctx(struct kioctx *ctx) mmdrop(ctx->mm); ctx->mm = NULL; pr_debug("__put_ioctx: freeing %p\n", ctx); - kmem_cache_free(kioctx_cachep, ctx); - - if (nr_events) { - spin_lock(&aio_nr_lock); - BUG_ON(aio_nr - nr_events > aio_nr); - aio_nr -= nr_events; - spin_unlock(&aio_nr_lock); - } + call_rcu(&ctx->rcu_head, ctx_rcu_free); } #define get_ioctx(kioctx) do { \ @@ -235,6 +240,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) { struct mm_struct *mm; struct kioctx *ctx; + int did_sync = 0; /* Prevent overflows */ if ((nr_events > (0x10000000U / sizeof(struct io_event))) || @@ -267,21 +273,30 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) goto out_freectx; /* limit the number of system wide aios */ - spin_lock(&aio_nr_lock); - if (aio_nr + ctx->max_reqs > aio_max_nr || - aio_nr + ctx->max_reqs < aio_nr) - ctx->max_reqs = 0; - else - aio_nr += ctx->max_reqs; - spin_unlock(&aio_nr_lock); + do { + spin_lock_bh(&aio_nr_lock); + if (aio_nr + nr_events > aio_max_nr || + aio_nr + nr_events < aio_nr) + ctx->max_reqs = 0; + else + aio_nr += ctx->max_reqs; + spin_unlock_bh(&aio_nr_lock); + if (ctx->max_reqs || did_sync) + break; + + /* wait for rcu callbacks to have completed before giving up */ + synchronize_rcu(); + did_sync = 1; + ctx->max_reqs = nr_events; + } while (1); + if (ctx->max_reqs == 0) goto out_cleanup; /* now link into global list. */ - write_lock(&mm->ioctx_list_lock); - ctx->next = mm->ioctx_list; - mm->ioctx_list = ctx; - write_unlock(&mm->ioctx_list_lock); + spin_lock(&mm->ioctx_lock); + hlist_add_head_rcu(&ctx->list, &mm->ioctx_list); + spin_unlock(&mm->ioctx_lock); dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", ctx, ctx->user_id, current->mm, ctx->ring_info.nr); @@ -375,11 +390,12 @@ ssize_t wait_on_sync_kiocb(struct kiocb *iocb) */ void exit_aio(struct mm_struct *mm) { - struct kioctx *ctx = mm->ioctx_list; - mm->ioctx_list = NULL; - while (ctx) { - struct kioctx *next = ctx->next; - ctx->next = NULL; + struct kioctx *ctx; + + while (!hlist_empty(&mm->ioctx_list)) { + ctx = hlist_entry(mm->ioctx_list.first, struct kioctx, list); + hlist_del_rcu(&ctx->list); + aio_cancel_all(ctx); wait_for_all_aios(ctx); @@ -394,7 +410,6 @@ void exit_aio(struct mm_struct *mm) atomic_read(&ctx->users), ctx->dead, ctx->reqs_active); put_ioctx(ctx); - ctx = next; } } @@ -555,19 +570,21 @@ int aio_put_req(struct kiocb *req) static struct kioctx *lookup_ioctx(unsigned long ctx_id) { - struct kioctx *ioctx; - struct mm_struct *mm; + struct mm_struct *mm = current->mm; + struct kioctx *ctx = NULL; + struct hlist_node *n; - mm = current->mm; - read_lock(&mm->ioctx_list_lock); - for (ioctx = mm->ioctx_list; ioctx; ioctx = ioctx->next) - if (likely(ioctx->user_id == ctx_id && !ioctx->dead)) { - get_ioctx(ioctx); + rcu_read_lock(); + + hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { + if (ctx->user_id == ctx_id && !ctx->dead) { + get_ioctx(ctx); break; } - read_unlock(&mm->ioctx_list_lock); + } - return ioctx; + rcu_read_unlock(); + return ctx; } /* @@ -1215,19 +1232,14 @@ out: static void io_destroy(struct kioctx *ioctx) { struct mm_struct *mm = current->mm; - struct kioctx **tmp; int was_dead; /* delete the entry from the list is someone else hasn't already */ - write_lock(&mm->ioctx_list_lock); + spin_lock(&mm->ioctx_lock); was_dead = ioctx->dead; ioctx->dead = 1; - for (tmp = &mm->ioctx_list; *tmp && *tmp != ioctx; - tmp = &(*tmp)->next) - ; - if (*tmp) - *tmp = ioctx->next; - write_unlock(&mm->ioctx_list_lock); + hlist_del_rcu(&ioctx->list); + spin_unlock(&mm->ioctx_lock); dprintk("aio_release(%p)\n", ioctx); if (likely(!was_dead)) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 19caf7c962ac..77ebc3c263d6 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -111,7 +111,7 @@ void bio_integrity_free(struct bio *bio, struct bio_set *bs) && bip->bip_buf != NULL) kfree(bip->bip_buf); - mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]); + bvec_free_bs(bs, bip->bip_vec, bip->bip_pool); mempool_free(bip, bs->bio_integrity_pool); bio->bi_integrity = NULL; @@ -31,7 +31,11 @@ DEFINE_TRACE(block_split); -static struct kmem_cache *bio_slab __read_mostly; +/* + * Test patch to inline a certain number of bi_io_vec's inside the bio + * itself, to shrink a bio data allocation from two mempool calls to one + */ +#define BIO_INLINE_VECS 4 static mempool_t *bio_split_pool __read_mostly; @@ -40,9 +44,8 @@ static mempool_t *bio_split_pool __read_mostly; * break badly! cannot be bigger than what you can fit into an * unsigned short */ - #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } -static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { +struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), }; #undef BV @@ -53,12 +56,121 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { */ struct bio_set *fs_bio_set; +/* + * Our slab pool management + */ +struct bio_slab { + struct kmem_cache *slab; + unsigned int slab_ref; + unsigned int slab_size; + char name[8]; +}; +static DEFINE_MUTEX(bio_slab_lock); +static struct bio_slab *bio_slabs; +static unsigned int bio_slab_nr, bio_slab_max; + +static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) +{ + unsigned int sz = sizeof(struct bio) + extra_size; + struct kmem_cache *slab = NULL; + struct bio_slab *bslab; + unsigned int i, entry = -1; + + mutex_lock(&bio_slab_lock); + + i = 0; + while (i < bio_slab_nr) { + struct bio_slab *bslab = &bio_slabs[i]; + + if (!bslab->slab && entry == -1) + entry = i; + else if (bslab->slab_size == sz) { + slab = bslab->slab; + bslab->slab_ref++; + break; + } + i++; + } + + if (slab) + goto out_unlock; + + if (bio_slab_nr == bio_slab_max && entry == -1) { + bio_slab_max <<= 1; + bio_slabs = krealloc(bio_slabs, + bio_slab_max * sizeof(struct bio_slab), + GFP_KERNEL); + if (!bio_slabs) + goto out_unlock; + } + if (entry == -1) + entry = bio_slab_nr++; + + bslab = &bio_slabs[entry]; + + snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry); + slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL); + if (!slab) + goto out_unlock; + + printk("bio: create slab <%s> at %d\n", bslab->name, entry); + bslab->slab = slab; + bslab->slab_ref = 1; + bslab->slab_size = sz; +out_unlock: + mutex_unlock(&bio_slab_lock); + return slab; +} + +static void bio_put_slab(struct bio_set *bs) +{ + struct bio_slab *bslab = NULL; + unsigned int i; + + mutex_lock(&bio_slab_lock); + + for (i = 0; i < bio_slab_nr; i++) { + if (bs->bio_slab == bio_slabs[i].slab) { + bslab = &bio_slabs[i]; + break; + } + } + + if (WARN(!bslab, KERN_ERR "bio: unable to find slab!\n")) + goto out; + + WARN_ON(!bslab->slab_ref); + + if (--bslab->slab_ref) + goto out; + + kmem_cache_destroy(bslab->slab); + bslab->slab = NULL; + +out: + mutex_unlock(&bio_slab_lock); +} + unsigned int bvec_nr_vecs(unsigned short idx) { return bvec_slabs[idx].nr_vecs; } -struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) +void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx) +{ + BIO_BUG_ON(idx >= BIOVEC_NR_POOLS); + + if (idx == BIOVEC_MAX_IDX) + mempool_free(bv, bs->bvec_pool); + else { + struct biovec_slab *bvs = bvec_slabs + idx; + + kmem_cache_free(bvs->slab, bv); + } +} + +struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, + struct bio_set *bs) { struct bio_vec *bvl; @@ -67,60 +179,85 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct * If not, this is a bio_kmalloc() allocation and just do a * kzalloc() for the exact number of vecs right away. */ - if (bs) { + if (!bs) + bvl = kmalloc(nr * sizeof(struct bio_vec), gfp_mask); + + /* + * see comment near bvec_array define! + */ + switch (nr) { + case 1: + *idx = 0; + break; + case 2 ... 4: + *idx = 1; + break; + case 5 ... 16: + *idx = 2; + break; + case 17 ... 64: + *idx = 3; + break; + case 65 ... 128: + *idx = 4; + break; + case 129 ... BIO_MAX_PAGES: + *idx = 5; + break; + default: + return NULL; + } + + /* + * idx now points to the pool we want to allocate from. only the + * 1-vec entry pool is mempool backed. + */ + if (*idx == BIOVEC_MAX_IDX) { +fallback: + bvl = mempool_alloc(bs->bvec_pool, gfp_mask); + } else { + struct biovec_slab *bvs = bvec_slabs + *idx; + gfp_t __gfp_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO); + /* - * see comment near bvec_array define! + * Make this allocation restricted and don't dump info on + * allocation failures, since we'll fallback to the mempool + * in case of failure. */ - switch (nr) { - case 1: - *idx = 0; - break; - case 2 ... 4: - *idx = 1; - break; - case 5 ... 16: - *idx = 2; - break; - case 17 ... 64: - *idx = 3; - break; - case 65 ... 128: - *idx = 4; - break; - case 129 ... BIO_MAX_PAGES: - *idx = 5; - break; - default: - return NULL; - } + __gfp_mask |= __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN; /* - * idx now points to the pool we want to allocate from + * Try a slab allocation. If this fails and __GFP_WAIT + * is set, retry with the 1-entry mempool */ - bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); - if (bvl) - memset(bvl, 0, - bvec_nr_vecs(*idx) * sizeof(struct bio_vec)); - } else - bvl = kzalloc(nr * sizeof(struct bio_vec), gfp_mask); + bvl = kmem_cache_alloc(bvs->slab, __gfp_mask); + if (unlikely(!bvl && (gfp_mask & __GFP_WAIT))) { + *idx = BIOVEC_MAX_IDX; + goto fallback; + } + } return bvl; } -void bio_free(struct bio *bio, struct bio_set *bio_set) +void bio_free(struct bio *bio, struct bio_set *bs) { - if (bio->bi_io_vec) { - const int pool_idx = BIO_POOL_IDX(bio); + void *p; - BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); - - mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]); - } + if (bio_has_allocated_vec(bio)) + bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); if (bio_integrity(bio)) - bio_integrity_free(bio, bio_set); + bio_integrity_free(bio, bs); + + /* + * If we have front padding, adjust the bio pointer before freeing + */ + p = bio; + if (bs->front_pad) + p -= bs->front_pad; - mempool_free(bio, bio_set->bio_pool); + mempool_free(p, bs->bio_pool); } /* @@ -133,7 +270,8 @@ static void bio_fs_destructor(struct bio *bio) static void bio_kmalloc_destructor(struct bio *bio) { - kfree(bio->bi_io_vec); + if (bio_has_allocated_vec(bio)) + kfree(bio->bi_io_vec); kfree(bio); } @@ -157,16 +295,20 @@ void bio_init(struct bio *bio) * for a &struct bio to become free. If a %NULL @bs is passed in, we will * fall back to just using @kmalloc to allocate the required memory. * - * allocate bio and iovecs from the memory pools specified by the - * bio_set structure, or @kmalloc if none given. + * Note that the caller must set ->bi_destructor on succesful return + * of a bio, to do the appropriate freeing of the bio once the reference + * count drops to zero. **/ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) { - struct bio *bio; + struct bio *bio = NULL; + + if (bs) { + void *p = mempool_alloc(bs->bio_pool, gfp_mask); - if (bs) - bio = mempool_alloc(bs->bio_pool, gfp_mask); - else + if (p) + bio = p + bs->front_pad; + } else bio = kmalloc(sizeof(*bio), gfp_mask); if (likely(bio)) { @@ -176,7 +318,15 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) if (likely(nr_iovecs)) { unsigned long uninitialized_var(idx); - bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); + if (nr_iovecs <= BIO_INLINE_VECS) { + idx = 0; + bvl = bio->bi_inline_vecs; + nr_iovecs = BIO_INLINE_VECS; + } else { + bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, + bs); + nr_iovecs = bvec_nr_vecs(idx); + } if (unlikely(!bvl)) { if (bs) mempool_free(bio, bs->bio_pool); @@ -186,7 +336,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) goto out; } bio->bi_flags |= idx << BIO_POOL_OFFSET; - bio->bi_max_vecs = bvec_nr_vecs(idx); + bio->bi_max_vecs = nr_iovecs; } bio->bi_io_vec = bvl; } @@ -1346,30 +1496,18 @@ EXPORT_SYMBOL(bio_sector_offset); */ static int biovec_create_pools(struct bio_set *bs, int pool_entries) { - int i; + struct biovec_slab *bp = bvec_slabs + BIOVEC_MAX_IDX; - for (i = 0; i < BIOVEC_NR_POOLS; i++) { - struct biovec_slab *bp = bvec_slabs + i; - mempool_t **bvp = bs->bvec_pools + i; + bs->bvec_pool = mempool_create_slab_pool(pool_entries, bp->slab); + if (!bs->bvec_pool) + return -ENOMEM; - *bvp = mempool_create_slab_pool(pool_entries, bp->slab); - if (!*bvp) - return -ENOMEM; - } return 0; } static void biovec_free_pools(struct bio_set *bs) { - int i; - - for (i = 0; i < BIOVEC_NR_POOLS; i++) { - mempool_t *bvp = bs->bvec_pools[i]; - - if (bvp) - mempool_destroy(bvp); - } - + mempool_destroy(bs->bvec_pool); } void bioset_free(struct bio_set *bs) @@ -1379,25 +1517,49 @@ void bioset_free(struct bio_set *bs) bioset_integrity_free(bs); biovec_free_pools(bs); + bio_put_slab(bs); kfree(bs); } -struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size) +/** + * bioset_create - Create a bio_set + * @pool_size: Number of bio and bio_vecs to cache in the mempool + * @front_pad: Number of bytes to allocate in front of the returned bio + * + * Description: + * Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller + * to ask for a number of bytes to be allocated in front of the bio. + * Front pad allocation is useful for embedding the bio inside + * another structure, to avoid allocating extra data to go with the bio. + * Note that the bio must be embedded at the END of that structure always, + * or things will break badly. + */ +struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) { - struct bio_set *bs = kzalloc(sizeof(*bs), GFP_KERNEL); + unsigned int back_pad = BIO_INLINE_VECS * sizeof(struct bio_vec); + struct bio_set *bs; + bs = kzalloc(sizeof(*bs), GFP_KERNEL); if (!bs) return NULL; - bs->bio_pool = mempool_create_slab_pool(bio_pool_size, bio_slab); + bs->front_pad = front_pad; + + bs->bio_slab = bio_find_or_create_slab(front_pad + back_pad); + if (!bs->bio_slab) { + kfree(bs); + return NULL; + } + + bs->bio_pool = mempool_create_slab_pool(pool_size, bs->bio_slab); if (!bs->bio_pool) goto bad; - if (bioset_integrity_create(bs, bio_pool_size)) + if (bioset_integrity_create(bs, pool_size)) goto bad; - if (!biovec_create_pools(bs, bvec_pool_size)) + if (!biovec_create_pools(bs, pool_size)) return bs; bad: @@ -1421,12 +1583,16 @@ static void __init biovec_init_slabs(void) static int __init init_bio(void) { - bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC); + bio_slab_max = 2; + bio_slab_nr = 0; + bio_slabs = kzalloc(bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL); + if (!bio_slabs) + panic("bio: can't allocate bios\n"); bio_integrity_init_slab(); biovec_init_slabs(); - fs_bio_set = bioset_create(BIO_POOL_SIZE, 2); + fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); if (!fs_bio_set) panic("bio: can't allocate bios\n"); diff --git a/fs/buffer.c b/fs/buffer.c index 10179cfa1152..776ae091d3b0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -99,10 +99,18 @@ __clear_page_buffers(struct page *page) page_cache_release(page); } + +static int quiet_error(struct buffer_head *bh) +{ + if (!test_bit(BH_Quiet, &bh->b_state) && printk_ratelimit()) + return 0; + return 1; +} + + static void buffer_io_error(struct buffer_head *bh) { char b[BDEVNAME_SIZE]; - printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n", bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); @@ -144,7 +152,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) if (uptodate) { set_buffer_uptodate(bh); } else { - if (!buffer_eopnotsupp(bh) && printk_ratelimit()) { + if (!buffer_eopnotsupp(bh) && !quiet_error(bh)) { buffer_io_error(bh); printk(KERN_WARNING "lost page write due to " "I/O error on %s\n", @@ -394,7 +402,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) set_buffer_uptodate(bh); } else { clear_buffer_uptodate(bh); - if (printk_ratelimit()) + if (!quiet_error(bh)) buffer_io_error(bh); SetPageError(page); } @@ -455,7 +463,7 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate) if (uptodate) { set_buffer_uptodate(bh); } else { - if (printk_ratelimit()) { + if (!quiet_error(bh)) { buffer_io_error(bh); printk(KERN_WARNING "lost page write due to " "I/O error on %s\n", @@ -2913,6 +2921,9 @@ static void end_bio_bh_io_sync(struct bio *bio, int err) set_bit(BH_Eopnotsupp, &bh->b_state); } + if (unlikely (test_bit(BIO_QUIET,&bio->bi_flags))) + set_bit(BH_Quiet, &bh->b_state); + bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags)); bio_put(bio); } diff --git a/fs/exec.c b/fs/exec.c index 1f59ea079cbb..02d2e120542d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -773,7 +773,6 @@ static int de_thread(struct task_struct *tsk) struct signal_struct *sig = tsk->signal; struct sighand_struct *oldsighand = tsk->sighand; spinlock_t *lock = &oldsighand->siglock; - struct task_struct *leader = NULL; int count; if (thread_group_empty(tsk)) @@ -811,7 +810,7 @@ static int de_thread(struct task_struct *tsk) * and to assume its PID: */ if (!thread_group_leader(tsk)) { - leader = tsk->group_leader; + struct task_struct *leader = tsk->group_leader; sig->notify_count = -1; /* for exit_notify() */ for (;;) { @@ -863,8 +862,9 @@ static int de_thread(struct task_struct *tsk) BUG_ON(leader->exit_state != EXIT_ZOMBIE); leader->exit_state = EXIT_DEAD; - write_unlock_irq(&tasklist_lock); + + release_task(leader); } sig->group_exit_task = NULL; @@ -873,8 +873,6 @@ static int de_thread(struct task_struct *tsk) no_thread_group: exit_itimers(sig); flush_itimer_signals(); - if (leader) - release_task(leader); if (atomic_read(&oldsighand->count) != 1) { struct sighand_struct *newsighand; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e4a241c65dbe..04158ad74dbb 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1721,7 +1721,7 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files) /* small i_blocks in vfs inode? */ if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) { /* - * CONFIG_LSF is not enabled implies the inode + * CONFIG_LBD is not enabled implies the inode * i_block represent total blocks in 512 bytes * 32 == size of vfs inode i_blocks * 8 */ @@ -1764,7 +1764,7 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files) if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) { /* - * !has_huge_files or CONFIG_LSF is not enabled + * !has_huge_files or CONFIG_LBD is not enabled * implies the inode i_block represent total blocks in * 512 bytes 32 == size of vfs inode i_blocks * 8 */ @@ -2021,13 +2021,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (has_huge_files) { /* * Large file size enabled file system can only be - * mount if kernel is build with CONFIG_LSF + * mount if kernel is build with CONFIG_LBD */ if (sizeof(root->i_blocks) < sizeof(u64) && !(sb->s_flags & MS_RDONLY)) { printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge " "files cannot be mounted read-write " - "without CONFIG_LSF.\n", sb->s_id); + "without CONFIG_LBD.\n", sb->s_id); goto failed_mount; } } diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 210339784b56..b00ee9f05a06 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -59,8 +59,14 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino) if (inode->i_size >= IDATASIZE) { inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &jfs_aops; - } else + } else { inode->i_op = &jfs_symlink_inode_operations; + /* + * The inline data should be null-terminated, but + * don't let on-disk corruption crash the kernel + */ + JFS_IP(inode)->i_inline[inode->i_size] = '\0'; + } } else { inode->i_op = &jfs_file_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 81904f07679d..3bb1cf1e7425 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -44,10 +44,13 @@ static int show_stat(struct seq_file *p, void *v) softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); - - for_each_irq_nr(j) + for_each_irq_nr(j) { +#ifdef CONFIG_SPARSE_IRQ + if (!irq_to_desc(j)) + continue; +#endif sum += kstat_irqs_cpu(j, i); - + } sum += arch_irq_stat_cpu(i); } sum += arch_irq_stat(); @@ -92,7 +95,12 @@ static int show_stat(struct seq_file *p, void *v) /* sum again ? it could be updated? */ for_each_irq_nr(j) { per_irq_sum = 0; - +#ifdef CONFIG_SPARSE_IRQ + if (!irq_to_desc(j)) { + seq_printf(p, " %u", per_irq_sum); + continue; + } +#endif for_each_possible_cpu(i) per_irq_sum += kstat_irqs_cpu(j, i); diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 4c794d73fb84..8af276361bf2 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -41,15 +41,14 @@ struct bug_entry { #ifndef __WARN #ifndef __ASSEMBLY__ -extern void warn_on_slowpath(const char *file, const int line); extern void warn_slowpath(const char *file, const int line, const char *fmt, ...) __attribute__((format(printf, 3, 4))); #define WANT_WARN_ON_SLOWPATH #endif -#define __WARN() warn_on_slowpath(__FILE__, __LINE__) -#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg) +#define __WARN() warn_slowpath(__FILE__, __LINE__, NULL) +#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg) #else -#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) +#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) #endif #ifndef WARN_ON diff --git a/include/drm/Kbuild b/include/drm/Kbuild index 82b6983b7fbb..b940fdfa3b25 100644 --- a/include/drm/Kbuild +++ b/include/drm/Kbuild @@ -1,4 +1,4 @@ -unifdef-y += drm.h drm_sarea.h +unifdef-y += drm.h drm_sarea.h drm_mode.h unifdef-y += i810_drm.h unifdef-y += i830_drm.h unifdef-y += i915_drm.h diff --git a/include/drm/drm.h b/include/drm/drm.h index f46ba4b57da4..32e5096554e9 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -173,6 +173,7 @@ enum drm_map_type { _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ + _DRM_GEM = 6, /**< GEM object */ }; /** @@ -598,6 +599,8 @@ struct drm_gem_open { uint64_t size; }; +#include "drm_mode.h" + #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) #define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) @@ -634,6 +637,9 @@ struct drm_gem_open { #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) @@ -664,6 +670,24 @@ struct drm_gem_open { #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) + /** * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x99. diff --git a/include/drm/drmP.h b/include/drm/drmP.h index d5e8e5c89548..afb7858c068d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -105,6 +105,7 @@ struct drm_device; #define DRIVER_FB_DMA 0x400 #define DRIVER_IRQ_VBL2 0x800 #define DRIVER_GEM 0x1000 +#define DRIVER_MODESET 0x2000 /***********************************************************************/ /** \name Begin the DRM... */ @@ -238,11 +239,11 @@ struct drm_device; */ #define LOCK_TEST_WITH_RETURN( dev, file_priv ) \ do { \ - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.file_priv != file_priv ) { \ + if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock) || \ + file_priv->master->lock.file_priv != file_priv) { \ DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\ - __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\ - dev->lock.file_priv, file_priv ); \ + __func__, _DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock),\ + file_priv->master->lock.file_priv, file_priv); \ return -EINVAL; \ } \ } while (0) @@ -276,6 +277,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_AUTH 0x1 #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 +#define DRM_CONTROL_ALLOW 0x8 struct drm_ioctl_desc { unsigned int cmd; @@ -379,21 +381,26 @@ struct drm_buf_entry { /** File private data */ struct drm_file { int authenticated; - int master; pid_t pid; uid_t uid; drm_magic_t magic; unsigned long ioctl_count; struct list_head lhead; struct drm_minor *minor; - int remove_auth_on_close; unsigned long lock_count; + /** Mapping of mm object handles to object pointers. */ struct idr object_idr; /** Lock for synchronization of access to object_idr. */ spinlock_t table_lock; + struct file *filp; void *driver_priv; + + int is_master; /* this file private is a master for a minor */ + struct drm_master *master; /* master this node is currently associated with + N.B. not always minor->master */ + struct list_head fbs; }; /** Wait queue */ @@ -523,6 +530,8 @@ struct drm_map_list { struct drm_hash_item hash; struct drm_map *map; /**< mapping */ uint64_t user_token; + struct drm_master *master; + struct drm_mm_node *file_offset_node; /**< fake offset */ }; typedef struct drm_map drm_local_map_t; @@ -563,6 +572,14 @@ struct drm_ati_pcigart_info { }; /** + * GEM specific mm private for tracking GEM objects + */ +struct drm_gem_mm { + struct drm_mm offset_manager; /**< Offset mgmt for buffer objects */ + struct drm_open_hash offset_hash; /**< User token hash table for maps */ +}; + +/** * This structure defines the drm_mm memory object, which will be used by the * DRM for its buffer objects. */ @@ -579,6 +596,9 @@ struct drm_gem_object { /** File representing the shmem storage */ struct file *filp; + /* Mapping info for this object */ + struct drm_map_list map_list; + /** * Size of the object, in bytes. Immutable over the object's * lifetime. @@ -612,6 +632,33 @@ struct drm_gem_object { void *driver_private; }; +#include "drm_crtc.h" + +/* per-master structure */ +struct drm_master { + + struct kref refcount; /* refcount for this master */ + + struct list_head head; /**< each minor contains a list of masters */ + struct drm_minor *minor; /**< link back to minor we are a master for */ + + char *unique; /**< Unique identifier: e.g., busid */ + int unique_len; /**< Length of unique field */ + int unique_size; /**< amount allocated */ + + int blocked; /**< Blocked due to VC switch? */ + + /** \name Authentication */ + /*@{ */ + struct drm_open_hash magiclist; + struct list_head magicfree; + /*@} */ + + struct drm_lock_data lock; /**< Information on hardware lock */ + + void *driver_priv; /**< Private structure for driver to use */ +}; + /** * DRM driver structure. This structure represent the common code for * a family of cards. There will one drm_device for each card present @@ -712,6 +759,10 @@ struct drm_driver { void (*set_version) (struct drm_device *dev, struct drm_set_version *sv); + /* Master routines */ + int (*master_create)(struct drm_device *dev, struct drm_master *master); + void (*master_destroy)(struct drm_device *dev, struct drm_master *master); + int (*proc_init)(struct drm_minor *minor); void (*proc_cleanup)(struct drm_minor *minor); @@ -724,6 +775,9 @@ struct drm_driver { int (*gem_init_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj); + /* Driver private ops for this object */ + struct vm_operations_struct *gem_vm_ops; + int major; int minor; int patchlevel; @@ -737,10 +791,14 @@ struct drm_driver { int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; + /* List of devices hanging off this driver */ + struct list_head device_list; }; #define DRM_MINOR_UNASSIGNED 0 #define DRM_MINOR_LEGACY 1 +#define DRM_MINOR_CONTROL 2 +#define DRM_MINOR_RENDER 3 /** * DRM minor structure. This structure represents a drm minor number. @@ -752,6 +810,9 @@ struct drm_minor { struct device kdev; /**< Linux device */ struct drm_device *dev; struct proc_dir_entry *dev_root; /**< proc directory entry */ + struct drm_master *master; /* currently active master for this node */ + struct list_head master_list; + struct drm_mode_group mode_group; }; /** @@ -759,13 +820,10 @@ struct drm_minor { * may contain multiple heads. */ struct drm_device { - char *unique; /**< Unique identifier: e.g., busid */ - int unique_len; /**< Length of unique field */ + struct list_head driver_item; /**< list of devices per driver */ char *devname; /**< For /proc/interrupts */ int if_version; /**< Highest interface version set */ - int blocked; /**< Blocked due to VC switch? */ - /** \name Locks */ /*@{ */ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ @@ -788,12 +846,7 @@ struct drm_device { atomic_t counts[15]; /*@} */ - /** \name Authentication */ - /*@{ */ struct list_head filelist; - struct drm_open_hash magiclist; /**< magic hash table */ - struct list_head magicfree; - /*@} */ /** \name Memory management */ /*@{ */ @@ -810,7 +863,7 @@ struct drm_device { struct idr ctx_idr; struct list_head vmalist; /**< List of vmas (for debugging) */ - struct drm_lock_data lock; /**< Information on hardware lock */ + /*@} */ /** \name DMA queues (contexts) */ @@ -858,6 +911,7 @@ struct drm_device { int *vblank_enabled; /* so we don't call enable more than once per disable */ int *vblank_inmodeset; /* Display driver is setting mode */ + u32 *last_vblank_wait; /* Last vblank seqno waited per CRTC */ struct timer_list vblank_disable_timer; u32 max_vblank_count; /**< size of vblank counter register */ @@ -881,12 +935,15 @@ struct drm_device { struct drm_sg_mem *sg; /**< Scatter gather memory */ int num_crtcs; /**< Number of CRTCs on this device */ void *dev_private; /**< device private data */ + void *mm_private; + struct address_space *dev_mapping; struct drm_sigdata sigdata; /**< For block_all_signals */ sigset_t sigmask; struct drm_driver *driver; drm_local_map_t *agp_buffer_map; unsigned int agp_buffer_token; + struct drm_minor *control; /**< Control node for card */ struct drm_minor *primary; /**< render type primary screen head */ /** \name Drawable information */ @@ -895,6 +952,8 @@ struct drm_device { struct idr drw_idr; /*@} */ + struct drm_mode_config mode_config; /**< Current mode config */ + /** \name GEM information */ /*@{ */ spinlock_t object_name_lock; @@ -997,6 +1056,8 @@ extern int drm_release(struct inode *inode, struct file *filp); /* Mapping support (drm_vm.h) */ extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); +extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); +extern void drm_vm_open_locked(struct vm_area_struct *vma); extern unsigned long drm_core_get_map_ofs(struct drm_map * map); extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); @@ -1153,6 +1214,8 @@ extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); extern void drm_vblank_cleanup(struct drm_device *dev); /* Modesetting support */ +extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); +extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); extern int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -1189,6 +1252,13 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle); extern void drm_agp_chipset_flush(struct drm_device *dev); /* Stub support (drm_stub.h) */ +extern int drm_setmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +struct drm_master *drm_master_create(struct drm_minor *minor); +extern struct drm_master *drm_master_get(struct drm_master *master); +extern void drm_master_put(struct drm_master **master); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); @@ -1231,7 +1301,11 @@ struct drm_sysfs_class; extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); extern int drm_sysfs_device_add(struct drm_minor *minor); +extern void drm_sysfs_hotplug_event(struct drm_device *dev); extern void drm_sysfs_device_remove(struct drm_minor *minor); +extern char *drm_get_connector_status_name(enum drm_connector_status status); +extern int drm_sysfs_connector_add(struct drm_connector *connector); +extern void drm_sysfs_connector_remove(struct drm_connector *connector); /* * Basic memory manager support (drm_mm.c) @@ -1251,10 +1325,12 @@ extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size); /* Graphics Execution Manager library functions (drm_gem.c) */ int drm_gem_init(struct drm_device *dev); +void drm_gem_destroy(struct drm_device *dev); void drm_gem_object_free(struct kref *kref); struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, size_t size); void drm_gem_object_handle_free(struct kref *kref); +int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); static inline void drm_gem_object_reference(struct drm_gem_object *obj) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h new file mode 100644 index 000000000000..0acb07f31fa4 --- /dev/null +++ b/include/drm/drm_crtc.h @@ -0,0 +1,733 @@ +/* + * Copyright © 2006 Keith Packard + * Copyright © 2007-2008 Dave Airlie + * Copyright © 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 __DRM_CRTC_H__ +#define __DRM_CRTC_H__ + +#include <linux/i2c.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/idr.h> + +#include <linux/fb.h> + +struct drm_device; +struct drm_mode_set; +struct drm_framebuffer; + + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb + +struct drm_mode_object { + uint32_t id; + uint32_t type; +}; + +/* + * Note on terminology: here, for brevity and convenience, we refer to connector + * control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS, + * DVI, etc. And 'screen' refers to the whole of the visible display, which + * may span multiple monitors (and therefore multiple CRTC and connector + * structures). + */ + +enum drm_mode_status { + MODE_OK = 0, /* Mode OK */ + MODE_HSYNC, /* hsync out of range */ + MODE_VSYNC, /* vsync out of range */ + MODE_H_ILLEGAL, /* mode has illegal horizontal timings */ + MODE_V_ILLEGAL, /* mode has illegal horizontal timings */ + MODE_BAD_WIDTH, /* requires an unsupported linepitch */ + MODE_NOMODE, /* no mode with a maching name */ + MODE_NO_INTERLACE, /* interlaced mode not supported */ + MODE_NO_DBLESCAN, /* doublescan mode not supported */ + MODE_NO_VSCAN, /* multiscan mode not supported */ + MODE_MEM, /* insufficient video memory */ + MODE_VIRTUAL_X, /* mode width too large for specified virtual size */ + MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */ + MODE_MEM_VIRT, /* insufficient video memory given virtual size */ + MODE_NOCLOCK, /* no fixed clock available */ + MODE_CLOCK_HIGH, /* clock required is too high */ + MODE_CLOCK_LOW, /* clock required is too low */ + MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */ + MODE_BAD_HVALUE, /* horizontal timing was out of range */ + MODE_BAD_VVALUE, /* vertical timing was out of range */ + MODE_BAD_VSCAN, /* VScan value out of range */ + MODE_HSYNC_NARROW, /* horizontal sync too narrow */ + MODE_HSYNC_WIDE, /* horizontal sync too wide */ + MODE_HBLANK_NARROW, /* horizontal blanking too narrow */ + MODE_HBLANK_WIDE, /* horizontal blanking too wide */ + MODE_VSYNC_NARROW, /* vertical sync too narrow */ + MODE_VSYNC_WIDE, /* vertical sync too wide */ + MODE_VBLANK_NARROW, /* vertical blanking too narrow */ + MODE_VBLANK_WIDE, /* vertical blanking too wide */ + MODE_PANEL, /* exceeds panel dimensions */ + MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ + MODE_ONE_WIDTH, /* only one width is supported */ + MODE_ONE_HEIGHT, /* only one height is supported */ + MODE_ONE_SIZE, /* only one resolution is supported */ + MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ + MODE_UNVERIFIED = -3, /* mode needs to reverified */ + MODE_BAD = -2, /* unspecified reason */ + MODE_ERROR = -1 /* error condition */ +}; + +#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ + DRM_MODE_TYPE_CRTC_C) + +#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ + .name = nm, .status = 0, .type = (t), .clock = (c), \ + .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ + .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ + .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ + .vscan = (vs), .flags = (f), .vrefresh = 0 + +#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ + +struct drm_display_mode { + /* Header */ + struct list_head head; + struct drm_mode_object base; + + char name[DRM_DISPLAY_MODE_LEN]; + + int connector_count; + enum drm_mode_status status; + int type; + + /* Proposed mode values */ + int clock; + int hdisplay; + int hsync_start; + int hsync_end; + int htotal; + int hskew; + int vdisplay; + int vsync_start; + int vsync_end; + int vtotal; + int vscan; + unsigned int flags; + + /* Addressable image size (may be 0 for projectors, etc.) */ + int width_mm; + int height_mm; + + /* Actual mode we give to hw */ + int clock_index; + int synth_clock; + int crtc_hdisplay; + int crtc_hblank_start; + int crtc_hblank_end; + int crtc_hsync_start; + int crtc_hsync_end; + int crtc_htotal; + int crtc_hskew; + int crtc_vdisplay; + int crtc_vblank_start; + int crtc_vblank_end; + int crtc_vsync_start; + int crtc_vsync_end; + int crtc_vtotal; + int crtc_hadjusted; + int crtc_vadjusted; + + /* Driver private mode info */ + int private_size; + int *private; + int private_flags; + + int vrefresh; + float hsync; +}; + +enum drm_connector_status { + connector_status_connected = 1, + connector_status_disconnected = 2, + connector_status_unknown = 3, +}; + +enum subpixel_order { + SubPixelUnknown = 0, + SubPixelHorizontalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalRGB, + SubPixelVerticalBGR, + SubPixelNone, +}; + + +/* + * Describes a given display (e.g. CRT or flat panel) and its limitations. + */ +struct drm_display_info { + char name[DRM_DISPLAY_INFO_LEN]; + /* Input info */ + bool serration_vsync; + bool sync_on_green; + bool composite_sync; + bool separate_syncs; + bool blank_to_black; + unsigned char video_level; + bool digital; + /* Physical size */ + unsigned int width_mm; + unsigned int height_mm; + + /* Display parameters */ + unsigned char gamma; /* FIXME: storage format */ + bool gtf_supported; + bool standard_color; + enum { + monochrome = 0, + rgb, + other, + unknown, + } display_type; + bool active_off_supported; + bool suspend_supported; + bool standby_supported; + + /* Color info FIXME: storage format */ + unsigned short redx, redy; + unsigned short greenx, greeny; + unsigned short bluex, bluey; + unsigned short whitex, whitey; + + /* Clock limits FIXME: storage format */ + unsigned int min_vfreq, max_vfreq; + unsigned int min_hfreq, max_hfreq; + unsigned int pixel_clock; + + /* White point indices FIXME: storage format */ + unsigned int wpx1, wpy1; + unsigned int wpgamma1; + unsigned int wpx2, wpy2; + unsigned int wpgamma2; + + enum subpixel_order subpixel_order; + + char *raw_edid; /* if any */ +}; + +struct drm_framebuffer_funcs { + void (*destroy)(struct drm_framebuffer *framebuffer); + int (*create_handle)(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle); +}; + +struct drm_framebuffer { + struct drm_device *dev; + struct list_head head; + struct drm_mode_object base; + const struct drm_framebuffer_funcs *funcs; + unsigned int pitch; + unsigned int width; + unsigned int height; + /* depth can be 15 or 16 */ + unsigned int depth; + int bits_per_pixel; + int flags; + void *fbdev; + u32 pseudo_palette[17]; + struct list_head filp_head; +}; + +struct drm_property_blob { + struct drm_mode_object base; + struct list_head head; + unsigned int length; + void *data; +}; + +struct drm_property_enum { + uint64_t value; + struct list_head head; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_property { + struct list_head head; + struct drm_mode_object base; + uint32_t flags; + char name[DRM_PROP_NAME_LEN]; + uint32_t num_values; + uint64_t *values; + + struct list_head enum_blob_list; +}; + +struct drm_crtc; +struct drm_connector; +struct drm_encoder; + +/** + * drm_crtc_funcs - control CRTCs for a given device + * @dpms: control display power levels + * @save: save CRTC state + * @resore: restore CRTC state + * @lock: lock the CRTC + * @unlock: unlock the CRTC + * @shadow_allocate: allocate shadow pixmap + * @shadow_create: create shadow pixmap for rotation support + * @shadow_destroy: free shadow pixmap + * @mode_fixup: fixup proposed mode + * @mode_set: set the desired mode on the CRTC + * @gamma_set: specify color ramp for CRTC + * @destroy: deinit and free object. + * + * The drm_crtc_funcs structure is the central CRTC management structure + * in the DRM. Each CRTC controls one or more connectors (note that the name + * CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc. + * connectors, not just CRTs). + * + * Each driver is responsible for filling out this structure at startup time, + * in addition to providing other modesetting features, like i2c and DDC + * bus accessors. + */ +struct drm_crtc_funcs { + /* Save CRTC state */ + void (*save)(struct drm_crtc *crtc); /* suspend? */ + /* Restore CRTC state */ + void (*restore)(struct drm_crtc *crtc); /* resume? */ + + /* cursor controls */ + int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, + uint32_t handle, uint32_t width, uint32_t height); + int (*cursor_move)(struct drm_crtc *crtc, int x, int y); + + /* Set gamma on the CRTC */ + void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, + uint32_t size); + /* Object destroy routine */ + void (*destroy)(struct drm_crtc *crtc); + + int (*set_config)(struct drm_mode_set *set); +}; + +/** + * drm_crtc - central CRTC control structure + * @enabled: is this CRTC enabled? + * @x: x position on screen + * @y: y position on screen + * @desired_mode: new desired mode + * @desired_x: desired x for desired_mode + * @desired_y: desired y for desired_mode + * @funcs: CRTC control functions + * + * Each CRTC may have one or more connectors associated with it. This structure + * allows the CRTC to be controlled. + */ +struct drm_crtc { + struct drm_device *dev; + struct list_head head; + + struct drm_mode_object base; + + /* framebuffer the connector is currently bound to */ + struct drm_framebuffer *fb; + + bool enabled; + + struct drm_display_mode mode; + + int x, y; + struct drm_display_mode *desired_mode; + int desired_x, desired_y; + const struct drm_crtc_funcs *funcs; + + /* CRTC gamma size for reporting to userspace */ + uint32_t gamma_size; + uint16_t *gamma_store; + + /* if you are using the helper */ + void *helper_private; +}; + + +/** + * drm_connector_funcs - control connectors on a given device + * @dpms: set power state (see drm_crtc_funcs above) + * @save: save connector state + * @restore: restore connector state + * @mode_valid: is this mode valid on the given connector? + * @mode_fixup: try to fixup proposed mode for this connector + * @mode_set: set this mode + * @detect: is this connector active? + * @get_modes: get mode list for this connector + * @set_property: property for this connector may need update + * @destroy: make object go away + * + * Each CRTC may have one or more connectors attached to it. The functions + * below allow the core DRM code to control connectors, enumerate available modes, + * etc. + */ +struct drm_connector_funcs { + void (*dpms)(struct drm_connector *connector, int mode); + void (*save)(struct drm_connector *connector); + void (*restore)(struct drm_connector *connector); + enum drm_connector_status (*detect)(struct drm_connector *connector); + void (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); + int (*set_property)(struct drm_connector *connector, struct drm_property *property, + uint64_t val); + void (*destroy)(struct drm_connector *connector); +}; + +struct drm_encoder_funcs { + void (*destroy)(struct drm_encoder *encoder); +}; + +#define DRM_CONNECTOR_MAX_UMODES 16 +#define DRM_CONNECTOR_MAX_PROPERTY 16 +#define DRM_CONNECTOR_LEN 32 +#define DRM_CONNECTOR_MAX_ENCODER 2 + +/** + * drm_encoder - central DRM encoder structure + */ +struct drm_encoder { + struct drm_device *dev; + struct list_head head; + + struct drm_mode_object base; + int encoder_type; + uint32_t possible_crtcs; + uint32_t possible_clones; + + struct drm_crtc *crtc; + const struct drm_encoder_funcs *funcs; + void *helper_private; +}; + +/** + * drm_connector - central DRM connector control structure + * @crtc: CRTC this connector is currently connected to, NULL if none + * @interlace_allowed: can this connector handle interlaced modes? + * @doublescan_allowed: can this connector handle doublescan? + * @available_modes: modes available on this connector (from get_modes() + user) + * @initial_x: initial x position for this connector + * @initial_y: initial y position for this connector + * @status: connector connected? + * @funcs: connector control functions + * + * Each connector may be connected to one or more CRTCs, or may be clonable by + * another connector if they can share a CRTC. Each connector also has a specific + * position in the broader display (referred to as a 'screen' though it could + * span multiple monitors). + */ +struct drm_connector { + struct drm_device *dev; + struct device kdev; + struct device_attribute *attr; + struct list_head head; + + struct drm_mode_object base; + + int connector_type; + int connector_type_id; + bool interlace_allowed; + bool doublescan_allowed; + struct list_head modes; /* list of modes on this connector */ + + int initial_x, initial_y; + enum drm_connector_status status; + + /* these are modes added by probing with DDC or the BIOS */ + struct list_head probed_modes; + + struct drm_display_info display_info; + const struct drm_connector_funcs *funcs; + + struct list_head user_modes; + struct drm_property_blob *edid_blob_ptr; + u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY]; + uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY]; + + void *helper_private; + + uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; + uint32_t force_encoder_id; + struct drm_encoder *encoder; /* currently active encoder */ +}; + +/** + * struct drm_mode_set + * + * Represents a single crtc the connectors that it drives with what mode + * and from which framebuffer it scans out from. + * + * This is used to set modes. + */ +struct drm_mode_set { + struct list_head head; + + struct drm_framebuffer *fb; + struct drm_crtc *crtc; + struct drm_display_mode *mode; + + uint32_t x; + uint32_t y; + + struct drm_connector **connectors; + size_t num_connectors; +}; + +/** + * struct drm_mode_config_funcs - configure CRTCs for a given screen layout + * @resize: adjust CRTCs as necessary for the proposed layout + * + * Currently only a resize hook is available. DRM will call back into the + * driver with a new screen width and height. If the driver can't support + * the proposed size, it can return false. Otherwise it should adjust + * the CRTC<->connector mappings as needed and update its view of the screen. + */ +struct drm_mode_config_funcs { + struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); + int (*fb_changed)(struct drm_device *dev); +}; + +struct drm_mode_group { + uint32_t num_crtcs; + uint32_t num_encoders; + uint32_t num_connectors; + + /* list of object IDs for this group */ + uint32_t *id_list; +}; + +/** + * drm_mode_config - Mode configuration control structure + * + */ +struct drm_mode_config { + struct mutex mutex; /* protects configuration and IDR */ + struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ + /* this is limited to one for now */ + int num_fb; + struct list_head fb_list; + int num_connector; + struct list_head connector_list; + int num_encoder; + struct list_head encoder_list; + + int num_crtc; + struct list_head crtc_list; + + struct list_head property_list; + + /* in-kernel framebuffers - hung of filp_head in drm_framebuffer */ + struct list_head fb_kernel_list; + + int min_width, min_height; + int max_width, max_height; + struct drm_mode_config_funcs *funcs; + unsigned long fb_base; + + /* pointers to standard properties */ + struct list_head property_blob_list; + struct drm_property *edid_property; + struct drm_property *dpms_property; + + /* DVI-I properties */ + struct drm_property *dvi_i_subconnector_property; + struct drm_property *dvi_i_select_subconnector_property; + + /* TV properties */ + struct drm_property *tv_subconnector_property; + struct drm_property *tv_select_subconnector_property; + struct drm_property *tv_mode_property; + struct drm_property *tv_left_margin_property; + struct drm_property *tv_right_margin_property; + struct drm_property *tv_top_margin_property; + struct drm_property *tv_bottom_margin_property; + + /* Optional properties */ + struct drm_property *scaling_mode_property; + struct drm_property *dithering_mode_property; +}; + +#define obj_to_crtc(x) container_of(x, struct drm_crtc, base) +#define obj_to_connector(x) container_of(x, struct drm_connector, base) +#define obj_to_encoder(x) container_of(x, struct drm_encoder, base) +#define obj_to_mode(x) container_of(x, struct drm_display_mode, base) +#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) +#define obj_to_property(x) container_of(x, struct drm_property, base) +#define obj_to_blob(x) container_of(x, struct drm_property_blob, base) + + +extern void drm_crtc_init(struct drm_device *dev, + struct drm_crtc *crtc, + const struct drm_crtc_funcs *funcs); +extern void drm_crtc_cleanup(struct drm_crtc *crtc); + +extern void drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type); + +extern void drm_connector_cleanup(struct drm_connector *connector); + +extern void drm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type); + +extern void drm_encoder_cleanup(struct drm_encoder *encoder); + +extern char *drm_get_connector_name(struct drm_connector *connector); +extern char *drm_get_dpms_name(int val); +extern char *drm_get_dvi_i_subconnector_name(int val); +extern char *drm_get_dvi_i_select_name(int val); +extern char *drm_get_tv_subconnector_name(int val); +extern char *drm_get_tv_select_name(int val); +extern void drm_fb_release(struct file *filp); +extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); +extern struct edid *drm_get_edid(struct drm_connector *connector, + struct i2c_adapter *adapter); +extern unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter); +extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); +extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); +extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode); +extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, + struct drm_display_mode *mode); +extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode); +extern void drm_mode_config_init(struct drm_device *dev); +extern void drm_mode_config_cleanup(struct drm_device *dev); +extern void drm_mode_set_name(struct drm_display_mode *mode); +extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2); +extern int drm_mode_width(struct drm_display_mode *mode); +extern int drm_mode_height(struct drm_display_mode *mode); + +/* for us by fb module */ +extern int drm_mode_attachmode_crtc(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_display_mode *mode); +extern int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode); + +extern struct drm_display_mode *drm_mode_create(struct drm_device *dev); +extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); +extern void drm_mode_list_concat(struct list_head *head, + struct list_head *new); +extern void drm_mode_validate_size(struct drm_device *dev, + struct list_head *mode_list, + int maxX, int maxY, int maxPitch); +extern void drm_mode_prune_invalid(struct drm_device *dev, + struct list_head *mode_list, bool verbose); +extern void drm_mode_sort(struct list_head *mode_list); +extern int drm_mode_vrefresh(struct drm_display_mode *mode); +extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, + int adjust_flags); +extern void drm_mode_connector_list_update(struct drm_connector *connector); +extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, + struct edid *edid); +extern int drm_connector_property_set_value(struct drm_connector *connector, + struct drm_property *property, + uint64_t value); +extern int drm_connector_property_get_value(struct drm_connector *connector, + struct drm_property *property, + uint64_t *value); +extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); +extern void drm_framebuffer_set_object(struct drm_device *dev, + unsigned long handle); +extern int drm_framebuffer_init(struct drm_device *dev, + struct drm_framebuffer *fb, + const struct drm_framebuffer_funcs *funcs); +extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb); +extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc); +extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); +extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY); +extern bool drm_crtc_in_use(struct drm_crtc *crtc); + +extern int drm_connector_attach_property(struct drm_connector *connector, + struct drm_property *property, uint64_t init_val); +extern struct drm_property *drm_property_create(struct drm_device *dev, int flags, + const char *name, int num_values); +extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); +extern int drm_property_add_enum(struct drm_property *property, int index, + uint64_t value, const char *name); +extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); +extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats, + char *formats[]); +extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); +extern int drm_mode_create_dithering_property(struct drm_device *dev); +extern char *drm_get_encoder_name(struct drm_encoder *encoder); + +extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, + struct drm_encoder *encoder); +extern void drm_mode_connector_detach_encoder(struct drm_connector *connector, + struct drm_encoder *encoder); +extern bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, + int gamma_size); +extern void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type); +/* IOCTLs */ +extern int drm_mode_getresources(struct drm_device *dev, + void *data, struct drm_file *file_priv); + +extern int drm_mode_getcrtc(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_getconnector(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_setcrtc(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_cursor_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_addfb(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_rmfb(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_getfb(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_addmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_rmmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_attachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_detachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); + +extern int drm_mode_getproperty_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_getblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_connector_property_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_hotplug_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_replacefb(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_getencoder(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +#endif /* __DRM_CRTC_H__ */ diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h new file mode 100644 index 000000000000..4bc04cf460a7 --- /dev/null +++ b/include/drm/drm_crtc_helper.h @@ -0,0 +1,124 @@ +/* + * Copyright © 2006 Keith Packard + * Copyright © 2007-2008 Dave Airlie + * Copyright © 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +/* + * The DRM mode setting helper functions are common code for drivers to use if + * they wish. Drivers are not forced to use this code in their + * implementations but it would be useful if they code they do use at least + * provides a consistent interface and operation to userspace + */ + +#ifndef __DRM_CRTC_HELPER_H__ +#define __DRM_CRTC_HELPER_H__ + +#include <linux/i2c.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/idr.h> + +#include <linux/fb.h> + +struct drm_crtc_helper_funcs { + /* + * Control power levels on the CRTC. If the mode passed in is + * unsupported, the provider must use the next lowest power level. + */ + void (*dpms)(struct drm_crtc *crtc, int mode); + void (*prepare)(struct drm_crtc *crtc); + void (*commit)(struct drm_crtc *crtc); + + /* Provider can fixup or change mode timings before modeset occurs */ + bool (*mode_fixup)(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + /* Actually set the mode */ + void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb); + + /* Move the crtc on the current fb to the given position *optional* */ + void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); +}; + +struct drm_encoder_helper_funcs { + void (*dpms)(struct drm_encoder *encoder, int mode); + void (*save)(struct drm_encoder *encoder); + void (*restore)(struct drm_encoder *encoder); + + bool (*mode_fixup)(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + void (*prepare)(struct drm_encoder *encoder); + void (*commit)(struct drm_encoder *encoder); + void (*mode_set)(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + /* detect for DAC style encoders */ + enum drm_connector_status (*detect)(struct drm_encoder *encoder, + struct drm_connector *connector); +}; + +struct drm_connector_helper_funcs { + int (*get_modes)(struct drm_connector *connector); + int (*mode_valid)(struct drm_connector *connector, + struct drm_display_mode *mode); + struct drm_encoder *(*best_encoder)(struct drm_connector *connector); +}; + +extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); +extern void drm_helper_disable_unused_functions(struct drm_device *dev); +extern int drm_helper_hotplug_stage_two(struct drm_device *dev); +extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); +extern int drm_crtc_helper_set_config(struct drm_mode_set *set); +extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, + struct drm_display_mode *mode, + int x, int y, + struct drm_framebuffer *old_fb); +extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); + +extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, + struct drm_mode_fb_cmd *mode_cmd); + +static inline void drm_crtc_helper_add(struct drm_crtc *crtc, + const struct drm_crtc_helper_funcs *funcs) +{ + crtc->helper_private = (void *)funcs; +} + +static inline void drm_encoder_helper_add(struct drm_encoder *encoder, + const struct drm_encoder_helper_funcs *funcs) +{ + encoder->helper_private = (void *)funcs; +} + +static inline void drm_connector_helper_add(struct drm_connector *connector, + const struct drm_connector_helper_funcs *funcs) +{ + connector->helper_private = (void *)funcs; +} + +extern int drm_helper_resume_force_mode(struct drm_device *dev); +#endif diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h new file mode 100644 index 000000000000..c707c15f5164 --- /dev/null +++ b/include/drm/drm_edid.h @@ -0,0 +1,202 @@ +/* + * Copyright © 2007-2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * 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 shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 __DRM_EDID_H__ +#define __DRM_EDID_H__ + +#include <linux/types.h> + +#define EDID_LENGTH 128 +#define DDC_ADDR 0x50 + +#ifdef BIG_ENDIAN +#error "EDID structure is little endian, need big endian versions" +#else + +struct est_timings { + u8 t1; + u8 t2; + u8 mfg_rsvd; +} __attribute__((packed)); + +struct std_timing { + u8 hsize; /* need to multiply by 8 then add 248 */ + u8 vfreq:6; /* need to add 60 */ + u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ +} __attribute__((packed)); + +/* If detailed data is pixel timing */ +struct detailed_pixel_timing { + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_offset_lo; + u8 hsync_pulse_width_lo; + u8 vsync_pulse_width_lo:4; + u8 vsync_offset_lo:4; + u8 hsync_pulse_width_hi:2; + u8 hsync_offset_hi:2; + u8 vsync_pulse_width_hi:2; + u8 vsync_offset_hi:2; + u8 width_mm_lo; + u8 height_mm_lo; + u8 height_mm_hi:4; + u8 width_mm_hi:4; + u8 hborder; + u8 vborder; + u8 unknown0:1; + u8 vsync_positive:1; + u8 hsync_positive:1; + u8 separate_sync:2; + u8 stereo:1; + u8 unknown6:1; + u8 interlaced:1; +} __attribute__((packed)); + +/* If it's not pixel timing, it'll be one of the below */ +struct detailed_data_string { + u8 str[13]; +} __attribute__((packed)); + +struct detailed_data_monitor_range { + u8 min_vfreq; + u8 max_vfreq; + u8 min_hfreq_khz; + u8 max_hfreq_khz; + u8 pixel_clock_mhz; /* need to multiply by 10 */ + u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */ + u8 hfreq_start_khz; /* need to multiply by 2 */ + u8 c; /* need to divide by 2 */ + u16 m; /* FIXME: byte order */ + u8 k; + u8 j; /* need to divide by 2 */ +} __attribute__((packed)); + +struct detailed_data_wpindex { + u8 white_y_lo:2; + u8 white_x_lo:2; + u8 pad:4; + u8 white_x_hi; + u8 white_y_hi; + u8 gamma; /* need to divide by 100 then add 1 */ +} __attribute__((packed)); + +struct detailed_data_color_point { + u8 windex1; + u8 wpindex1[3]; + u8 windex2; + u8 wpindex2[3]; +} __attribute__((packed)); + +struct detailed_non_pixel { + u8 pad1; + u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name + fb=color point data, fa=standard timing data, + f9=undefined, f8=mfg. reserved */ + u8 pad2; + union { + struct detailed_data_string str; + struct detailed_data_monitor_range range; + struct detailed_data_wpindex color; + struct std_timing timings[5]; + } data; +} __attribute__((packed)); + +#define EDID_DETAIL_STD_MODES 0xfa +#define EDID_DETAIL_MONITOR_CPDATA 0xfb +#define EDID_DETAIL_MONITOR_NAME 0xfc +#define EDID_DETAIL_MONITOR_RANGE 0xfd +#define EDID_DETAIL_MONITOR_STRING 0xfe +#define EDID_DETAIL_MONITOR_SERIAL 0xff + +struct detailed_timing { + u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */ + union { + struct detailed_pixel_timing pixel_data; + struct detailed_non_pixel other_data; + } data; +} __attribute__((packed)); + +struct edid { + u8 header[8]; + /* Vendor & product info */ + u8 mfg_id[2]; + u8 prod_code[2]; + u32 serial; /* FIXME: byte order */ + u8 mfg_week; + u8 mfg_year; + /* EDID version */ + u8 version; + u8 revision; + /* Display info: */ + /* input definition */ + u8 serration_vsync:1; + u8 sync_on_green:1; + u8 composite_sync:1; + u8 separate_syncs:1; + u8 blank_to_black:1; + u8 video_level:2; + u8 digital:1; /* bits below must be zero if set */ + u8 width_cm; + u8 height_cm; + u8 gamma; + /* feature support */ + u8 default_gtf:1; + u8 preferred_timing:1; + u8 standard_color:1; + u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ + u8 pm_active_off:1; + u8 pm_suspend:1; + u8 pm_standby:1; + /* Color characteristics */ + u8 red_green_lo; + u8 black_white_lo; + u8 red_x; + u8 red_y; + u8 green_x; + u8 green_y; + u8 blue_x; + u8 blue_y; + u8 white_x; + u8 white_y; + /* Est. timings and mfg rsvd timings*/ + struct est_timings established_timings; + /* Standard timings 1-8*/ + struct std_timing standard_timings[8]; + /* Detailing timings 1-4 */ + struct detailed_timing detailed_timings[4]; + /* Number of 128 byte ext. blocks */ + u8 extensions; + /* Checksum */ + u8 checksum; +} __attribute__((packed)); + +#endif /* little endian structs */ + +#define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) + +#endif /* __DRM_EDID_H__ */ diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h new file mode 100644 index 000000000000..601d2bd839f6 --- /dev/null +++ b/include/drm/drm_mode.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com> + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * 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 shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#if !defined(__KERNEL__) && !defined(_KERNEL) +#include <stdint.h> +#else +#include <linux/kernel.h> +#endif + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NON_GPU 0 +#define DRM_MODE_SCALE_FULLSCREEN 1 +#define DRM_MODE_SCALE_NO_SCALE 2 +#define DRM_MODE_SCALE_ASPECT 3 + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 + +struct drm_mode_modeinfo { + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; + uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + + uint32_t vrefresh; /* vertical refresh * 1000 */ + + uint32_t flags; + uint32_t type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + uint64_t fb_id_ptr; + uint64_t crtc_id_ptr; + uint64_t connector_id_ptr; + uint64_t encoder_id_ptr; + uint32_t count_fbs; + uint32_t count_crtcs; + uint32_t count_connectors; + uint32_t count_encoders; + uint32_t min_width, max_width; + uint32_t min_height, max_height; +}; + +struct drm_mode_crtc { + uint64_t set_connectors_ptr; + uint32_t count_connectors; + + uint32_t crtc_id; /**< Id */ + uint32_t fb_id; /**< Id of framebuffer */ + + uint32_t x, y; /**< Position on the frameuffer */ + + uint32_t gamma_size; + uint32_t mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 + +struct drm_mode_get_encoder { + uint32_t encoder_id; + uint32_t encoder_type; + + uint32_t crtc_id; /**< Id of crtc */ + + uint32_t possible_crtcs; + uint32_t possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 + +struct drm_mode_get_connector { + + uint64_t encoders_ptr; + uint64_t modes_ptr; + uint64_t props_ptr; + uint64_t prop_values_ptr; + + uint32_t count_modes; + uint32_t count_props; + uint32_t count_encoders; + + uint32_t encoder_id; /**< Current Encoder */ + uint32_t connector_id; /**< Id */ + uint32_t connector_type; + uint32_t connector_type_id; + + uint32_t connection; + uint32_t mm_width, mm_height; /**< HxW in millimeters */ + uint32_t subpixel; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) + +struct drm_mode_property_enum { + uint64_t value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + uint64_t values_ptr; /* values and blob lengths */ + uint64_t enum_blob_ptr; /* enum and blob id ptrs */ + + uint32_t prop_id; + uint32_t flags; + char name[DRM_PROP_NAME_LEN]; + + uint32_t count_values; + uint32_t count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + uint64_t value; + uint32_t prop_id; + uint32_t connector_id; +}; + +struct drm_mode_get_blob { + uint32_t blob_id; + uint32_t length; + uint64_t data; +}; + +struct drm_mode_fb_cmd { + uint32_t fb_id; + uint32_t width, height; + uint32_t pitch; + uint32_t bpp; + uint32_t depth; + /* driver specific handle */ + uint32_t handle; +}; + +struct drm_mode_mode_cmd { + uint32_t connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +/* + * depending on the value in flags diffrent members are used. + * + * CURSOR_BO uses + * crtc + * width + * height + * handle - if 0 turns the cursor of + * + * CURSOR_MOVE uses + * crtc + * x + * y + */ +struct drm_mode_cursor { + uint32_t flags; + uint32_t crtc_id; + int32_t x; + int32_t y; + uint32_t width; + uint32_t height; + /* driver specific handle */ + uint32_t handle; +}; + +struct drm_mode_crtc_lut { + uint32_t crtc_id; + uint32_t gamma_size; + + /* pointers to arrays */ + uint64_t red; + uint64_t green; + uint64_t blue; +}; + +#endif diff --git a/include/drm/drm_sarea.h b/include/drm/drm_sarea.h index 480037331e4e..ee5389d22c64 100644 --- a/include/drm/drm_sarea.h +++ b/include/drm/drm_sarea.h @@ -36,12 +36,12 @@ /* SAREA area needs to be at least a page */ #if defined(__alpha__) -#define SAREA_MAX 0x2000 +#define SAREA_MAX 0x2000U #elif defined(__ia64__) -#define SAREA_MAX 0x10000 /* 64kB */ +#define SAREA_MAX 0x10000U /* 64kB */ #else /* Intel 830M driver needs at least 8k SAREA */ -#define SAREA_MAX 0x2000 +#define SAREA_MAX 0x2000U #endif /** Maximum number of drawables in the SAREA */ diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 152b34da927c..b3bcf72dc656 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -113,8 +113,31 @@ typedef struct _drm_i915_sarea { int pipeB_y; int pipeB_w; int pipeB_h; + + /* fill out some space for old userspace triple buffer */ + drm_handle_t unused_handle; + uint32_t unused1, unused2, unused3; + + /* buffer object handles for static buffers. May change + * over the lifetime of the client. + */ + uint32_t front_bo_handle; + uint32_t back_bo_handle; + uint32_t unused_bo_handle; + uint32_t depth_bo_handle; + } drm_i915_sarea_t; +/* due to userspace building against these headers we need some compat here */ +#define planeA_x pipeA_x +#define planeA_y pipeA_y +#define planeA_w pipeA_w +#define planeA_h pipeA_h +#define planeB_x pipeB_x +#define planeB_y pipeB_y +#define planeB_w pipeB_w +#define planeB_h pipeB_h + /* Flags for perf_boxes */ #define I915_BOX_RING_EMPTY 0x1 @@ -160,6 +183,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_SET_TILING 0x21 #define DRM_I915_GEM_GET_TILING 0x22 #define DRM_I915_GEM_GET_APERTURE 0x23 +#define DRM_I915_GEM_MMAP_GTT 0x24 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -177,6 +201,8 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) #define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) #define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) #define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) @@ -187,6 +213,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) @@ -196,7 +223,7 @@ typedef struct _drm_i915_sarea { /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ -typedef struct _drm_i915_batchbuffer { +typedef struct drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ @@ -382,6 +409,18 @@ struct drm_i915_gem_mmap { uint64_t addr_ptr; }; +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + uint32_t handle; + uint32_t pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + uint64_t offset; +}; + struct drm_i915_gem_set_domain { /** Handle for the object */ uint32_t handle; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index e531783e5d78..95ac82340c3b 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -313,6 +313,7 @@ unifdef-y += ptrace.h unifdef-y += qnx4_fs.h unifdef-y += quota.h unifdef-y += random.h +unifdef-y += irqnr.h unifdef-y += reboot.h unifdef-y += reiserfs_fs.h unifdef-y += reiserfs_xattr.h diff --git a/include/linux/aio.h b/include/linux/aio.h index f6b8cf99b596..b16a957030f8 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -5,6 +5,7 @@ #include <linux/workqueue.h> #include <linux/aio_abi.h> #include <linux/uio.h> +#include <linux/rcupdate.h> #include <asm/atomic.h> @@ -183,7 +184,7 @@ struct kioctx { /* This needs improving */ unsigned long user_id; - struct kioctx *next; + struct hlist_node list; wait_queue_head_t wait; @@ -199,6 +200,8 @@ struct kioctx { struct aio_ring_info ring_info; struct delayed_work wq; + + struct rcu_head rcu_head; }; /* prototypes */ diff --git a/include/linux/bio.h b/include/linux/bio.h index 6a642098e5c3..18462c5b8fff 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -90,10 +90,11 @@ struct bio { unsigned int bi_comp_cpu; /* completion CPU */ + atomic_t bi_cnt; /* pin count */ + struct bio_vec *bi_io_vec; /* the actual vec list */ bio_end_io_t *bi_end_io; - atomic_t bi_cnt; /* pin count */ void *bi_private; #if defined(CONFIG_BLK_DEV_INTEGRITY) @@ -101,6 +102,13 @@ struct bio { #endif bio_destructor_t *bi_destructor; /* destructor */ + + /* + * We can inline a number of vecs at the end of the bio, to avoid + * double allocations for a small number of bio_vecs. This member + * MUST obviously be kept at the very end of the bio. + */ + struct bio_vec bi_inline_vecs[0]; }; /* @@ -117,6 +125,7 @@ struct bio { #define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ #define BIO_NULL_MAPPED 9 /* contains invalid user pages */ #define BIO_FS_INTEGRITY 10 /* fs owns integrity data, not block layer */ +#define BIO_QUIET 11 /* Make BIO Quiet */ #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) /* @@ -211,6 +220,11 @@ static inline void *bio_data(struct bio *bio) return NULL; } +static inline int bio_has_allocated_vec(struct bio *bio) +{ + return bio->bi_io_vec && bio->bi_io_vec != bio->bi_inline_vecs; +} + /* * will die */ @@ -332,7 +346,7 @@ struct bio_pair { extern struct bio_pair *bio_split(struct bio *bi, int first_sectors); extern void bio_pair_release(struct bio_pair *dbio); -extern struct bio_set *bioset_create(int, int); +extern struct bio_set *bioset_create(unsigned int, unsigned int); extern void bioset_free(struct bio_set *); extern struct bio *bio_alloc(gfp_t, int); @@ -377,6 +391,7 @@ extern struct bio *bio_copy_user_iov(struct request_queue *, extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *); +extern void bvec_free_bs(struct bio_set *, struct bio_vec *, unsigned int); extern unsigned int bvec_nr_vecs(unsigned short idx); /* @@ -395,13 +410,17 @@ static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu) */ #define BIO_POOL_SIZE 2 #define BIOVEC_NR_POOLS 6 +#define BIOVEC_MAX_IDX (BIOVEC_NR_POOLS - 1) struct bio_set { + struct kmem_cache *bio_slab; + unsigned int front_pad; + mempool_t *bio_pool; #if defined(CONFIG_BLK_DEV_INTEGRITY) mempool_t *bio_integrity_pool; #endif - mempool_t *bvec_pools[BIOVEC_NR_POOLS]; + mempool_t *bvec_pool; }; struct biovec_slab { @@ -411,6 +430,7 @@ struct biovec_slab { }; extern struct bio_set *fs_bio_set; +extern struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly; /* * a small number of entries is fine, not going to be performance critical. diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 031a315c0509..7035cec583b6 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -26,7 +26,6 @@ struct scsi_ioctl_command; struct request_queue; struct elevator_queue; -typedef struct elevator_queue elevator_t; struct request_pm_state; struct blk_trace; struct request; @@ -313,7 +312,7 @@ struct request_queue */ struct list_head queue_head; struct request *last_merge; - elevator_t *elevator; + struct elevator_queue *elevator; /* * the queue request freelist, one for reads and one for writes @@ -449,6 +448,7 @@ struct request_queue #define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ #define QUEUE_FLAG_STACKABLE 13 /* supports request stacking */ #define QUEUE_FLAG_NONROT 14 /* non-rotational device (SSD) */ +#define QUEUE_FLAG_VIRT QUEUE_FLAG_NONROT /* paravirt device */ static inline int queue_is_locked(struct request_queue *q) { @@ -522,22 +522,32 @@ enum { * TAG_FLUSH : ordering by tag w/ pre and post flushes * TAG_FUA : ordering by tag w/ pre flush and FUA write */ - QUEUE_ORDERED_NONE = 0x00, - QUEUE_ORDERED_DRAIN = 0x01, - QUEUE_ORDERED_TAG = 0x02, - - QUEUE_ORDERED_PREFLUSH = 0x10, - QUEUE_ORDERED_POSTFLUSH = 0x20, - QUEUE_ORDERED_FUA = 0x40, - - QUEUE_ORDERED_DRAIN_FLUSH = QUEUE_ORDERED_DRAIN | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH, - QUEUE_ORDERED_DRAIN_FUA = QUEUE_ORDERED_DRAIN | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA, - QUEUE_ORDERED_TAG_FLUSH = QUEUE_ORDERED_TAG | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH, - QUEUE_ORDERED_TAG_FUA = QUEUE_ORDERED_TAG | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA, + QUEUE_ORDERED_BY_DRAIN = 0x01, + QUEUE_ORDERED_BY_TAG = 0x02, + QUEUE_ORDERED_DO_PREFLUSH = 0x10, + QUEUE_ORDERED_DO_BAR = 0x20, + QUEUE_ORDERED_DO_POSTFLUSH = 0x40, + QUEUE_ORDERED_DO_FUA = 0x80, + + QUEUE_ORDERED_NONE = 0x00, + + QUEUE_ORDERED_DRAIN = QUEUE_ORDERED_BY_DRAIN | + QUEUE_ORDERED_DO_BAR, + QUEUE_ORDERED_DRAIN_FLUSH = QUEUE_ORDERED_DRAIN | + QUEUE_ORDERED_DO_PREFLUSH | + QUEUE_ORDERED_DO_POSTFLUSH, + QUEUE_ORDERED_DRAIN_FUA = QUEUE_ORDERED_DRAIN | + QUEUE_ORDERED_DO_PREFLUSH | + QUEUE_ORDERED_DO_FUA, + + QUEUE_ORDERED_TAG = QUEUE_ORDERED_BY_TAG | + QUEUE_ORDERED_DO_BAR, + QUEUE_ORDERED_TAG_FLUSH = QUEUE_ORDERED_TAG | + QUEUE_ORDERED_DO_PREFLUSH | + QUEUE_ORDERED_DO_POSTFLUSH, + QUEUE_ORDERED_TAG_FUA = QUEUE_ORDERED_TAG | + QUEUE_ORDERED_DO_PREFLUSH | + QUEUE_ORDERED_DO_FUA, /* * Ordered operation sequence @@ -585,7 +595,6 @@ enum { #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) #define blk_discard_rq(rq) ((rq)->cmd_flags & REQ_DISCARD) #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) -#define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) /* rq->queuelist of dequeued request must be list_empty() */ #define blk_queued_rq(rq) (!list_empty(&(rq)->queuelist)) @@ -855,10 +864,10 @@ extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); -extern int blk_do_ordered(struct request_queue *, struct request **); +extern bool blk_do_ordered(struct request_queue *, struct request **); extern unsigned blk_ordered_cur_seq(struct request_queue *); extern unsigned blk_ordered_req_seq(struct request *); -extern void blk_ordered_complete_seq(struct request_queue *, unsigned, int); +extern bool blk_ordered_complete_seq(struct request_queue *, unsigned, int); extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); extern void blk_dump_rq_flags(struct request *, char *); @@ -977,7 +986,6 @@ static inline void put_dev_sector(Sector p) struct work_struct; int kblockd_schedule_work(struct request_queue *q, struct work_struct *work); -void kblockd_flush_work(struct work_struct *work); #define MODULE_ALIAS_BLOCKDEV(major,minor) \ MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor)) diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h index 777dbf695d44..27b1bcffe408 100644 --- a/include/linux/bottom_half.h +++ b/include/linux/bottom_half.h @@ -2,7 +2,6 @@ #define _LINUX_BH_H extern void local_bh_disable(void); -extern void __local_bh_enable(void); extern void _local_bh_enable(void); extern void local_bh_enable(void); extern void local_bh_enable_ip(unsigned long ip); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 3ce64b90118c..8605f8a74df9 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -35,6 +35,7 @@ enum bh_state_bits { BH_Ordered, /* ordered write */ BH_Eopnotsupp, /* operation not supported (barrier) */ BH_Unwritten, /* Buffer is allocated on disk but not written */ + BH_Quiet, /* Buffer Error Prinks to be quiet */ BH_PrivateStart,/* not a state bit, but the first bit available * for private allocation by other entities diff --git a/include/linux/console.h b/include/linux/console.h index 248e6e3b9b73..a67a90cf8268 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -153,4 +153,8 @@ void vcs_remove_sysfs(struct tty_struct *tty); #define VESA_HSYNC_SUSPEND 2 #define VESA_POWERDOWN 3 +#ifdef CONFIG_VGA_CONSOLE +extern bool vgacon_text_force(void); +#endif + #endif /* _LINUX_CONSOLE_H */ diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index 4aaa4afb1cb9..096476f1fb35 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -17,7 +17,7 @@ extern int debug_locks_off(void); ({ \ int __ret = 0; \ \ - if (unlikely(c)) { \ + if (!oops_in_progress && unlikely(c)) { \ if (debug_locks_off() && !debug_locks_silent) \ WARN_ON(1); \ __ret = 1; \ diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 2bfda178f274..34161907b2f8 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -47,6 +47,7 @@ extern int dmi_name_in_vendors(const char *str); extern int dmi_name_in_serial(const char *str); extern int dmi_available; extern int dmi_walk(void (*decode)(const struct dmi_header *)); +extern bool dmi_match(enum dmi_field f, const char *str); #else @@ -61,6 +62,8 @@ static inline int dmi_name_in_serial(const char *s) { return 0; } #define dmi_available 0 static inline int dmi_walk(void (*decode)(const struct dmi_header *)) { return -1; } +static inline bool dmi_match(enum dmi_field f, const char *str) + { return false; } #endif diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 92f6f634e3e6..7a204256b155 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -28,7 +28,7 @@ typedef void (elevator_activate_req_fn) (struct request_queue *, struct request typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *); typedef void *(elevator_init_fn) (struct request_queue *); -typedef void (elevator_exit_fn) (elevator_t *); +typedef void (elevator_exit_fn) (struct elevator_queue *); struct elevator_ops { @@ -62,8 +62,8 @@ struct elevator_ops struct elv_fs_entry { struct attribute attr; - ssize_t (*show)(elevator_t *, char *); - ssize_t (*store)(elevator_t *, const char *, size_t); + ssize_t (*show)(struct elevator_queue *, char *); + ssize_t (*store)(struct elevator_queue *, const char *, size_t); }; /* @@ -130,7 +130,7 @@ extern ssize_t elv_iosched_show(struct request_queue *, char *); extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t); extern int elevator_init(struct request_queue *, char *); -extern void elevator_exit(elevator_t *); +extern void elevator_exit(struct elevator_queue *); extern int elv_rq_merge_ok(struct request *, struct bio *); /* diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h index 32368c4f0326..06ca9b21dad2 100644 --- a/include/linux/fault-inject.h +++ b/include/linux/fault-inject.h @@ -81,4 +81,13 @@ static inline void cleanup_fault_attr_dentries(struct fault_attr *attr) #endif /* CONFIG_FAULT_INJECTION */ +#ifdef CONFIG_FAILSLAB +extern bool should_failslab(size_t size, gfp_t gfpflags); +#else +static inline bool should_failslab(size_t size, gfp_t gfpflags) +{ + return false; +} +#endif /* CONFIG_FAILSLAB */ + #endif /* _LINUX_FAULT_INJECT_H */ diff --git a/include/linux/futex.h b/include/linux/futex.h index 586ab56a3ec3..3bf5bb5a34f9 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -25,7 +25,8 @@ union ktime; #define FUTEX_WAKE_BITSET 10 #define FUTEX_PRIVATE_FLAG 128 -#define FUTEX_CMD_MASK ~FUTEX_PRIVATE_FLAG +#define FUTEX_CLOCK_REALTIME 256 +#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) #define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) #define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) @@ -164,6 +165,8 @@ union futex_key { } both; }; +#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } } + #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); extern void exit_pi_state_list(struct task_struct *curr); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 3df7742ce246..16948eaecae3 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -126,6 +126,7 @@ struct blk_scsi_cmd_filter { struct disk_part_tbl { struct rcu_head rcu_head; int len; + struct hd_struct *last_lookup; struct hd_struct *part[]; }; diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 89a56d79e4c6..f83288347dda 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -119,13 +119,17 @@ static inline void account_system_vtime(struct task_struct *tsk) } #endif -#if defined(CONFIG_PREEMPT_RCU) && defined(CONFIG_NO_HZ) +#if defined(CONFIG_NO_HZ) && !defined(CONFIG_CLASSIC_RCU) extern void rcu_irq_enter(void); extern void rcu_irq_exit(void); +extern void rcu_nmi_enter(void); +extern void rcu_nmi_exit(void); #else # define rcu_irq_enter() do { } while (0) # define rcu_irq_exit() do { } while (0) -#endif /* CONFIG_PREEMPT_RCU */ +# define rcu_nmi_enter() do { } while (0) +# define rcu_nmi_exit() do { } while (0) +#endif /* #if defined(CONFIG_NO_HZ) && !defined(CONFIG_CLASSIC_RCU) */ /* * It is safe to do non-atomic ops on ->hardirq_context, @@ -135,7 +139,6 @@ extern void rcu_irq_exit(void); */ #define __irq_enter() \ do { \ - rcu_irq_enter(); \ account_system_vtime(current); \ add_preempt_count(HARDIRQ_OFFSET); \ trace_hardirq_enter(); \ @@ -154,7 +157,6 @@ extern void irq_enter(void); trace_hardirq_exit(); \ account_system_vtime(current); \ sub_preempt_count(HARDIRQ_OFFSET); \ - rcu_irq_exit(); \ } while (0) /* @@ -166,11 +168,14 @@ extern void irq_exit(void); do { \ ftrace_nmi_enter(); \ lockdep_off(); \ + rcu_nmi_enter(); \ __irq_enter(); \ } while (0) + #define nmi_exit() \ do { \ __irq_exit(); \ + rcu_nmi_exit(); \ lockdep_on(); \ ftrace_nmi_exit(); \ } while (0) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 3eba43878dcb..bd37078c2d7d 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -43,26 +43,6 @@ enum hrtimer_restart { }; /* - * hrtimer callback modes: - * - * HRTIMER_CB_SOFTIRQ: Callback must run in softirq context - * HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context - * Special mode for tick emulation and - * scheduler timer. Such timers are per - * cpu and not allowed to be migrated on - * cpu unplug. - * HRTIMER_CB_IRQSAFE_UNLOCKED: Callback should run in hardirq context - * with timer->base lock unlocked - * used for timers which call wakeup to - * avoid lock order problems with rq->lock - */ -enum hrtimer_cb_mode { - HRTIMER_CB_SOFTIRQ, - HRTIMER_CB_IRQSAFE_PERCPU, - HRTIMER_CB_IRQSAFE_UNLOCKED, -}; - -/* * Values to track state of the timer * * Possible states: @@ -70,7 +50,6 @@ enum hrtimer_cb_mode { * 0x00 inactive * 0x01 enqueued into rbtree * 0x02 callback function running - * 0x04 callback pending (high resolution mode) * * Special cases: * 0x03 callback function running and enqueued @@ -92,8 +71,7 @@ enum hrtimer_cb_mode { #define HRTIMER_STATE_INACTIVE 0x00 #define HRTIMER_STATE_ENQUEUED 0x01 #define HRTIMER_STATE_CALLBACK 0x02 -#define HRTIMER_STATE_PENDING 0x04 -#define HRTIMER_STATE_MIGRATE 0x08 +#define HRTIMER_STATE_MIGRATE 0x04 /** * struct hrtimer - the basic hrtimer structure @@ -109,8 +87,6 @@ enum hrtimer_cb_mode { * @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) - * @cb_mode: high resolution timer feature to select the callback execution - * mode * @cb_entry: list head to enqueue an expired timer into the callback list * @start_site: timer statistics field to store the site where the timer * was started @@ -129,7 +105,6 @@ struct hrtimer { struct hrtimer_clock_base *base; unsigned long state; struct list_head cb_entry; - enum hrtimer_cb_mode cb_mode; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; @@ -188,15 +163,11 @@ struct hrtimer_clock_base { * @check_clocks: Indictator, when set evaluate time source and clock * event devices whether high resolution mode can be * activated. - * @cb_pending: Expired timers are moved from the rbtree to this - * list in the timer interrupt. The list is processed - * in the softirq. * @nr_events: Total number of timer interrupt events */ struct hrtimer_cpu_base { spinlock_t lock; struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; - struct list_head cb_pending; #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; @@ -404,8 +375,7 @@ static inline int hrtimer_active(const struct hrtimer *timer) */ static inline int hrtimer_is_queued(struct hrtimer *timer) { - return timer->state & - (HRTIMER_STATE_ENQUEUED | HRTIMER_STATE_PENDING); + return timer->state & HRTIMER_STATE_ENQUEUED; } /* diff --git a/include/linux/ide.h b/include/linux/ide.h index 010fb26a1579..e99c56de7f56 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -122,8 +122,6 @@ struct ide_io_ports { #define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */ #define SECTOR_SIZE 512 -#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t))) - /* * Timeouts for various operations: */ @@ -172,9 +170,7 @@ typedef int (ide_ack_intr_t)(struct hwif_s *); enum { ide_unknown, ide_generic, ide_pci, ide_cmd640, ide_dtc2278, ide_ali14xx, ide_qd65xx, ide_umc8672, ide_ht6560b, - ide_rz1000, ide_trm290, - ide_cmd646, ide_cy82c693, ide_4drives, - ide_pmac, ide_acorn, + ide_4drives, ide_pmac, ide_acorn, ide_au1xxx, ide_palm3710 }; @@ -496,8 +492,6 @@ enum { * when more than one interrupt is needed. */ IDE_AFLAG_LIMIT_NFRAMES = (1 << 7), - /* Seeking in progress. */ - IDE_AFLAG_SEEKING = (1 << 8), /* Saved TOC information is current. */ IDE_AFLAG_TOC_VALID = (1 << 9), /* We think that the drive door is locked. */ @@ -845,8 +839,6 @@ typedef struct hwif_s { unsigned extra_ports; /* number of extra dma ports */ unsigned present : 1; /* this interface exists */ - unsigned serialized : 1; /* serialized all channel operation */ - unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ struct device gendev; @@ -909,6 +901,8 @@ typedef struct hwgroup_s { int req_gen; int req_gen_timer; + + spinlock_t lock; } ide_hwgroup_t; typedef struct ide_driver_s ide_driver_t; @@ -1122,6 +1116,14 @@ enum { IDE_PM_COMPLETED, }; +int generic_ide_suspend(struct device *, pm_message_t); +int generic_ide_resume(struct device *); + +void ide_complete_power_step(ide_drive_t *, struct request *); +ide_startstop_t ide_start_power_step(ide_drive_t *, struct request *); +void ide_complete_pm_request(ide_drive_t *, struct request *); +void ide_check_pm_state(ide_drive_t *, struct request *); + /* * Subdrivers support. * @@ -1376,8 +1378,8 @@ enum { IDE_HFLAG_LEGACY_IRQS = (1 << 21), /* force use of legacy IRQs */ IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22), - /* limit LBA48 requests to 256 sectors */ - IDE_HFLAG_RQSIZE_256 = (1 << 23), + /* host is TRM290 */ + IDE_HFLAG_TRM290 = (1 << 23), /* use 32-bit I/O ops */ IDE_HFLAG_IO_32BIT = (1 << 24), /* unmask IRQs */ @@ -1415,6 +1417,9 @@ struct ide_port_info { ide_pci_enablebit_t enablebits[2]; hwif_chipset_t chipset; + + u16 max_sectors; /* if < than the default one */ + u32 host_flags; u8 pio_mask; u8 swdma_mask; @@ -1610,13 +1615,13 @@ extern struct mutex ide_cfg_mtx; /* * Structure locking: * - * ide_cfg_mtx and ide_lock together protect changes to - * ide_hwif_t->{next,hwgroup} + * ide_cfg_mtx and hwgroup->lock together protect changes to + * ide_hwif_t->next * ide_drive_t->next * - * ide_hwgroup_t->busy: ide_lock - * ide_hwgroup_t->hwif: ide_lock - * ide_hwif_t->mate: constant, no locking + * ide_hwgroup_t->busy: hwgroup->lock + * ide_hwgroup_t->hwif: hwgroup->lock + * ide_hwif_t->{hwgroup,mate}: constant, no locking * ide_drive_t->hwif: constant, no locking */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index f58a0cf8929a..be3c484b5242 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -14,6 +14,8 @@ #include <linux/irqflags.h> #include <linux/smp.h> #include <linux/percpu.h> +#include <linux/irqnr.h> + #include <asm/atomic.h> #include <asm/ptrace.h> #include <asm/system.h> @@ -251,9 +253,6 @@ enum BLOCK_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, -#ifdef CONFIG_HIGH_RES_TIMERS - HRTIMER_SOFTIRQ, -#endif RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS diff --git a/include/linux/irq.h b/include/linux/irq.h index 3dddfa703ebd..98564dc64476 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -129,9 +129,14 @@ struct irq_chip { const char *typename; }; +struct timer_rand_state; +struct irq_2_iommu; /** * struct irq_desc - interrupt descriptor * @irq: interrupt number for this descriptor + * @timer_rand_state: pointer to timer rand state struct + * @kstat_irqs: irq stats per cpu + * @irq_2_iommu: iommu with this irq * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] * @chip: low level interrupt hardware access * @msi_desc: MSI descriptor @@ -143,8 +148,8 @@ struct irq_chip { * @depth: disable-depth, for nested irq_disable() calls * @wake_depth: enable depth, for multiple set_irq_wake() callers * @irq_count: stats field to detect stalled irqs - * @irqs_unhandled: stats field for spurious unhandled interrupts * @last_unhandled: aging timer for unhandled count + * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP * @affinity: IRQ affinity on SMP * @cpu: cpu index useful for balancing @@ -154,6 +159,13 @@ struct irq_chip { */ struct irq_desc { unsigned int irq; +#ifdef CONFIG_SPARSE_IRQ + struct timer_rand_state *timer_rand_state; + unsigned int *kstat_irqs; +# ifdef CONFIG_INTR_REMAP + struct irq_2_iommu *irq_2_iommu; +# endif +#endif irq_flow_handler_t handle_irq; struct irq_chip *chip; struct msi_desc *msi_desc; @@ -165,8 +177,8 @@ struct irq_desc { unsigned int depth; /* nested irq disables */ unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ - unsigned int irqs_unhandled; unsigned long last_unhandled; /* Aging timer for unhandled count */ + unsigned int irqs_unhandled; spinlock_t lock; #ifdef CONFIG_SMP cpumask_t affinity; @@ -181,12 +193,51 @@ struct irq_desc { const char *name; } ____cacheline_internodealigned_in_smp; +extern void early_irq_init(void); +extern void arch_early_irq_init(void); +extern void arch_init_chip_data(struct irq_desc *desc, int cpu); +extern void arch_init_copy_chip_data(struct irq_desc *old_desc, + struct irq_desc *desc, int cpu); +extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc); +#ifndef CONFIG_SPARSE_IRQ extern struct irq_desc irq_desc[NR_IRQS]; static inline struct irq_desc *irq_to_desc(unsigned int irq) { - return (irq < nr_irqs) ? irq_desc + irq : NULL; + return (irq < NR_IRQS) ? irq_desc + irq : NULL; +} +static inline struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) +{ + return irq_to_desc(irq); +} + +#else + +extern struct irq_desc *irq_to_desc(unsigned int irq); +extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu); +extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu); + +# define for_each_irq_desc(irq, desc) \ + for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; irq++, desc = irq_to_desc(irq)) +# define for_each_irq_desc_reverse(irq, desc) \ + for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; irq--, desc = irq_to_desc(irq)) + +#define kstat_irqs_this_cpu(DESC) \ + ((DESC)->kstat_irqs[smp_processor_id()]) +#define kstat_incr_irqs_this_cpu(irqno, DESC) \ + ((DESC)->kstat_irqs[smp_processor_id()]++) + +#endif + +static inline struct irq_desc * +irq_remap_to_desc(unsigned int irq, struct irq_desc *desc) +{ +#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC + return irq_to_desc(irq); +#else + return desc; +#endif } /* @@ -380,6 +431,11 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); #define get_irq_data(irq) (irq_to_desc(irq)->handler_data) #define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc) +#define get_irq_desc_chip(desc) ((desc)->chip) +#define get_irq_desc_chip_data(desc) ((desc)->chip_data) +#define get_irq_desc_data(desc) ((desc)->handler_data) +#define get_irq_desc_msi(desc) ((desc)->msi_desc) + #endif /* CONFIG_GENERIC_HARDIRQS */ #endif /* !CONFIG_S390 */ diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index 452c280c8115..95d2b74641f5 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h @@ -1,24 +1,38 @@ #ifndef _LINUX_IRQNR_H #define _LINUX_IRQNR_H +/* + * Generic irq_desc iterators: + */ +#ifdef __KERNEL__ + #ifndef CONFIG_GENERIC_HARDIRQS #include <asm/irq.h> # define nr_irqs NR_IRQS # define for_each_irq_desc(irq, desc) \ for (irq = 0; irq < nr_irqs; irq++) + +# define for_each_irq_desc_reverse(irq, desc) \ + for (irq = nr_irqs - 1; irq >= 0; irq--) #else + extern int nr_irqs; +#ifndef CONFIG_SPARSE_IRQ + +struct irq_desc; # define for_each_irq_desc(irq, desc) \ for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++) - -# define for_each_irq_desc_reverse(irq, desc) \ - for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \ - irq >= 0; irq--, desc--) +# define for_each_irq_desc_reverse(irq, desc) \ + for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \ + irq >= 0; irq--, desc--) +#endif #endif -#define for_each_irq_nr(irq) \ - for (irq = 0; irq < nr_irqs; irq++) +#define for_each_irq_nr(irq) \ + for (irq = 0; irq < nr_irqs; irq++) + +#endif /* __KERNEL__ */ #endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 6002ae76785c..ca9ff6411dfa 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -141,6 +141,15 @@ extern int _cond_resched(void); (__x < 0) ? -__x : __x; \ }) +#ifdef CONFIG_PROVE_LOCKING +void might_fault(void); +#else +static inline void might_fault(void) +{ + might_sleep(); +} +#endif + extern struct atomic_notifier_head panic_notifier_list; extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) @@ -188,6 +197,8 @@ extern unsigned long long memparse(const char *ptr, char **retptr); extern int core_kernel_text(unsigned long addr); extern int __kernel_text_address(unsigned long addr); extern int kernel_text_address(unsigned long addr); +extern int func_ptr_is_kernel_text(void *ptr); + struct pid; extern struct pid *session_of_pgrp(struct pid *pgrp); diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 4a145caeee07..4ee4b3d2316f 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -28,7 +28,9 @@ struct cpu_usage_stat { struct kernel_stat { struct cpu_usage_stat cpustat; - unsigned int irqs[NR_IRQS]; +#ifndef CONFIG_SPARSE_IRQ + unsigned int irqs[NR_IRQS]; +#endif }; DECLARE_PER_CPU(struct kernel_stat, kstat); @@ -39,6 +41,10 @@ DECLARE_PER_CPU(struct kernel_stat, kstat); extern unsigned long long nr_context_switches(void); +#ifndef CONFIG_SPARSE_IRQ +#define kstat_irqs_this_cpu(irq) \ + (kstat_this_cpu.irqs[irq]) + struct irq_desc; static inline void kstat_incr_irqs_this_cpu(unsigned int irq, @@ -46,11 +52,17 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, { kstat_this_cpu.irqs[irq]++; } +#endif + +#ifndef CONFIG_SPARSE_IRQ static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) { return kstat_cpu(cpu).irqs[irq]; } +#else +extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); +#endif /* * Number of interrupts per specific IRQ source, since bootup diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h index e7217dc58f39..a53407a4165c 100644 --- a/include/linux/lguest_launcher.h +++ b/include/linux/lguest_launcher.h @@ -54,9 +54,13 @@ struct lguest_vqconfig { /* Write command first word is a request. */ enum lguest_req { - LHREQ_INITIALIZE, /* + base, pfnlimit, pgdir, start */ + LHREQ_INITIALIZE, /* + base, pfnlimit, start */ LHREQ_GETDMA, /* No longer used */ LHREQ_IRQ, /* + irq */ LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */ }; + +/* The alignment to use between consumer and producer parts of vring. + * x86 pagesize for historical reasons. */ +#define LGUEST_VRING_ALIGN 4096 #endif /* _LINUX_LGUEST_LAUNCHER */ diff --git a/include/linux/libata.h b/include/linux/libata.h index ed3f26eb5df1..3449de597eff 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -213,10 +213,11 @@ enum { ATA_PFLAG_FROZEN = (1 << 2), /* port is frozen */ ATA_PFLAG_RECOVERED = (1 << 3), /* recovery action performed */ ATA_PFLAG_LOADING = (1 << 4), /* boot/loading probe */ - ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */ ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */ ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */ ATA_PFLAG_RESETTING = (1 << 8), /* reset in progress */ + ATA_PFLAG_UNLOADING = (1 << 9), /* driver is being unloaded */ + ATA_PFLAG_UNLOADED = (1 << 10), /* driver is unloaded */ ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ @@ -1285,26 +1286,62 @@ static inline int ata_link_active(struct ata_link *link) return ata_tag_valid(link->active_tag) || link->sactive; } -extern struct ata_link *__ata_port_next_link(struct ata_port *ap, - struct ata_link *link, - bool dev_only); +/* + * Iterators + * + * ATA_LITER_* constants are used to select link iteration mode and + * ATA_DITER_* device iteration mode. + * + * For a custom iteration directly using ata_{link|dev}_next(), if + * @link or @dev, respectively, is NULL, the first element is + * returned. @dev and @link can be any valid device or link and the + * next element according to the iteration mode will be returned. + * After the last element, NULL is returned. + */ +enum ata_link_iter_mode { + ATA_LITER_EDGE, /* if present, PMP links only; otherwise, + * host link. no slave link */ + ATA_LITER_HOST_FIRST, /* host link followed by PMP or slave links */ + ATA_LITER_PMP_FIRST, /* PMP links followed by host link, + * slave link still comes after host link */ +}; -#define __ata_port_for_each_link(link, ap) \ - for ((link) = __ata_port_next_link((ap), NULL, false); (link); \ - (link) = __ata_port_next_link((ap), (link), false)) +enum ata_dev_iter_mode { + ATA_DITER_ENABLED, + ATA_DITER_ENABLED_REVERSE, + ATA_DITER_ALL, + ATA_DITER_ALL_REVERSE, +}; -#define ata_port_for_each_link(link, ap) \ - for ((link) = __ata_port_next_link((ap), NULL, true); (link); \ - (link) = __ata_port_next_link((ap), (link), true)) +extern struct ata_link *ata_link_next(struct ata_link *link, + struct ata_port *ap, + enum ata_link_iter_mode mode); -#define ata_link_for_each_dev(dev, link) \ - for ((dev) = (link)->device; \ - (dev) < (link)->device + ata_link_max_devices(link) || ((dev) = NULL); \ - (dev)++) +extern struct ata_device *ata_dev_next(struct ata_device *dev, + struct ata_link *link, + enum ata_dev_iter_mode mode); + +/* + * Shortcut notation for iterations + * + * ata_for_each_link() iterates over each link of @ap according to + * @mode. @link points to the current link in the loop. @link is + * NULL after loop termination. ata_for_each_dev() works the same way + * except that it iterates over each device of @link. + * + * Note that the mode prefixes ATA_{L|D}ITER_ shouldn't need to be + * specified when using the following shorthand notations. Only the + * mode itself (EDGE, HOST_FIRST, ENABLED, etc...) should be + * specified. This not only increases brevity but also makes it + * impossible to use ATA_LITER_* for device iteration or vice-versa. + */ +#define ata_for_each_link(link, ap, mode) \ + for ((link) = ata_link_next(NULL, (ap), ATA_LITER_##mode); (link); \ + (link) = ata_link_next((link), (ap), ATA_LITER_##mode)) -#define ata_link_for_each_dev_reverse(dev, link) \ - for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \ - (dev) >= (link)->device || ((dev) = NULL); (dev)--) +#define ata_for_each_dev(dev, link, mode) \ + for ((dev) = ata_dev_next(NULL, (link), ATA_DITER_##mode); (dev); \ + (dev) = ata_dev_next((dev), (link), ATA_DITER_##mode)) /** * ata_ncq_enabled - Test whether NCQ is enabled diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 29aec6e10020..23bf02fb124f 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -73,6 +73,8 @@ struct lock_class_key { struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; }; +#define LOCKSTAT_POINTS 4 + /* * The lock-class itself: */ @@ -119,7 +121,8 @@ struct lock_class { int name_version; #ifdef CONFIG_LOCK_STAT - unsigned long contention_point[4]; + unsigned long contention_point[LOCKSTAT_POINTS]; + unsigned long contending_point[LOCKSTAT_POINTS]; #endif }; @@ -144,6 +147,7 @@ enum bounce_type { struct lock_class_stats { unsigned long contention_point[4]; + unsigned long contending_point[4]; struct lock_time read_waittime; struct lock_time write_waittime; struct lock_time read_holdtime; @@ -165,6 +169,7 @@ struct lockdep_map { const char *name; #ifdef CONFIG_LOCK_STAT int cpu; + unsigned long ip; #endif }; @@ -309,8 +314,15 @@ extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass, extern void lock_release(struct lockdep_map *lock, int nested, unsigned long ip); -extern void lock_set_subclass(struct lockdep_map *lock, unsigned int subclass, - unsigned long ip); +extern void lock_set_class(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, unsigned int subclass, + unsigned long ip); + +static inline void lock_set_subclass(struct lockdep_map *lock, + unsigned int subclass, unsigned long ip) +{ + lock_set_class(lock, lock->name, lock->key, subclass, ip); +} # define INIT_LOCKDEP .lockdep_recursion = 0, @@ -328,6 +340,7 @@ static inline void lockdep_on(void) # define lock_acquire(l, s, t, r, c, n, i) do { } while (0) # define lock_release(l, n, i) do { } while (0) +# define lock_set_class(l, n, k, s, i) do { } while (0) # define lock_set_subclass(l, s, i) do { } while (0) # define lockdep_init() do { } while (0) # define lockdep_info() do { } while (0) @@ -356,7 +369,7 @@ struct lock_class_key { }; #ifdef CONFIG_LOCK_STAT extern void lock_contended(struct lockdep_map *lock, unsigned long ip); -extern void lock_acquired(struct lockdep_map *lock); +extern void lock_acquired(struct lockdep_map *lock, unsigned long ip); #define LOCK_CONTENDED(_lock, try, lock) \ do { \ @@ -364,20 +377,20 @@ do { \ lock_contended(&(_lock)->dep_map, _RET_IP_); \ lock(_lock); \ } \ - lock_acquired(&(_lock)->dep_map); \ + lock_acquired(&(_lock)->dep_map, _RET_IP_); \ } while (0) #else /* CONFIG_LOCK_STAT */ #define lock_contended(lockdep_map, ip) do {} while (0) -#define lock_acquired(lockdep_map) do {} while (0) +#define lock_acquired(lockdep_map, ip) do {} while (0) #define LOCK_CONTENDED(_lock, try, lock) \ lock(_lock) #endif /* CONFIG_LOCK_STAT */ -#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS) +#ifdef CONFIG_GENERIC_HARDIRQS extern void early_init_irq_lock_class(void); #else static inline void early_init_irq_lock_class(void) @@ -481,4 +494,22 @@ static inline void print_irqtrace_events(struct task_struct *curr) # define lock_map_release(l) do { } while (0) #endif +#ifdef CONFIG_PROVE_LOCKING +# define might_lock(lock) \ +do { \ + typecheck(struct lockdep_map *, &(lock)->dep_map); \ + lock_acquire(&(lock)->dep_map, 0, 0, 0, 2, NULL, _THIS_IP_); \ + lock_release(&(lock)->dep_map, 0, _THIS_IP_); \ +} while (0) +# define might_lock_read(lock) \ +do { \ + typecheck(struct lockdep_map *, &(lock)->dep_map); \ + lock_acquire(&(lock)->dep_map, 0, 0, 1, 2, NULL, _THIS_IP_); \ + lock_release(&(lock)->dep_map, 0, _THIS_IP_); \ +} while (0) +#else +# define might_lock(lock) do { } while (0) +# define might_lock_read(lock) do { } while (0) +#endif + #endif /* __LINUX_LOCKDEP_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index fe825471d5aa..9cfc9b627fdd 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -232,8 +232,9 @@ struct mm_struct { struct core_state *core_state; /* coredumping support */ /* aio bits */ - rwlock_t ioctx_list_lock; /* aio lock */ - struct kioctx *ioctx_list; + spinlock_t ioctx_lock; + struct hlist_head ioctx_list; + #ifdef CONFIG_MM_OWNER /* * "owner" points to a task that is regarded as the canonical diff --git a/include/linux/msi.h b/include/linux/msi.h index 8f2939227207..d2b8a1e8ca11 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -10,8 +10,11 @@ struct msi_msg { }; /* Helper functions */ +struct irq_desc; extern void mask_msi_irq(unsigned int irq); extern void unmask_msi_irq(unsigned int irq); +extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); +extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); diff --git a/include/linux/mutex.h b/include/linux/mutex.h index bc6da10ceee0..7a0e5c4f8072 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -144,6 +144,8 @@ extern int __must_check mutex_lock_killable(struct mutex *lock); /* * NOTE: mutex_trylock() follows the spin_trylock() convention, * not the down_trylock() convention! + * + * Returns 1 if the mutex has been acquired successfully, and 0 on contention. */ extern int mutex_trylock(struct mutex *lock); extern void mutex_unlock(struct mutex *lock); diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index a8efcfeea732..3d327b67d7e2 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -26,8 +26,7 @@ extern struct bus_type of_platform_bus_type; /* * An of_platform_driver driver is attached to a basic of_device on - * the "platform bus" (of_platform_bus_type) (or ISA, EBUS and SBUS - * busses on sparc). + * the "platform bus" (of_platform_bus_type). */ struct of_platform_driver { diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 5231861f357d..1ce9fe572e51 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -86,8 +86,7 @@ int oprofile_arch_init(struct oprofile_operations * ops); void oprofile_arch_exit(void); /** - * Add a sample. This may be called from any context. Pass - * smp_processor_id() as cpu. + * Add a sample. This may be called from any context. */ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event); diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index a7c721355549..4f71bf4e628c 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -45,7 +45,11 @@ struct k_itimer { int it_requeue_pending; /* waiting to requeue this timer */ #define REQUEUE_PENDING 1 int it_sigev_notify; /* notify word of sigevent struct */ - struct task_struct *it_process; /* process to send signal to */ + struct signal_struct *it_signal; + union { + struct pid *it_pid; /* pid of process to send signal to */ + struct task_struct *it_process; /* for clock_nanosleep */ + }; struct sigqueue *sigq; /* signal queue entry. */ union { struct { diff --git a/include/linux/random.h b/include/linux/random.h index 36f125c0c603..adbf3bd3c6b3 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -8,6 +8,7 @@ #define _LINUX_RANDOM_H #include <linux/ioctl.h> +#include <linux/irqnr.h> /* ioctl()'s for the random number generator */ @@ -44,6 +45,56 @@ struct rand_pool_info { extern void rand_initialize_irq(int irq); +struct timer_rand_state; +#ifndef CONFIG_SPARSE_IRQ + +extern struct timer_rand_state *irq_timer_state[]; + +static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq) +{ + if (irq >= nr_irqs) + return NULL; + + return irq_timer_state[irq]; +} + +static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state) +{ + if (irq >= nr_irqs) + return; + + irq_timer_state[irq] = state; +} + +#else + +#include <linux/irq.h> +static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq) +{ + struct irq_desc *desc; + + desc = irq_to_desc(irq); + + if (!desc) + return NULL; + + return desc->timer_rand_state; +} + +static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state) +{ + struct irq_desc *desc; + + desc = irq_to_desc(irq); + + if (!desc) + return; + + desc->timer_rand_state = state; +} +#endif + + extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); extern void add_interrupt_randomness(int irq); diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index 5f89b62e6983..301dda829e37 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h @@ -41,7 +41,7 @@ #include <linux/seqlock.h> #ifdef CONFIG_RCU_CPU_STALL_DETECTOR -#define RCU_SECONDS_TILL_STALL_CHECK ( 3 * HZ) /* for rcp->jiffies_stall */ +#define RCU_SECONDS_TILL_STALL_CHECK (10 * HZ) /* for rcp->jiffies_stall */ #define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ) /* for rcp->jiffies_stall */ #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 895dc9c1088c..1168fbcea8d4 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -52,11 +52,15 @@ struct rcu_head { void (*func)(struct rcu_head *head); }; -#ifdef CONFIG_CLASSIC_RCU +#if defined(CONFIG_CLASSIC_RCU) #include <linux/rcuclassic.h> -#else /* #ifdef CONFIG_CLASSIC_RCU */ +#elif defined(CONFIG_TREE_RCU) +#include <linux/rcutree.h> +#elif defined(CONFIG_PREEMPT_RCU) #include <linux/rcupreempt.h> -#endif /* #else #ifdef CONFIG_CLASSIC_RCU */ +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif /* #else #if defined(CONFIG_CLASSIC_RCU) */ #define RCU_HEAD_INIT { .next = NULL, .func = NULL } #define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h new file mode 100644 index 000000000000..d4368b7975c3 --- /dev/null +++ b/include/linux/rcutree.h @@ -0,0 +1,329 @@ +/* + * Read-Copy Update mechanism for mutual exclusion (tree-based version) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2008 + * + * Author: Dipankar Sarma <dipankar@in.ibm.com> + * Paul E. McKenney <paulmck@linux.vnet.ibm.com> Hierarchical algorithm + * + * Based on the original work by Paul McKenney <paulmck@us.ibm.com> + * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. + * + * For detailed explanation of Read-Copy Update mechanism see - + * Documentation/RCU + */ + +#ifndef __LINUX_RCUTREE_H +#define __LINUX_RCUTREE_H + +#include <linux/cache.h> +#include <linux/spinlock.h> +#include <linux/threads.h> +#include <linux/percpu.h> +#include <linux/cpumask.h> +#include <linux/seqlock.h> + +/* + * Define shape of hierarchy based on NR_CPUS and CONFIG_RCU_FANOUT. + * In theory, it should be possible to add more levels straightforwardly. + * In practice, this has not been tested, so there is probably some + * bug somewhere. + */ +#define MAX_RCU_LVLS 3 +#define RCU_FANOUT (CONFIG_RCU_FANOUT) +#define RCU_FANOUT_SQ (RCU_FANOUT * RCU_FANOUT) +#define RCU_FANOUT_CUBE (RCU_FANOUT_SQ * RCU_FANOUT) + +#if NR_CPUS <= RCU_FANOUT +# define NUM_RCU_LVLS 1 +# define NUM_RCU_LVL_0 1 +# define NUM_RCU_LVL_1 (NR_CPUS) +# define NUM_RCU_LVL_2 0 +# define NUM_RCU_LVL_3 0 +#elif NR_CPUS <= RCU_FANOUT_SQ +# define NUM_RCU_LVLS 2 +# define NUM_RCU_LVL_0 1 +# define NUM_RCU_LVL_1 (((NR_CPUS) + RCU_FANOUT - 1) / RCU_FANOUT) +# define NUM_RCU_LVL_2 (NR_CPUS) +# define NUM_RCU_LVL_3 0 +#elif NR_CPUS <= RCU_FANOUT_CUBE +# define NUM_RCU_LVLS 3 +# define NUM_RCU_LVL_0 1 +# define NUM_RCU_LVL_1 (((NR_CPUS) + RCU_FANOUT_SQ - 1) / RCU_FANOUT_SQ) +# define NUM_RCU_LVL_2 (((NR_CPUS) + (RCU_FANOUT) - 1) / (RCU_FANOUT)) +# define NUM_RCU_LVL_3 NR_CPUS +#else +# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS" +#endif /* #if (NR_CPUS) <= RCU_FANOUT */ + +#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3) +#define NUM_RCU_NODES (RCU_SUM - NR_CPUS) + +/* + * Dynticks per-CPU state. + */ +struct rcu_dynticks { + int dynticks_nesting; /* Track nesting level, sort of. */ + int dynticks; /* Even value for dynticks-idle, else odd. */ + int dynticks_nmi; /* Even value for either dynticks-idle or */ + /* not in nmi handler, else odd. So this */ + /* remains even for nmi from irq handler. */ +}; + +/* + * Definition for node within the RCU grace-period-detection hierarchy. + */ +struct rcu_node { + spinlock_t lock; + unsigned long qsmask; /* CPUs or groups that need to switch in */ + /* order for current grace period to proceed.*/ + unsigned long qsmaskinit; + /* Per-GP initialization for qsmask. */ + unsigned long grpmask; /* Mask to apply to parent qsmask. */ + int grplo; /* lowest-numbered CPU or group here. */ + int grphi; /* highest-numbered CPU or group here. */ + u8 grpnum; /* CPU/group number for next level up. */ + u8 level; /* root is at level 0. */ + struct rcu_node *parent; +} ____cacheline_internodealigned_in_smp; + +/* Index values for nxttail array in struct rcu_data. */ +#define RCU_DONE_TAIL 0 /* Also RCU_WAIT head. */ +#define RCU_WAIT_TAIL 1 /* Also RCU_NEXT_READY head. */ +#define RCU_NEXT_READY_TAIL 2 /* Also RCU_NEXT head. */ +#define RCU_NEXT_TAIL 3 +#define RCU_NEXT_SIZE 4 + +/* Per-CPU data for read-copy update. */ +struct rcu_data { + /* 1) quiescent-state and grace-period handling : */ + long completed; /* Track rsp->completed gp number */ + /* in order to detect GP end. */ + long gpnum; /* Highest gp number that this CPU */ + /* is aware of having started. */ + long passed_quiesc_completed; + /* Value of completed at time of qs. */ + bool passed_quiesc; /* User-mode/idle loop etc. */ + bool qs_pending; /* Core waits for quiesc state. */ + bool beenonline; /* CPU online at least once. */ + struct rcu_node *mynode; /* This CPU's leaf of hierarchy */ + unsigned long grpmask; /* Mask to apply to leaf qsmask. */ + + /* 2) batch handling */ + /* + * If nxtlist is not NULL, it is partitioned as follows. + * Any of the partitions might be empty, in which case the + * pointer to that partition will be equal to the pointer for + * the following partition. When the list is empty, all of + * the nxttail elements point to nxtlist, which is NULL. + * + * [*nxttail[RCU_NEXT_READY_TAIL], NULL = *nxttail[RCU_NEXT_TAIL]): + * Entries that might have arrived after current GP ended + * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]): + * Entries known to have arrived before current GP ended + * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]): + * Entries that batch # <= ->completed - 1: waiting for current GP + * [nxtlist, *nxttail[RCU_DONE_TAIL]): + * Entries that batch # <= ->completed + * The grace period for these entries has completed, and + * the other grace-period-completed entries may be moved + * here temporarily in rcu_process_callbacks(). + */ + struct rcu_head *nxtlist; + struct rcu_head **nxttail[RCU_NEXT_SIZE]; + long qlen; /* # of queued callbacks */ + long blimit; /* Upper limit on a processed batch */ + +#ifdef CONFIG_NO_HZ + /* 3) dynticks interface. */ + struct rcu_dynticks *dynticks; /* Shared per-CPU dynticks state. */ + int dynticks_snap; /* Per-GP tracking for dynticks. */ + int dynticks_nmi_snap; /* Per-GP tracking for dynticks_nmi. */ +#endif /* #ifdef CONFIG_NO_HZ */ + + /* 4) reasons this CPU needed to be kicked by force_quiescent_state */ +#ifdef CONFIG_NO_HZ + unsigned long dynticks_fqs; /* Kicked due to dynticks idle. */ +#endif /* #ifdef CONFIG_NO_HZ */ + unsigned long offline_fqs; /* Kicked due to being offline. */ + unsigned long resched_ipi; /* Sent a resched IPI. */ + + /* 5) state to allow this CPU to force_quiescent_state on others */ + long n_rcu_pending; /* rcu_pending() calls since boot. */ + long n_rcu_pending_force_qs; /* when to force quiescent states. */ + + int cpu; +}; + +/* Values for signaled field in struct rcu_state. */ +#define RCU_GP_INIT 0 /* Grace period being initialized. */ +#define RCU_SAVE_DYNTICK 1 /* Need to scan dyntick state. */ +#define RCU_FORCE_QS 2 /* Need to force quiescent state. */ +#ifdef CONFIG_NO_HZ +#define RCU_SIGNAL_INIT RCU_SAVE_DYNTICK +#else /* #ifdef CONFIG_NO_HZ */ +#define RCU_SIGNAL_INIT RCU_FORCE_QS +#endif /* #else #ifdef CONFIG_NO_HZ */ + +#define RCU_JIFFIES_TILL_FORCE_QS 3 /* for rsp->jiffies_force_qs */ +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR +#define RCU_SECONDS_TILL_STALL_CHECK (10 * HZ) /* for rsp->jiffies_stall */ +#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ) /* for rsp->jiffies_stall */ +#define RCU_STALL_RAT_DELAY 2 /* Allow other CPUs time */ + /* to take at least one */ + /* scheduling clock irq */ + /* before ratting on them. */ + +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + +/* + * RCU global state, including node hierarchy. This hierarchy is + * represented in "heap" form in a dense array. The root (first level) + * of the hierarchy is in ->node[0] (referenced by ->level[0]), the second + * level in ->node[1] through ->node[m] (->node[1] referenced by ->level[1]), + * and the third level in ->node[m+1] and following (->node[m+1] referenced + * by ->level[2]). The number of levels is determined by the number of + * CPUs and by CONFIG_RCU_FANOUT. Small systems will have a "hierarchy" + * consisting of a single rcu_node. + */ +struct rcu_state { + struct rcu_node node[NUM_RCU_NODES]; /* Hierarchy. */ + struct rcu_node *level[NUM_RCU_LVLS]; /* Hierarchy levels. */ + u32 levelcnt[MAX_RCU_LVLS + 1]; /* # nodes in each level. */ + u8 levelspread[NUM_RCU_LVLS]; /* kids/node in each level. */ + struct rcu_data *rda[NR_CPUS]; /* array of rdp pointers. */ + + /* The following fields are guarded by the root rcu_node's lock. */ + + u8 signaled ____cacheline_internodealigned_in_smp; + /* Force QS state. */ + long gpnum; /* Current gp number. */ + long completed; /* # of last completed gp. */ + spinlock_t onofflock; /* exclude on/offline and */ + /* starting new GP. */ + spinlock_t fqslock; /* Only one task forcing */ + /* quiescent states. */ + unsigned long jiffies_force_qs; /* Time at which to invoke */ + /* force_quiescent_state(). */ + unsigned long n_force_qs; /* Number of calls to */ + /* force_quiescent_state(). */ + unsigned long n_force_qs_lh; /* ~Number of calls leaving */ + /* due to lock unavailable. */ + unsigned long n_force_qs_ngp; /* Number of calls leaving */ + /* due to no GP active. */ +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + unsigned long gp_start; /* Time at which GP started, */ + /* but in jiffies. */ + unsigned long jiffies_stall; /* Time at which to check */ + /* for CPU stalls. */ +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ +#ifdef CONFIG_NO_HZ + long dynticks_completed; /* Value of completed @ snap. */ +#endif /* #ifdef CONFIG_NO_HZ */ +}; + +extern struct rcu_state rcu_state; +DECLARE_PER_CPU(struct rcu_data, rcu_data); + +extern struct rcu_state rcu_bh_state; +DECLARE_PER_CPU(struct rcu_data, rcu_bh_data); + +/* + * Increment the quiescent state counter. + * The counter is a bit degenerated: We do not need to know + * how many quiescent states passed, just if there was at least + * one since the start of the grace period. Thus just a flag. + */ +static inline void rcu_qsctr_inc(int cpu) +{ + struct rcu_data *rdp = &per_cpu(rcu_data, cpu); + rdp->passed_quiesc = 1; + rdp->passed_quiesc_completed = rdp->completed; +} +static inline void rcu_bh_qsctr_inc(int cpu) +{ + struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); + rdp->passed_quiesc = 1; + rdp->passed_quiesc_completed = rdp->completed; +} + +extern int rcu_pending(int cpu); +extern int rcu_needs_cpu(int cpu); + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +extern struct lockdep_map rcu_lock_map; +# define rcu_read_acquire() \ + lock_acquire(&rcu_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_) +# define rcu_read_release() lock_release(&rcu_lock_map, 1, _THIS_IP_) +#else +# define rcu_read_acquire() do { } while (0) +# define rcu_read_release() do { } while (0) +#endif + +static inline void __rcu_read_lock(void) +{ + preempt_disable(); + __acquire(RCU); + rcu_read_acquire(); +} +static inline void __rcu_read_unlock(void) +{ + rcu_read_release(); + __release(RCU); + preempt_enable(); +} +static inline void __rcu_read_lock_bh(void) +{ + local_bh_disable(); + __acquire(RCU_BH); + rcu_read_acquire(); +} +static inline void __rcu_read_unlock_bh(void) +{ + rcu_read_release(); + __release(RCU_BH); + local_bh_enable(); +} + +#define __synchronize_sched() synchronize_rcu() + +#define call_rcu_sched(head, func) call_rcu(head, func) + +static inline void rcu_init_sched(void) +{ +} + +extern void __rcu_init(void); +extern void rcu_check_callbacks(int cpu, int user); +extern void rcu_restart_cpu(int cpu); + +extern long rcu_batches_completed(void); +extern long rcu_batches_completed_bh(void); + +#ifdef CONFIG_NO_HZ +void rcu_enter_nohz(void); +void rcu_exit_nohz(void); +#else /* CONFIG_NO_HZ */ +static inline void rcu_enter_nohz(void) +{ +} +static inline void rcu_exit_nohz(void) +{ +} +#endif /* CONFIG_NO_HZ */ + +#endif /* __LINUX_RCUTREE_H */ diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index d363467c8f13..b3b359660082 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -118,6 +118,8 @@ void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu); unsigned long ring_buffer_entries(struct ring_buffer *buffer); unsigned long ring_buffer_overruns(struct ring_buffer *buffer); +unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu); +unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu); u64 ring_buffer_time_stamp(int cpu); void ring_buffer_normalize_time_stamp(int cpu, u64 *ts); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 4e4f1277f3bf..feb3b939ec4b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -158,6 +158,8 @@ /* SH-SCI */ #define PORT_SCIFA 83 +#define PORT_S3C6400 84 + #ifdef __KERNEL__ #include <linux/compiler.h> diff --git a/include/linux/slab.h b/include/linux/slab.h index 000da12b5cf0..f96d13c281e8 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -253,9 +253,9 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, * request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) -extern void *__kmalloc_track_caller(size_t, gfp_t, void*); +extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); #define kmalloc_track_caller(size, flags) \ - __kmalloc_track_caller(size, flags, __builtin_return_address(0)) + __kmalloc_track_caller(size, flags, _RET_IP_) #else #define kmalloc_track_caller(size, flags) \ __kmalloc(size, flags) @@ -271,10 +271,10 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, void*); * allocation request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) -extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *); +extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); #define kmalloc_node_track_caller(size, flags, node) \ __kmalloc_node_track_caller(size, flags, node, \ - __builtin_return_address(0)) + _RET_IP_) #else #define kmalloc_node_track_caller(size, flags, node) \ __kmalloc_node(size, flags, node) @@ -285,7 +285,7 @@ extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *); #define kmalloc_node_track_caller(size, flags, node) \ kmalloc_track_caller(size, flags) -#endif /* DEBUG_SLAB */ +#endif /* CONFIG_NUMA */ /* * Shortcuts diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index b18ec5533e8c..325af1de0351 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -7,9 +7,31 @@ struct device; struct dma_attrs; struct scatterlist; +/* + * Maximum allowable number of contiguous slabs to map, + * must be a power of 2. What is the appropriate value ? + * The complexity of {map,unmap}_single is linearly dependent on this value. + */ +#define IO_TLB_SEGSIZE 128 + + +/* + * log of the size of each IO TLB slab. The number of slabs is command line + * controllable. + */ +#define IO_TLB_SHIFT 11 + extern void swiotlb_init(void); +extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs); +extern void *swiotlb_alloc(unsigned order, unsigned long nslabs); + +extern dma_addr_t swiotlb_phys_to_bus(phys_addr_t address); +extern phys_addr_t swiotlb_bus_to_phys(dma_addr_t address); + +extern int swiotlb_arch_range_needs_mapping(void *ptr, size_t size); + extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flags); diff --git a/include/linux/timex.h b/include/linux/timex.h index 9007313b5b71..998a55d80acf 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -53,47 +53,11 @@ #ifndef _LINUX_TIMEX_H #define _LINUX_TIMEX_H -#include <linux/compiler.h> #include <linux/time.h> -#include <asm/param.h> - #define NTP_API 4 /* NTP API version */ /* - * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen - * for a slightly underdamped convergence characteristic. SHIFT_KH - * establishes the damping of the FLL and is chosen by wisdom and black - * art. - * - * MAXTC establishes the maximum time constant of the PLL. With the - * SHIFT_KG and SHIFT_KF values given and a time constant range from - * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours, - * respectively. - */ -#define SHIFT_PLL 4 /* PLL frequency factor (shift) */ -#define SHIFT_FLL 2 /* FLL frequency factor (shift) */ -#define MAXTC 10 /* maximum time constant (shift) */ - -/* - * SHIFT_USEC defines the scaling (shift) of the time_freq and - * time_tolerance variables, which represent the current frequency - * offset and maximum frequency tolerance. - */ -#define SHIFT_USEC 16 /* frequency offset scale (shift) */ -#define PPM_SCALE (NSEC_PER_USEC << (NTP_SCALE_SHIFT - SHIFT_USEC)) -#define PPM_SCALE_INV_SHIFT 19 -#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \ - PPM_SCALE + 1) - -#define MAXPHASE 500000000l /* max phase error (ns) */ -#define MAXFREQ 500000 /* max frequency error (ns/s) */ -#define MAXFREQ_SCALED ((s64)MAXFREQ << NTP_SCALE_SHIFT) -#define MINSEC 256 /* min interval between updates (s) */ -#define MAXSEC 2048 /* max interval between updates (s) */ -#define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */ - -/* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator */ @@ -199,9 +163,46 @@ struct timex { #define TIME_BAD TIME_ERROR /* bw compat */ #ifdef __KERNEL__ +#include <linux/compiler.h> +#include <linux/types.h> +#include <linux/param.h> + #include <asm/timex.h> /* + * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen + * for a slightly underdamped convergence characteristic. SHIFT_KH + * establishes the damping of the FLL and is chosen by wisdom and black + * art. + * + * MAXTC establishes the maximum time constant of the PLL. With the + * SHIFT_KG and SHIFT_KF values given and a time constant range from + * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours, + * respectively. + */ +#define SHIFT_PLL 4 /* PLL frequency factor (shift) */ +#define SHIFT_FLL 2 /* FLL frequency factor (shift) */ +#define MAXTC 10 /* maximum time constant (shift) */ + +/* + * SHIFT_USEC defines the scaling (shift) of the time_freq and + * time_tolerance variables, which represent the current frequency + * offset and maximum frequency tolerance. + */ +#define SHIFT_USEC 16 /* frequency offset scale (shift) */ +#define PPM_SCALE (NSEC_PER_USEC << (NTP_SCALE_SHIFT - SHIFT_USEC)) +#define PPM_SCALE_INV_SHIFT 19 +#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \ + PPM_SCALE + 1) + +#define MAXPHASE 500000000l /* max phase error (ns) */ +#define MAXFREQ 500000 /* max frequency error (ns/s) */ +#define MAXFREQ_SCALED ((s64)MAXFREQ << NTP_SCALE_SHIFT) +#define MINSEC 256 /* min interval between updates (s) */ +#define MAXSEC 2048 /* max interval between updates (s) */ +#define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */ + +/* * kernel variables * Note: maximum error = NTP synch distance = dispersion + delay / 2; * estimated error = NTP dispersion. diff --git a/include/linux/types.h b/include/linux/types.h index 1d98330b1f2c..121f349cb7ec 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -135,19 +135,14 @@ typedef __s64 int64_t; * * Linux always considers sectors to be 512 bytes long independently * of the devices real block size. + * + * blkcnt_t is the type of the inode's block count. */ #ifdef CONFIG_LBD typedef u64 sector_t; -#else -typedef unsigned long sector_t; -#endif - -/* - * The type of the inode's block count. - */ -#ifdef CONFIG_LSF typedef u64 blkcnt_t; #else +typedef unsigned long sector_t; typedef unsigned long blkcnt_t; #endif diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index fec6decfb983..6b58367d145e 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -78,7 +78,7 @@ static inline unsigned long __copy_from_user_nocache(void *to, \ set_fs(KERNEL_DS); \ pagefault_disable(); \ - ret = __get_user(retval, (__force typeof(retval) __user *)(addr)); \ + ret = __copy_from_user_inatomic(&(retval), (__force typeof(retval) __user *)(addr), sizeof(retval)); \ pagefault_enable(); \ set_fs(old_fs); \ ret; \ diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h index c30c7bfbf39b..8726ff77763e 100644 --- a/include/linux/virtio_balloon.h +++ b/include/linux/virtio_balloon.h @@ -10,6 +10,9 @@ /* The feature bitmap for virtio balloon */ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ +/* Size of a PFN in the balloon interface. */ +#define VIRTIO_BALLOON_PFN_SHIFT 12 + struct virtio_balloon_config { /* Number of pages host wants Guest to give up. */ diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 19a0da0dba41..7615ffcdd555 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -7,6 +7,17 @@ /* The ID for virtio console */ #define VIRTIO_ID_CONSOLE 3 +/* Feature bits */ +#define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ + +struct virtio_console_config { + /* colums of the screens */ + __u16 cols; + /* rows of the screens */ + __u16 rows; +} __attribute__((packed)); + + #ifdef __KERNEL__ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); #endif /* __KERNEL__ */ diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h index cdef35742932..cd0fd5d181a6 100644 --- a/include/linux/virtio_pci.h +++ b/include/linux/virtio_pci.h @@ -53,4 +53,12 @@ /* Virtio ABI version, this must match exactly */ #define VIRTIO_PCI_ABI_VERSION 0 + +/* How many bits to shift physical queue address written to QUEUE_PFN. + * 12 is historical, and due to x86 page size. */ +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 + +/* The alignment to use between consumer and producer parts of vring. + * x86 pagesize again. */ +#define VIRTIO_PCI_VRING_ALIGN 4096 #endif diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index c4a598fb3826..71e03722fb59 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -83,7 +83,7 @@ struct vring { * __u16 avail_idx; * __u16 available[num]; * - * // Padding to the next page boundary. + * // Padding to the next align boundary. * char pad[]; * * // A ring of used descriptor heads with free-running index. @@ -93,19 +93,19 @@ struct vring { * }; */ static inline void vring_init(struct vring *vr, unsigned int num, void *p, - unsigned long pagesize) + unsigned long align) { vr->num = num; vr->desc = p; vr->avail = p + num*sizeof(struct vring_desc); - vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1) - & ~(pagesize - 1)); + vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1) + & ~(align - 1)); } -static inline unsigned vring_size(unsigned int num, unsigned long pagesize) +static inline unsigned vring_size(unsigned int num, unsigned long align) { return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num) - + pagesize - 1) & ~(pagesize - 1)) + + align - 1) & ~(align - 1)) + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num; } @@ -115,6 +115,7 @@ struct virtio_device; struct virtqueue; struct virtqueue *vring_new_virtqueue(unsigned int num, + unsigned int vring_align, struct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *vq), diff --git a/init/Kconfig b/init/Kconfig index 8a63c404ef44..13627191a60d 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -936,10 +936,90 @@ source "block/Kconfig" config PREEMPT_NOTIFIERS bool +choice + prompt "RCU Implementation" + default CLASSIC_RCU + config CLASSIC_RCU - def_bool !PREEMPT_RCU + bool "Classic RCU" help This option selects the classic RCU implementation that is designed for best read-side performance on non-realtime - systems. Classic RCU is the default. Note that the - PREEMPT_RCU symbol is used to select/deselect this option. + systems. + + Select this option if you are unsure. + +config TREE_RCU + bool "Tree-based hierarchical RCU" + help + This option selects the RCU implementation that is + designed for very large SMP system with hundreds or + thousands of CPUs. + +config PREEMPT_RCU + bool "Preemptible RCU" + depends on PREEMPT + help + This option reduces the latency of the kernel by making certain + RCU sections preemptible. Normally RCU code is non-preemptible, if + this option is selected then read-only RCU sections become + preemptible. This helps latency, but may expose bugs due to + now-naive assumptions about each RCU read-side critical section + remaining on a given CPU through its execution. + +endchoice + +config RCU_TRACE + bool "Enable tracing for RCU" + depends on TREE_RCU || PREEMPT_RCU + help + This option provides tracing in RCU which presents stats + in debugfs for debugging RCU implementation. + + Say Y here if you want to enable RCU tracing + Say N if you are unsure. + +config RCU_FANOUT + int "Tree-based hierarchical RCU fanout value" + range 2 64 if 64BIT + range 2 32 if !64BIT + depends on TREE_RCU + default 64 if 64BIT + default 32 if !64BIT + help + This option controls the fanout of hierarchical implementations + of RCU, allowing RCU to work efficiently on machines with + large numbers of CPUs. This value must be at least the cube + root of NR_CPUS, which allows NR_CPUS up to 32,768 for 32-bit + systems and up to 262,144 for 64-bit systems. + + Select a specific number if testing RCU itself. + Take the default if unsure. + +config RCU_FANOUT_EXACT + bool "Disable tree-based hierarchical RCU auto-balancing" + depends on TREE_RCU + default n + help + This option forces use of the exact RCU_FANOUT value specified, + regardless of imbalances in the hierarchy. This is useful for + testing RCU itself, and might one day be useful on systems with + strong NUMA behavior. + + Without RCU_FANOUT_EXACT, the code will balance the hierarchy. + + Say N if unsure. + +config TREE_RCU_TRACE + def_bool RCU_TRACE && TREE_RCU + select DEBUG_FS + help + This option provides tracing for the TREE_RCU implementation, + permitting Makefile to trivially select kernel/rcutree_trace.c. + +config PREEMPT_RCU_TRACE + def_bool RCU_TRACE && PREEMPT_RCU + select DEBUG_FS + help + This option provides tracing for the PREEMPT_RCU implementation, + permitting Makefile to trivially select kernel/rcupreempt_trace.c. diff --git a/init/main.c b/init/main.c index 17e9757bfde2..2a7ce0f8e453 100644 --- a/init/main.c +++ b/init/main.c @@ -540,6 +540,15 @@ void __init __weak thread_info_cache_init(void) { } +void __init __weak arch_early_irq_init(void) +{ +} + +void __init __weak early_irq_init(void) +{ + arch_early_irq_init(); +} + asmlinkage void __init start_kernel(void) { char * command_line; @@ -604,6 +613,8 @@ asmlinkage void __init start_kernel(void) sort_main_extable(); trap_init(); rcu_init(); + /* init some links before init_ISA_irqs() */ + early_irq_init(); init_IRQ(); pidhash_init(); init_timers(); diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt index 9fdba03dc1fc..bf987b95b356 100644 --- a/kernel/Kconfig.preempt +++ b/kernel/Kconfig.preempt @@ -52,28 +52,3 @@ config PREEMPT endchoice -config PREEMPT_RCU - bool "Preemptible RCU" - depends on PREEMPT - default n - help - This option reduces the latency of the kernel by making certain - RCU sections preemptible. Normally RCU code is non-preemptible, if - this option is selected then read-only RCU sections become - preemptible. This helps latency, but may expose bugs due to - now-naive assumptions about each RCU read-side critical section - remaining on a given CPU through its execution. - - Say N if you are unsure. - -config RCU_TRACE - bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU - select DEBUG_FS - default y - help - This option provides tracing in RCU which presents stats - in debugfs for debugging RCU implementation. - - Say Y here if you want to enable RCU tracing - Say N if you are unsure. diff --git a/kernel/Makefile b/kernel/Makefile index 027edda63511..e1c5bf3365c0 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -73,10 +73,10 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o +obj-$(CONFIG_TREE_RCU) += rcutree.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o -ifeq ($(CONFIG_PREEMPT_RCU),y) -obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o -endif +obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o +obj-$(CONFIG_PREEMPT_RCU_TRACE) += rcupreempt_trace.o obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.o obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o diff --git a/kernel/exit.c b/kernel/exit.c index c7422ca92038..c9e5a1c14e08 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1037,8 +1037,6 @@ NORET_TYPE void do_exit(long code) * task into the wait for ever nirwana as well. */ tsk->flags |= PF_EXITPIDONE; - if (tsk->io_context) - exit_io_context(); set_current_state(TASK_UNINTERRUPTIBLE); schedule(); } @@ -1328,10 +1326,10 @@ static int wait_task_zombie(struct task_struct *p, int options, * group, which consolidates times for all threads in the * group including the group leader. */ + thread_group_cputime(p, &cputime); spin_lock_irq(&p->parent->sighand->siglock); psig = p->parent->signal; sig = p->signal; - thread_group_cputime(p, &cputime); psig->cutime = cputime_add(psig->cutime, cputime_add(cputime.utime, diff --git a/kernel/extable.c b/kernel/extable.c index feb0317cf09a..e136ed8d82ba 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -67,3 +67,19 @@ int kernel_text_address(unsigned long addr) return 1; return module_text_address(addr) != NULL; } + +/* + * On some architectures (PPC64, IA64) function pointers + * are actually only tokens to some data that then holds the + * real function address. As a result, to find if a function + * pointer is part of the kernel text, we need to do some + * special dereferencing first. + */ +int func_ptr_is_kernel_text(void *ptr) +{ + unsigned long addr; + addr = (unsigned long) dereference_function_descriptor(ptr); + if (core_kernel_text(addr)) + return 1; + return module_text_address(addr) != NULL; +} diff --git a/kernel/fork.c b/kernel/fork.c index 6144b36cd897..43cbf30669e6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -415,8 +415,8 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) set_mm_counter(mm, file_rss, 0); set_mm_counter(mm, anon_rss, 0); spin_lock_init(&mm->page_table_lock); - rwlock_init(&mm->ioctx_list_lock); - mm->ioctx_list = NULL; + spin_lock_init(&mm->ioctx_lock); + INIT_HLIST_HEAD(&mm->ioctx_list); mm->free_area_cache = TASK_UNMAPPED_BASE; mm->cached_hole_size = ~0UL; mm_init_owner(mm, p); diff --git a/kernel/futex.c b/kernel/futex.c index 4fe790e89d0f..7c6cbabe52b3 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -92,11 +92,12 @@ struct futex_pi_state { * A futex_q has a woken state, just like tasks have TASK_RUNNING. * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0. * The order of wakup is always to make the first condition true, then - * wake up q->waiters, then make the second condition true. + * wake up q->waiter, then make the second condition true. */ struct futex_q { struct plist_node list; - wait_queue_head_t waiters; + /* There can only be a single waiter */ + wait_queue_head_t waiter; /* Which hash list lock to use: */ spinlock_t *lock_ptr; @@ -123,24 +124,6 @@ struct futex_hash_bucket { static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS]; /* - * Take mm->mmap_sem, when futex is shared - */ -static inline void futex_lock_mm(struct rw_semaphore *fshared) -{ - if (fshared) - down_read(fshared); -} - -/* - * Release mm->mmap_sem, when the futex is shared - */ -static inline void futex_unlock_mm(struct rw_semaphore *fshared) -{ - if (fshared) - up_read(fshared); -} - -/* * We hash on the keys returned from get_futex_key (see below). */ static struct futex_hash_bucket *hash_futex(union futex_key *key) @@ -161,6 +144,45 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2) && key1->both.offset == key2->both.offset); } +/* + * Take a reference to the resource addressed by a key. + * Can be called while holding spinlocks. + * + */ +static void get_futex_key_refs(union futex_key *key) +{ + if (!key->both.ptr) + return; + + switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { + case FUT_OFF_INODE: + atomic_inc(&key->shared.inode->i_count); + break; + case FUT_OFF_MMSHARED: + atomic_inc(&key->private.mm->mm_count); + break; + } +} + +/* + * Drop a reference to the resource addressed by a key. + * The hash bucket spinlock must not be held. + */ +static void drop_futex_key_refs(union futex_key *key) +{ + if (!key->both.ptr) + return; + + switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { + case FUT_OFF_INODE: + iput(key->shared.inode); + break; + case FUT_OFF_MMSHARED: + mmdrop(key->private.mm); + break; + } +} + /** * get_futex_key - Get parameters which are the keys for a futex. * @uaddr: virtual address of the futex @@ -179,12 +201,10 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2) * For other futexes, it points to ¤t->mm->mmap_sem and * caller must have taken the reader lock. but NOT any spinlocks. */ -static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared, - union futex_key *key) +static int get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key) { unsigned long address = (unsigned long)uaddr; struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; struct page *page; int err; @@ -208,100 +228,50 @@ static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared, return -EFAULT; key->private.mm = mm; key->private.address = address; + get_futex_key_refs(key); return 0; } - /* - * The futex is hashed differently depending on whether - * it's in a shared or private mapping. So check vma first. - */ - vma = find_extend_vma(mm, address); - if (unlikely(!vma)) - return -EFAULT; - /* - * Permissions. - */ - if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ)) - return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES; +again: + err = get_user_pages_fast(address, 1, 0, &page); + if (err < 0) + return err; + + lock_page(page); + if (!page->mapping) { + unlock_page(page); + put_page(page); + goto again; + } /* * Private mappings are handled in a simple way. * * NOTE: When userspace waits on a MAP_SHARED mapping, even if * it's a read-only handle, it's expected that futexes attach to - * the object not the particular process. Therefore we use - * VM_MAYSHARE here, not VM_SHARED which is restricted to shared - * mappings of _writable_ handles. + * the object not the particular process. */ - if (likely(!(vma->vm_flags & VM_MAYSHARE))) { - key->both.offset |= FUT_OFF_MMSHARED; /* reference taken on mm */ + if (PageAnon(page)) { + key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */ key->private.mm = mm; key->private.address = address; - return 0; + } else { + key->both.offset |= FUT_OFF_INODE; /* inode-based key */ + key->shared.inode = page->mapping->host; + key->shared.pgoff = page->index; } - /* - * Linear file mappings are also simple. - */ - key->shared.inode = vma->vm_file->f_path.dentry->d_inode; - key->both.offset |= FUT_OFF_INODE; /* inode-based key. */ - if (likely(!(vma->vm_flags & VM_NONLINEAR))) { - key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT) - + vma->vm_pgoff); - return 0; - } + get_futex_key_refs(key); - /* - * We could walk the page table to read the non-linear - * pte, and get the page index without fetching the page - * from swap. But that's a lot of code to duplicate here - * for a rare case, so we simply fetch the page. - */ - err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL); - if (err >= 0) { - key->shared.pgoff = - page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - put_page(page); - return 0; - } - return err; -} - -/* - * Take a reference to the resource addressed by a key. - * Can be called while holding spinlocks. - * - */ -static void get_futex_key_refs(union futex_key *key) -{ - if (key->both.ptr == NULL) - return; - switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { - case FUT_OFF_INODE: - atomic_inc(&key->shared.inode->i_count); - break; - case FUT_OFF_MMSHARED: - atomic_inc(&key->private.mm->mm_count); - break; - } + unlock_page(page); + put_page(page); + return 0; } -/* - * Drop a reference to the resource addressed by a key. - * The hash bucket spinlock must not be held. - */ -static void drop_futex_key_refs(union futex_key *key) +static inline +void put_futex_key(int fshared, union futex_key *key) { - if (!key->both.ptr) - return; - switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { - case FUT_OFF_INODE: - iput(key->shared.inode); - break; - case FUT_OFF_MMSHARED: - mmdrop(key->private.mm); - break; - } + drop_futex_key_refs(key); } static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval) @@ -328,10 +298,8 @@ static int get_futex_value_locked(u32 *dest, u32 __user *from) /* * Fault handling. - * if fshared is non NULL, current->mm->mmap_sem is already held */ -static int futex_handle_fault(unsigned long address, - struct rw_semaphore *fshared, int attempt) +static int futex_handle_fault(unsigned long address, int attempt) { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; @@ -340,8 +308,7 @@ static int futex_handle_fault(unsigned long address, if (attempt > 2) return ret; - if (!fshared) - down_read(&mm->mmap_sem); + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (vma && address >= vma->vm_start && (vma->vm_flags & VM_WRITE)) { @@ -361,8 +328,7 @@ static int futex_handle_fault(unsigned long address, current->min_flt++; } } - if (!fshared) - up_read(&mm->mmap_sem); + up_read(&mm->mmap_sem); return ret; } @@ -385,6 +351,7 @@ static int refill_pi_state_cache(void) /* pi_mutex gets initialized later */ pi_state->owner = NULL; atomic_set(&pi_state->refcount, 1); + pi_state->key = FUTEX_KEY_INIT; current->pi_state_cache = pi_state; @@ -469,7 +436,7 @@ void exit_pi_state_list(struct task_struct *curr) struct list_head *next, *head = &curr->pi_state_list; struct futex_pi_state *pi_state; struct futex_hash_bucket *hb; - union futex_key key; + union futex_key key = FUTEX_KEY_INIT; if (!futex_cmpxchg_enabled) return; @@ -614,7 +581,7 @@ static void wake_futex(struct futex_q *q) * The lock in wake_up_all() is a crucial memory barrier after the * plist_del() and also before assigning to q->lock_ptr. */ - wake_up_all(&q->waiters); + wake_up(&q->waiter); /* * The waiting task can free the futex_q as soon as this is written, * without taking any locks. This must come last. @@ -726,20 +693,17 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2) * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, - int nr_wake, u32 bitset) +static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset) { struct futex_hash_bucket *hb; struct futex_q *this, *next; struct plist_head *head; - union futex_key key; + union futex_key key = FUTEX_KEY_INIT; int ret; if (!bitset) return -EINVAL; - futex_lock_mm(fshared); - ret = get_futex_key(uaddr, fshared, &key); if (unlikely(ret != 0)) goto out; @@ -767,7 +731,7 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, spin_unlock(&hb->lock); out: - futex_unlock_mm(fshared); + put_futex_key(fshared, &key); return ret; } @@ -776,19 +740,16 @@ out: * to this virtual address: */ static int -futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared, - u32 __user *uaddr2, +futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, int nr_wake, int nr_wake2, int op) { - union futex_key key1, key2; + union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT; struct futex_hash_bucket *hb1, *hb2; struct plist_head *head; struct futex_q *this, *next; int ret, op_ret, attempt = 0; retryfull: - futex_lock_mm(fshared); - ret = get_futex_key(uaddr1, fshared, &key1); if (unlikely(ret != 0)) goto out; @@ -833,18 +794,12 @@ retry: */ if (attempt++) { ret = futex_handle_fault((unsigned long)uaddr2, - fshared, attempt); + attempt); if (ret) goto out; goto retry; } - /* - * If we would have faulted, release mmap_sem, - * fault it in and start all over again. - */ - futex_unlock_mm(fshared); - ret = get_user(dummy, uaddr2); if (ret) return ret; @@ -880,7 +835,8 @@ retry: if (hb1 != hb2) spin_unlock(&hb2->lock); out: - futex_unlock_mm(fshared); + put_futex_key(fshared, &key2); + put_futex_key(fshared, &key1); return ret; } @@ -889,19 +845,16 @@ out: * Requeue all waiters hashed on one physical page to another * physical page. */ -static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared, - u32 __user *uaddr2, +static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, int nr_wake, int nr_requeue, u32 *cmpval) { - union futex_key key1, key2; + union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT; struct futex_hash_bucket *hb1, *hb2; struct plist_head *head1; struct futex_q *this, *next; int ret, drop_count = 0; retry: - futex_lock_mm(fshared); - ret = get_futex_key(uaddr1, fshared, &key1); if (unlikely(ret != 0)) goto out; @@ -924,12 +877,6 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared, if (hb1 != hb2) spin_unlock(&hb2->lock); - /* - * If we would have faulted, release mmap_sem, fault - * it in and start all over again. - */ - futex_unlock_mm(fshared); - ret = get_user(curval, uaddr1); if (!ret) @@ -981,7 +928,8 @@ out_unlock: drop_futex_key_refs(&key1); out: - futex_unlock_mm(fshared); + put_futex_key(fshared, &key2); + put_futex_key(fshared, &key1); return ret; } @@ -990,7 +938,7 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q) { struct futex_hash_bucket *hb; - init_waitqueue_head(&q->waiters); + init_waitqueue_head(&q->waiter); get_futex_key_refs(&q->key); hb = hash_futex(&q->key); @@ -1103,8 +1051,7 @@ static void unqueue_me_pi(struct futex_q *q) * private futexes. */ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, - struct task_struct *newowner, - struct rw_semaphore *fshared) + struct task_struct *newowner, int fshared) { u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS; struct futex_pi_state *pi_state = q->pi_state; @@ -1183,7 +1130,7 @@ retry: handle_fault: spin_unlock(q->lock_ptr); - ret = futex_handle_fault((unsigned long)uaddr, fshared, attempt++); + ret = futex_handle_fault((unsigned long)uaddr, attempt++); spin_lock(q->lock_ptr); @@ -1203,12 +1150,13 @@ handle_fault: * In case we must use restart_block to restart a futex_wait, * we encode in the 'flags' shared capability */ -#define FLAGS_SHARED 1 +#define FLAGS_SHARED 0x01 +#define FLAGS_CLOCKRT 0x02 static long futex_wait_restart(struct restart_block *restart); -static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, - u32 val, ktime_t *abs_time, u32 bitset) +static int futex_wait(u32 __user *uaddr, int fshared, + u32 val, ktime_t *abs_time, u32 bitset, int clockrt) { struct task_struct *curr = current; DECLARE_WAITQUEUE(wait, curr); @@ -1225,8 +1173,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, q.pi_state = NULL; q.bitset = bitset; retry: - futex_lock_mm(fshared); - + q.key = FUTEX_KEY_INIT; ret = get_futex_key(uaddr, fshared, &q.key); if (unlikely(ret != 0)) goto out_release_sem; @@ -1258,12 +1205,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, if (unlikely(ret)) { queue_unlock(&q, hb); - /* - * If we would have faulted, release mmap_sem, fault it in and - * start all over again. - */ - futex_unlock_mm(fshared); - ret = get_user(uval, uaddr); if (!ret) @@ -1278,12 +1219,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, queue_me(&q, hb); /* - * Now the futex is queued and we have checked the data, we - * don't want to hold mmap_sem while we sleep. - */ - futex_unlock_mm(fshared); - - /* * There might have been scheduling since the queue_me(), as we * cannot hold a spinlock across the get_user() in case it * faults, and we cannot just set TASK_INTERRUPTIBLE state when @@ -1294,7 +1229,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, /* add_wait_queue is the barrier after __set_current_state. */ __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&q.waiters, &wait); + add_wait_queue(&q.waiter, &wait); /* * !plist_node_empty() is safe here without any lock. * q.lock_ptr != 0 is not safe, because of ordering against wakeup. @@ -1307,8 +1242,10 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, slack = current->timer_slack_ns; if (rt_task(current)) slack = 0; - hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, - HRTIMER_MODE_ABS); + hrtimer_init_on_stack(&t.timer, + clockrt ? CLOCK_REALTIME : + CLOCK_MONOTONIC, + HRTIMER_MODE_ABS); hrtimer_init_sleeper(&t, current); hrtimer_set_expires_range_ns(&t.timer, *abs_time, slack); @@ -1363,6 +1300,8 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, if (fshared) restart->futex.flags |= FLAGS_SHARED; + if (clockrt) + restart->futex.flags |= FLAGS_CLOCKRT; return -ERESTART_RESTARTBLOCK; } @@ -1370,7 +1309,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, queue_unlock(&q, hb); out_release_sem: - futex_unlock_mm(fshared); + put_futex_key(fshared, &q.key); return ret; } @@ -1378,15 +1317,16 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, static long futex_wait_restart(struct restart_block *restart) { u32 __user *uaddr = (u32 __user *)restart->futex.uaddr; - struct rw_semaphore *fshared = NULL; + int fshared = 0; ktime_t t; t.tv64 = restart->futex.time; restart->fn = do_no_restart_syscall; if (restart->futex.flags & FLAGS_SHARED) - fshared = ¤t->mm->mmap_sem; + fshared = 1; return (long)futex_wait(uaddr, fshared, restart->futex.val, &t, - restart->futex.bitset); + restart->futex.bitset, + restart->futex.flags & FLAGS_CLOCKRT); } @@ -1396,7 +1336,7 @@ static long futex_wait_restart(struct restart_block *restart) * if there are waiters then it will block, it does PI, etc. (Due to * races the kernel might see a 0 value of the futex too.) */ -static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, +static int futex_lock_pi(u32 __user *uaddr, int fshared, int detect, ktime_t *time, int trylock) { struct hrtimer_sleeper timeout, *to = NULL; @@ -1419,8 +1359,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, q.pi_state = NULL; retry: - futex_lock_mm(fshared); - + q.key = FUTEX_KEY_INIT; ret = get_futex_key(uaddr, fshared, &q.key); if (unlikely(ret != 0)) goto out_release_sem; @@ -1509,7 +1448,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, * exit to complete. */ queue_unlock(&q, hb); - futex_unlock_mm(fshared); cond_resched(); goto retry; @@ -1541,12 +1479,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, */ queue_me(&q, hb); - /* - * Now the futex is queued and we have checked the data, we - * don't want to hold mmap_sem while we sleep. - */ - futex_unlock_mm(fshared); - WARN_ON(!q.pi_state); /* * Block on the PI mutex: @@ -1559,7 +1491,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, ret = ret ? 0 : -EWOULDBLOCK; } - futex_lock_mm(fshared); spin_lock(q.lock_ptr); if (!ret) { @@ -1625,7 +1556,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, /* Unqueue and drop the lock */ unqueue_me_pi(&q); - futex_unlock_mm(fshared); if (to) destroy_hrtimer_on_stack(&to->timer); @@ -1635,34 +1565,30 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, queue_unlock(&q, hb); out_release_sem: - futex_unlock_mm(fshared); + put_futex_key(fshared, &q.key); if (to) destroy_hrtimer_on_stack(&to->timer); return ret; uaddr_faulted: /* - * We have to r/w *(int __user *)uaddr, but we can't modify it - * non-atomically. Therefore, if get_user below is not - * enough, we need to handle the fault ourselves, while - * still holding the mmap_sem. - * - * ... and hb->lock. :-) --ANK + * We have to r/w *(int __user *)uaddr, and we have to modify it + * atomically. Therefore, if we continue to fault after get_user() + * below, we need to handle the fault ourselves, while still holding + * the mmap_sem. This can occur if the uaddr is under contention as + * we have to drop the mmap_sem in order to call get_user(). */ queue_unlock(&q, hb); if (attempt++) { - ret = futex_handle_fault((unsigned long)uaddr, fshared, - attempt); + ret = futex_handle_fault((unsigned long)uaddr, attempt); if (ret) goto out_release_sem; goto retry_unlocked; } - futex_unlock_mm(fshared); - ret = get_user(uval, uaddr); - if (!ret && (uval != -EFAULT)) + if (!ret) goto retry; if (to) @@ -1675,13 +1601,13 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, * This is the in-kernel slowpath: we look up the PI state (if any), * and do the rt-mutex unlock. */ -static int futex_unlock_pi(u32 __user *uaddr, struct rw_semaphore *fshared) +static int futex_unlock_pi(u32 __user *uaddr, int fshared) { struct futex_hash_bucket *hb; struct futex_q *this, *next; u32 uval; struct plist_head *head; - union futex_key key; + union futex_key key = FUTEX_KEY_INIT; int ret, attempt = 0; retry: @@ -1692,10 +1618,6 @@ retry: */ if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) return -EPERM; - /* - * First take all the futex related locks: - */ - futex_lock_mm(fshared); ret = get_futex_key(uaddr, fshared, &key); if (unlikely(ret != 0)) @@ -1754,34 +1676,30 @@ retry_unlocked: out_unlock: spin_unlock(&hb->lock); out: - futex_unlock_mm(fshared); + put_futex_key(fshared, &key); return ret; pi_faulted: /* - * We have to r/w *(int __user *)uaddr, but we can't modify it - * non-atomically. Therefore, if get_user below is not - * enough, we need to handle the fault ourselves, while - * still holding the mmap_sem. - * - * ... and hb->lock. --ANK + * We have to r/w *(int __user *)uaddr, and we have to modify it + * atomically. Therefore, if we continue to fault after get_user() + * below, we need to handle the fault ourselves, while still holding + * the mmap_sem. This can occur if the uaddr is under contention as + * we have to drop the mmap_sem in order to call get_user(). */ spin_unlock(&hb->lock); if (attempt++) { - ret = futex_handle_fault((unsigned long)uaddr, fshared, - attempt); + ret = futex_handle_fault((unsigned long)uaddr, attempt); if (ret) goto out; uval = 0; goto retry_unlocked; } - futex_unlock_mm(fshared); - ret = get_user(uval, uaddr); - if (!ret && (uval != -EFAULT)) + if (!ret) goto retry; return ret; @@ -1908,8 +1826,7 @@ retry: * PI futexes happens in exit_pi_state(): */ if (!pi && (uval & FUTEX_WAITERS)) - futex_wake(uaddr, &curr->mm->mmap_sem, 1, - FUTEX_BITSET_MATCH_ANY); + futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); } return 0; } @@ -2003,18 +1920,22 @@ void exit_robust_list(struct task_struct *curr) long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, u32 __user *uaddr2, u32 val2, u32 val3) { - int ret = -ENOSYS; + int clockrt, ret = -ENOSYS; int cmd = op & FUTEX_CMD_MASK; - struct rw_semaphore *fshared = NULL; + int fshared = 0; if (!(op & FUTEX_PRIVATE_FLAG)) - fshared = ¤t->mm->mmap_sem; + fshared = 1; + + clockrt = op & FUTEX_CLOCK_REALTIME; + if (clockrt && cmd != FUTEX_WAIT_BITSET) + return -ENOSYS; switch (cmd) { case FUTEX_WAIT: val3 = FUTEX_BITSET_MATCH_ANY; case FUTEX_WAIT_BITSET: - ret = futex_wait(uaddr, fshared, val, timeout, val3); + ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt); break; case FUTEX_WAKE: val3 = FUTEX_BITSET_MATCH_ANY; diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 47e63349d1b2..bda9cb924276 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -442,22 +442,6 @@ static inline void debug_hrtimer_activate(struct hrtimer *timer) { } static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { } #endif -/* - * Check, whether the timer is on the callback pending list - */ -static inline int hrtimer_cb_pending(const struct hrtimer *timer) -{ - return timer->state & HRTIMER_STATE_PENDING; -} - -/* - * Remove a timer from the callback pending list - */ -static inline void hrtimer_remove_cb_pending(struct hrtimer *timer) -{ - list_del_init(&timer->cb_entry); -} - /* High resolution timer related functions */ #ifdef CONFIG_HIGH_RES_TIMERS @@ -651,6 +635,8 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { } +static void __run_hrtimer(struct hrtimer *timer); + /* * When High resolution timers are active, try to reprogram. Note, that in case * the state has HRTIMER_STATE_CALLBACK set, no reprogramming and no expiry @@ -661,31 +647,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { - - /* Timer is expired, act upon the callback mode */ - switch(timer->cb_mode) { - case HRTIMER_CB_IRQSAFE_PERCPU: - case HRTIMER_CB_IRQSAFE_UNLOCKED: - /* - * This is solely for the sched tick emulation with - * dynamic tick support to ensure that we do not - * restart the tick right on the edge and end up with - * the tick timer in the softirq ! The calling site - * takes care of this. Also used for hrtimer sleeper ! - */ - debug_hrtimer_deactivate(timer); - return 1; - case HRTIMER_CB_SOFTIRQ: - /* - * Move everything else into the softirq pending list ! - */ - list_add_tail(&timer->cb_entry, - &base->cpu_base->cb_pending); - timer->state = HRTIMER_STATE_PENDING; - return 1; - default: - BUG(); - } + /* + * XXX: recursion check? + * hrtimer_forward() should round up with timer granularity + * so that we never get into inf recursion here, + * it doesn't do that though + */ + __run_hrtimer(timer); + return 1; } return 0; } @@ -724,11 +693,6 @@ static int hrtimer_switch_to_hres(void) return 1; } -static inline void hrtimer_raise_softirq(void) -{ - raise_softirq(HRTIMER_SOFTIRQ); -} - #else static inline int hrtimer_hres_active(void) { return 0; } @@ -747,7 +711,6 @@ static inline int hrtimer_reprogram(struct hrtimer *timer, { return 0; } -static inline void hrtimer_raise_softirq(void) { } #endif /* CONFIG_HIGH_RES_TIMERS */ @@ -890,10 +853,7 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, unsigned long newstate, int reprogram) { - /* High res. callback list. NOP for !HIGHRES */ - if (hrtimer_cb_pending(timer)) - hrtimer_remove_cb_pending(timer); - else { + if (timer->state & HRTIMER_STATE_ENQUEUED) { /* * Remove the timer from the rbtree and replace the * first entry pointer if necessary. @@ -953,7 +913,7 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n { struct hrtimer_clock_base *base, *new_base; unsigned long flags; - int ret, raise; + int ret; base = lock_hrtimer_base(timer, &flags); @@ -988,26 +948,8 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n enqueue_hrtimer(timer, new_base, new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); - /* - * The timer may be expired and moved to the cb_pending - * list. We can not raise the softirq with base lock held due - * to a possible deadlock with runqueue lock. - */ - raise = timer->state == HRTIMER_STATE_PENDING; - - /* - * We use preempt_disable to prevent this task from migrating after - * setting up the softirq and raising it. Otherwise, if me migrate - * we will raise the softirq on the wrong CPU. - */ - preempt_disable(); - unlock_hrtimer_base(timer, &flags); - if (raise) - hrtimer_raise_softirq(); - preempt_enable(); - return ret; } EXPORT_SYMBOL_GPL(hrtimer_start_range_ns); @@ -1192,75 +1134,6 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) } EXPORT_SYMBOL_GPL(hrtimer_get_res); -static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base) -{ - spin_lock_irq(&cpu_base->lock); - - while (!list_empty(&cpu_base->cb_pending)) { - enum hrtimer_restart (*fn)(struct hrtimer *); - struct hrtimer *timer; - int restart; - int emulate_hardirq_ctx = 0; - - timer = list_entry(cpu_base->cb_pending.next, - struct hrtimer, cb_entry); - - debug_hrtimer_deactivate(timer); - timer_stats_account_hrtimer(timer); - - fn = timer->function; - /* - * A timer might have been added to the cb_pending list - * when it was migrated during a cpu-offline operation. - * Emulate hardirq context for such timers. - */ - if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU || - timer->cb_mode == HRTIMER_CB_IRQSAFE_UNLOCKED) - emulate_hardirq_ctx = 1; - - __remove_hrtimer(timer, timer->base, HRTIMER_STATE_CALLBACK, 0); - spin_unlock_irq(&cpu_base->lock); - - if (unlikely(emulate_hardirq_ctx)) { - local_irq_disable(); - restart = fn(timer); - local_irq_enable(); - } else - restart = fn(timer); - - spin_lock_irq(&cpu_base->lock); - - timer->state &= ~HRTIMER_STATE_CALLBACK; - if (restart == HRTIMER_RESTART) { - BUG_ON(hrtimer_active(timer)); - /* - * Enqueue the timer, allow reprogramming of the event - * device - */ - enqueue_hrtimer(timer, timer->base, 1); - } else if (hrtimer_active(timer)) { - /* - * If the timer was rearmed on another CPU, reprogram - * the event device. - */ - struct hrtimer_clock_base *base = timer->base; - - if (base->first == &timer->node && - hrtimer_reprogram(timer, base)) { - /* - * Timer is expired. Thus move it from tree to - * pending list again. - */ - __remove_hrtimer(timer, base, - HRTIMER_STATE_PENDING, 0); - list_add_tail(&timer->cb_entry, - &base->cpu_base->cb_pending); - } - } - } - spin_unlock_irq(&cpu_base->lock); -} - static void __run_hrtimer(struct hrtimer *timer) { struct hrtimer_clock_base *base = timer->base; @@ -1268,25 +1141,21 @@ static void __run_hrtimer(struct hrtimer *timer) enum hrtimer_restart (*fn)(struct hrtimer *); int restart; + WARN_ON(!irqs_disabled()); + debug_hrtimer_deactivate(timer); __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0); timer_stats_account_hrtimer(timer); - fn = timer->function; - if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU || - timer->cb_mode == HRTIMER_CB_IRQSAFE_UNLOCKED) { - /* - * Used for scheduler timers, avoid lock inversion with - * rq->lock and tasklist_lock. - * - * These timers are required to deal with enqueue expiry - * themselves and are not allowed to migrate. - */ - spin_unlock(&cpu_base->lock); - restart = fn(timer); - spin_lock(&cpu_base->lock); - } else - restart = fn(timer); + + /* + * Because we run timers from hardirq context, there is no chance + * they get migrated to another cpu, therefore its safe to unlock + * the timer base. + */ + spin_unlock(&cpu_base->lock); + restart = fn(timer); + spin_lock(&cpu_base->lock); /* * Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid @@ -1311,7 +1180,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; ktime_t expires_next, now; - int i, raise = 0; + int i; BUG_ON(!cpu_base->hres_active); cpu_base->nr_events++; @@ -1360,16 +1229,6 @@ void hrtimer_interrupt(struct clock_event_device *dev) break; } - /* Move softirq callbacks to the pending list */ - if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) { - __remove_hrtimer(timer, base, - HRTIMER_STATE_PENDING, 0); - list_add_tail(&timer->cb_entry, - &base->cpu_base->cb_pending); - raise = 1; - continue; - } - __run_hrtimer(timer); } spin_unlock(&cpu_base->lock); @@ -1383,10 +1242,6 @@ void hrtimer_interrupt(struct clock_event_device *dev) if (tick_program_event(expires_next, 0)) goto retry; } - - /* Raise softirq ? */ - if (raise) - raise_softirq(HRTIMER_SOFTIRQ); } /** @@ -1413,11 +1268,6 @@ void hrtimer_peek_ahead_timers(void) local_irq_restore(flags); } -static void run_hrtimer_softirq(struct softirq_action *h) -{ - run_hrtimer_pending(&__get_cpu_var(hrtimer_bases)); -} - #endif /* CONFIG_HIGH_RES_TIMERS */ /* @@ -1429,8 +1279,6 @@ static void run_hrtimer_softirq(struct softirq_action *h) */ void hrtimer_run_pending(void) { - struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - if (hrtimer_hres_active()) return; @@ -1444,8 +1292,6 @@ void hrtimer_run_pending(void) */ if (tick_check_oneshot_change(!hrtimer_is_hres_enabled())) hrtimer_switch_to_hres(); - - run_hrtimer_pending(cpu_base); } /* @@ -1482,14 +1328,6 @@ void hrtimer_run_queues(void) hrtimer_get_expires_tv64(timer)) break; - if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) { - __remove_hrtimer(timer, base, - HRTIMER_STATE_PENDING, 0); - list_add_tail(&timer->cb_entry, - &base->cpu_base->cb_pending); - continue; - } - __run_hrtimer(timer); } spin_unlock(&cpu_base->lock); @@ -1516,9 +1354,6 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task) { sl->timer.function = hrtimer_wakeup; sl->task = task; -#ifdef CONFIG_HIGH_RES_TIMERS - sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; -#endif } static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) @@ -1655,18 +1490,16 @@ static void __cpuinit init_hrtimers_cpu(int cpu) for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) cpu_base->clock_base[i].cpu_base = cpu_base; - INIT_LIST_HEAD(&cpu_base->cb_pending); hrtimer_init_hres(cpu_base); } #ifdef CONFIG_HOTPLUG_CPU -static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base, - struct hrtimer_clock_base *new_base, int dcpu) +static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, + struct hrtimer_clock_base *new_base) { struct hrtimer *timer; struct rb_node *node; - int raise = 0; while ((node = rb_first(&old_base->active))) { timer = rb_entry(node, struct hrtimer, node); @@ -1674,18 +1507,6 @@ static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base, debug_hrtimer_deactivate(timer); /* - * Should not happen. Per CPU timers should be - * canceled _before_ the migration code is called - */ - if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU) { - __remove_hrtimer(timer, old_base, - HRTIMER_STATE_INACTIVE, 0); - WARN(1, "hrtimer (%p %p)active but cpu %d dead\n", - timer, timer->function, dcpu); - continue; - } - - /* * Mark it as STATE_MIGRATE not INACTIVE otherwise the * timer could be seen as !active and just vanish away * under us on another CPU @@ -1693,69 +1514,34 @@ static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base, __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0); timer->base = new_base; /* - * Enqueue the timer. Allow reprogramming of the event device + * Enqueue the timers on the new cpu, but do not reprogram + * the timer as that would enable a deadlock between + * hrtimer_enqueue_reprogramm() running the timer and us still + * holding a nested base lock. + * + * Instead we tickle the hrtimer interrupt after the migration + * is done, which will run all expired timers and re-programm + * the timer device. */ - enqueue_hrtimer(timer, new_base, 1); + enqueue_hrtimer(timer, new_base, 0); -#ifdef CONFIG_HIGH_RES_TIMERS - /* - * Happens with high res enabled when the timer was - * already expired and the callback mode is - * HRTIMER_CB_IRQSAFE_UNLOCKED (hrtimer_sleeper). The - * enqueue code does not move them to the soft irq - * pending list for performance/latency reasons, but - * in the migration state, we need to do that - * otherwise we end up with a stale timer. - */ - if (timer->state == HRTIMER_STATE_MIGRATE) { - timer->state = HRTIMER_STATE_PENDING; - list_add_tail(&timer->cb_entry, - &new_base->cpu_base->cb_pending); - raise = 1; - } -#endif /* Clear the migration state bit */ timer->state &= ~HRTIMER_STATE_MIGRATE; } - return raise; -} - -#ifdef CONFIG_HIGH_RES_TIMERS -static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, - struct hrtimer_cpu_base *new_base) -{ - struct hrtimer *timer; - int raise = 0; - - while (!list_empty(&old_base->cb_pending)) { - timer = list_entry(old_base->cb_pending.next, - struct hrtimer, cb_entry); - - __remove_hrtimer(timer, timer->base, HRTIMER_STATE_PENDING, 0); - timer->base = &new_base->clock_base[timer->base->index]; - list_add_tail(&timer->cb_entry, &new_base->cb_pending); - raise = 1; - } - return raise; -} -#else -static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, - struct hrtimer_cpu_base *new_base) -{ - return 0; } -#endif -static void migrate_hrtimers(int cpu) +static int migrate_hrtimers(int scpu) { struct hrtimer_cpu_base *old_base, *new_base; - int i, raise = 0; + int dcpu, i; - BUG_ON(cpu_online(cpu)); - old_base = &per_cpu(hrtimer_bases, cpu); + BUG_ON(cpu_online(scpu)); + old_base = &per_cpu(hrtimer_bases, scpu); new_base = &get_cpu_var(hrtimer_bases); - tick_cancel_sched_timer(cpu); + dcpu = smp_processor_id(); + + tick_cancel_sched_timer(scpu); /* * The caller is globally serialized and nobody else * takes two locks at once, deadlock is not possible. @@ -1764,41 +1550,47 @@ static void migrate_hrtimers(int cpu) spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { - if (migrate_hrtimer_list(&old_base->clock_base[i], - &new_base->clock_base[i], cpu)) - raise = 1; + migrate_hrtimer_list(&old_base->clock_base[i], + &new_base->clock_base[i]); } - if (migrate_hrtimer_pending(old_base, new_base)) - raise = 1; - spin_unlock(&old_base->lock); spin_unlock_irq(&new_base->lock); put_cpu_var(hrtimer_bases); - if (raise) - hrtimer_raise_softirq(); + return dcpu; +} + +static void tickle_timers(void *arg) +{ + hrtimer_peek_ahead_timers(); } + #endif /* CONFIG_HOTPLUG_CPU */ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { - unsigned int cpu = (long)hcpu; + int scpu = (long)hcpu; switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - init_hrtimers_cpu(cpu); + init_hrtimers_cpu(scpu); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: case CPU_DEAD_FROZEN: - clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &cpu); - migrate_hrtimers(cpu); + { + int dcpu; + + clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu); + dcpu = migrate_hrtimers(scpu); + smp_call_function_single(dcpu, tickle_timers, NULL, 0); break; + } #endif default: @@ -1817,9 +1609,6 @@ void __init hrtimers_init(void) hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE, (void *)(long)smp_processor_id()); register_cpu_notifier(&hrtimers_nb); -#ifdef CONFIG_HIGH_RES_TIMERS - open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq); -#endif } /** diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index 681c52dbfe22..4dd5b1edac98 100644 --- a/kernel/irq/Makefile +++ b/kernel/irq/Makefile @@ -3,3 +3,4 @@ obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o +obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index cc0f7321b8ce..650ce4102a63 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c @@ -40,6 +40,9 @@ unsigned long probe_irq_on(void) * flush such a longstanding irq before considering it as spurious. */ for_each_irq_desc_reverse(i, desc) { + if (!desc) + continue; + spin_lock_irq(&desc->lock); if (!desc->action && !(desc->status & IRQ_NOPROBE)) { /* @@ -68,6 +71,9 @@ unsigned long probe_irq_on(void) * happened in the previous stage, it may have masked itself) */ for_each_irq_desc_reverse(i, desc) { + if (!desc) + continue; + spin_lock_irq(&desc->lock); if (!desc->action && !(desc->status & IRQ_NOPROBE)) { desc->status |= IRQ_AUTODETECT | IRQ_WAITING; @@ -86,6 +92,9 @@ unsigned long probe_irq_on(void) * Now filter out any obviously spurious interrupts */ for_each_irq_desc(i, desc) { + if (!desc) + continue; + spin_lock_irq(&desc->lock); status = desc->status; @@ -124,6 +133,9 @@ unsigned int probe_irq_mask(unsigned long val) int i; for_each_irq_desc(i, desc) { + if (!desc) + continue; + spin_lock_irq(&desc->lock); status = desc->status; @@ -166,6 +178,9 @@ int probe_irq_off(unsigned long val) unsigned int status; for_each_irq_desc(i, desc) { + if (!desc) + continue; + spin_lock_irq(&desc->lock); status = desc->status; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 10b5092e9bfe..6eb3c7952b64 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -24,9 +24,10 @@ */ void dynamic_irq_init(unsigned int irq) { - struct irq_desc *desc = irq_to_desc(irq); + struct irq_desc *desc; unsigned long flags; + desc = irq_to_desc(irq); if (!desc) { WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); return; @@ -124,6 +125,7 @@ int set_irq_type(unsigned int irq, unsigned int type) return -ENODEV; } + type &= IRQ_TYPE_SENSE_MASK; if (type == IRQ_TYPE_NONE) return 0; @@ -352,6 +354,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) spin_lock(&desc->lock); mask_ack_irq(desc, irq); + desc = irq_remap_to_desc(irq, desc); if (unlikely(desc->status & IRQ_INPROGRESS)) goto out_unlock; @@ -429,6 +432,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) desc->status &= ~IRQ_INPROGRESS; out: desc->chip->eoi(irq); + desc = irq_remap_to_desc(irq, desc); spin_unlock(&desc->lock); } @@ -465,12 +469,14 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) !desc->action)) { desc->status |= (IRQ_PENDING | IRQ_MASKED); mask_ack_irq(desc, irq); + desc = irq_remap_to_desc(irq, desc); goto out_unlock; } kstat_incr_irqs_this_cpu(irq, desc); /* Start handling the irq */ desc->chip->ack(irq); + desc = irq_remap_to_desc(irq, desc); /* Mark the IRQ currently in progress.*/ desc->status |= IRQ_INPROGRESS; @@ -531,8 +537,10 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) if (!noirqdebug) note_interrupt(irq, desc, action_ret); - if (desc->chip->eoi) + if (desc->chip->eoi) { desc->chip->eoi(irq); + desc = irq_remap_to_desc(irq, desc); + } } void @@ -567,8 +575,10 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, /* Uninstall? */ if (handle == handle_bad_irq) { - if (desc->chip != &no_irq_chip) + if (desc->chip != &no_irq_chip) { mask_ack_irq(desc, irq); + desc = irq_remap_to_desc(irq, desc); + } desc->status |= IRQ_DISABLED; desc->depth = 1; } diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index c815b42d0f5b..6492400cb50d 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -15,9 +15,16 @@ #include <linux/random.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> +#include <linux/rculist.h> +#include <linux/hash.h> #include "internals.h" +/* + * lockdep: we want to handle all irq_desc locks as a single lock-class: + */ +struct lock_class_key irq_desc_lock_class; + /** * handle_bad_irq - handle spurious and unhandled irqs * @irq: the interrupt number @@ -49,6 +56,155 @@ void handle_bad_irq(unsigned int irq, struct irq_desc *desc) int nr_irqs = NR_IRQS; EXPORT_SYMBOL_GPL(nr_irqs); +void __init __attribute__((weak)) arch_early_irq_init(void) +{ +} + +#ifdef CONFIG_SPARSE_IRQ +static struct irq_desc irq_desc_init = { + .irq = -1, + .status = IRQ_DISABLED, + .chip = &no_irq_chip, + .handle_irq = handle_bad_irq, + .depth = 1, + .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), +#ifdef CONFIG_SMP + .affinity = CPU_MASK_ALL +#endif +}; + +void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) +{ + unsigned long bytes; + char *ptr; + int node; + + /* Compute how many bytes we need per irq and allocate them */ + bytes = nr * sizeof(unsigned int); + + node = cpu_to_node(cpu); + ptr = kzalloc_node(bytes, GFP_ATOMIC, node); + printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", cpu, node); + + if (ptr) + desc->kstat_irqs = (unsigned int *)ptr; +} + +void __attribute__((weak)) arch_init_chip_data(struct irq_desc *desc, int cpu) +{ +} + +static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) +{ + memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); + desc->irq = irq; +#ifdef CONFIG_SMP + desc->cpu = cpu; +#endif + lockdep_set_class(&desc->lock, &irq_desc_lock_class); + init_kstat_irqs(desc, cpu, nr_cpu_ids); + if (!desc->kstat_irqs) { + printk(KERN_ERR "can not alloc kstat_irqs\n"); + BUG_ON(1); + } + arch_init_chip_data(desc, cpu); +} + +/* + * Protect the sparse_irqs: + */ +DEFINE_SPINLOCK(sparse_irq_lock); + +struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly; + +static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { + [0 ... NR_IRQS_LEGACY-1] = { + .irq = -1, + .status = IRQ_DISABLED, + .chip = &no_irq_chip, + .handle_irq = handle_bad_irq, + .depth = 1, + .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), +#ifdef CONFIG_SMP + .affinity = CPU_MASK_ALL +#endif + } +}; + +/* FIXME: use bootmem alloc ...*/ +static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS]; + +void __init early_irq_init(void) +{ + struct irq_desc *desc; + int legacy_count; + int i; + + desc = irq_desc_legacy; + legacy_count = ARRAY_SIZE(irq_desc_legacy); + + for (i = 0; i < legacy_count; i++) { + desc[i].irq = i; + desc[i].kstat_irqs = kstat_irqs_legacy[i]; + + irq_desc_ptrs[i] = desc + i; + } + + for (i = legacy_count; i < NR_IRQS; i++) + irq_desc_ptrs[i] = NULL; + + arch_early_irq_init(); +} + +struct irq_desc *irq_to_desc(unsigned int irq) +{ + return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL; +} + +struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) +{ + struct irq_desc *desc; + unsigned long flags; + int node; + + if (irq >= NR_IRQS) { + printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n", + irq, NR_IRQS); + WARN_ON(1); + return NULL; + } + + desc = irq_desc_ptrs[irq]; + if (desc) + return desc; + + spin_lock_irqsave(&sparse_irq_lock, flags); + + /* We have to check it to avoid races with another CPU */ + desc = irq_desc_ptrs[irq]; + if (desc) + goto out_unlock; + + node = cpu_to_node(cpu); + desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); + printk(KERN_DEBUG " alloc irq_desc for %d on cpu %d node %d\n", + irq, cpu, node); + if (!desc) { + printk(KERN_ERR "can not alloc irq_desc\n"); + BUG_ON(1); + } + init_one_irq_desc(irq, desc, cpu); + + irq_desc_ptrs[irq] = desc; + +out_unlock: + spin_unlock_irqrestore(&sparse_irq_lock, flags); + + return desc; +} + +#else + struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, @@ -62,6 +218,8 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { } }; +#endif + /* * What should we do if we get a hw irq event on an illegal vector? * Each architecture has to answer this themself. @@ -179,8 +337,11 @@ unsigned int __do_IRQ(unsigned int irq) /* * No locking required for CPU-local interrupts: */ - if (desc->chip->ack) + if (desc->chip->ack) { desc->chip->ack(irq); + /* get new one */ + desc = irq_remap_to_desc(irq, desc); + } if (likely(!(desc->status & IRQ_DISABLED))) { action_ret = handle_IRQ_event(irq, desc->action); if (!noirqdebug) @@ -191,8 +352,10 @@ unsigned int __do_IRQ(unsigned int irq) } spin_lock(&desc->lock); - if (desc->chip->ack) + if (desc->chip->ack) { desc->chip->ack(irq); + desc = irq_remap_to_desc(irq, desc); + } /* * REPLAY is when Linux resends an IRQ that was dropped earlier * WAITING is used by probe to mark irqs that are being tested @@ -259,19 +422,25 @@ out: } #endif - -#ifdef CONFIG_TRACE_IRQFLAGS -/* - * lockdep: we want to handle all irq_desc locks as a single lock-class: - */ -static struct lock_class_key irq_desc_lock_class; - void early_init_irq_lock_class(void) { struct irq_desc *desc; int i; - for_each_irq_desc(i, desc) + for_each_irq_desc(i, desc) { + if (!desc) + continue; + lockdep_set_class(&desc->lock, &irq_desc_lock_class); + } +} + +#ifdef CONFIG_SPARSE_IRQ +unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) +{ + struct irq_desc *desc = irq_to_desc(irq); + return desc->kstat_irqs[cpu]; } #endif +EXPORT_SYMBOL(kstat_irqs_cpu); + diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 64c1c7253dae..e6d0a43cc125 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -13,6 +13,11 @@ extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, unsigned long flags); +extern struct lock_class_key irq_desc_lock_class; +extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); +extern spinlock_t sparse_irq_lock; +extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; + #ifdef CONFIG_PROC_FS extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); extern void register_handler_proc(unsigned int irq, struct irqaction *action); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 801addda3c43..540f6c49f3fa 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -370,16 +370,18 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, return 0; } - ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK); + /* caller masked out all except trigger mode flags */ + ret = chip->set_type(irq, flags); if (ret) pr_err("setting trigger mode %d for irq %u failed (%pF)\n", - (int)(flags & IRQF_TRIGGER_MASK), - irq, chip->set_type); + (int)flags, irq, chip->set_type); else { + if (flags & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + flags |= IRQ_LEVEL; /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */ - desc->status &= ~IRQ_TYPE_SENSE_MASK; - desc->status |= flags & IRQ_TYPE_SENSE_MASK; + desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK); + desc->status |= flags; } return ret; @@ -459,7 +461,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) /* Setup the type (level, edge polarity) if configured: */ if (new->flags & IRQF_TRIGGER_MASK) { - ret = __irq_set_trigger(desc, irq, new->flags); + ret = __irq_set_trigger(desc, irq, + new->flags & IRQF_TRIGGER_MASK); if (ret) { spin_unlock_irqrestore(&desc->lock, flags); @@ -673,6 +676,18 @@ int request_irq(unsigned int irq, irq_handler_t handler, struct irq_desc *desc; int retval; + /* + * handle_IRQ_event() always ignores IRQF_DISABLED except for + * the _first_ irqaction (sigh). That can cause oopsing, but + * the behavior is classified as "will not fix" so we need to + * start nudging drivers away from using that idiom. + */ + if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) + == (IRQF_SHARED|IRQF_DISABLED)) + pr_warning("IRQ %d/%s: IRQF_DISABLED is not " + "guaranteed on shared IRQs\n", + irq, devname); + #ifdef CONFIG_LOCKDEP /* * Lockdep wants atomic interrupt handlers: diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c new file mode 100644 index 000000000000..089c3746358a --- /dev/null +++ b/kernel/irq/numa_migrate.c @@ -0,0 +1,122 @@ +/* + * NUMA irq-desc migration code + * + * Migrate IRQ data structures (irq_desc, chip_data, etc.) over to + * the new "home node" of the IRQ. + */ + +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/random.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> + +#include "internals.h" + +static void init_copy_kstat_irqs(struct irq_desc *old_desc, + struct irq_desc *desc, + int cpu, int nr) +{ + unsigned long bytes; + + init_kstat_irqs(desc, cpu, nr); + + if (desc->kstat_irqs != old_desc->kstat_irqs) { + /* Compute how many bytes we need per irq and allocate them */ + bytes = nr * sizeof(unsigned int); + + memcpy(desc->kstat_irqs, old_desc->kstat_irqs, bytes); + } +} + +static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) +{ + if (old_desc->kstat_irqs == desc->kstat_irqs) + return; + + kfree(old_desc->kstat_irqs); + old_desc->kstat_irqs = NULL; +} + +static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, + struct irq_desc *desc, int cpu) +{ + memcpy(desc, old_desc, sizeof(struct irq_desc)); + desc->cpu = cpu; + lockdep_set_class(&desc->lock, &irq_desc_lock_class); + init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); + arch_init_copy_chip_data(old_desc, desc, cpu); +} + +static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc) +{ + free_kstat_irqs(old_desc, desc); + arch_free_chip_data(old_desc, desc); +} + +static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, + int cpu) +{ + struct irq_desc *desc; + unsigned int irq; + unsigned long flags; + int node; + + irq = old_desc->irq; + + spin_lock_irqsave(&sparse_irq_lock, flags); + + /* We have to check it to avoid races with another CPU */ + desc = irq_desc_ptrs[irq]; + + if (desc && old_desc != desc) + goto out_unlock; + + node = cpu_to_node(cpu); + desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); + printk(KERN_DEBUG " move irq_desc for %d to cpu %d node %d\n", + irq, cpu, node); + if (!desc) { + printk(KERN_ERR "can not get new irq_desc for moving\n"); + /* still use old one */ + desc = old_desc; + goto out_unlock; + } + init_copy_one_irq_desc(irq, old_desc, desc, cpu); + + irq_desc_ptrs[irq] = desc; + + /* free the old one */ + free_one_irq_desc(old_desc, desc); + kfree(old_desc); + +out_unlock: + spin_unlock_irqrestore(&sparse_irq_lock, flags); + + return desc; +} + +struct irq_desc *move_irq_desc(struct irq_desc *desc, int cpu) +{ + int old_cpu; + int node, old_node; + + /* those all static, do move them */ + if (desc->irq < NR_IRQS_LEGACY) + return desc; + + old_cpu = desc->cpu; + printk(KERN_DEBUG + "try to move irq_desc from cpu %d to %d\n", old_cpu, cpu); + if (old_cpu != cpu) { + node = cpu_to_node(cpu); + old_node = cpu_to_node(old_cpu); + if (old_node != node) + desc = __real_move_irq_desc(desc, cpu); + else + desc->cpu = cpu; + } + + return desc; +} + diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index d257e7d6a8a4..f6b3440f05bc 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -243,7 +243,11 @@ void init_irq_proc(void) /* * Create entries for all existing IRQs. */ - for_each_irq_desc(irq, desc) + for_each_irq_desc(irq, desc) { + if (!desc) + continue; + register_irq_proc(irq, desc); + } } diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dd364c11e56e..3738107531fd 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -91,6 +91,9 @@ static int misrouted_irq(int irq) int i, ok = 0; for_each_irq_desc(i, desc) { + if (!desc) + continue; + if (!i) continue; @@ -112,6 +115,8 @@ static void poll_spurious_irqs(unsigned long dummy) for_each_irq_desc(i, desc) { unsigned int status; + if (!desc) + continue; if (!i) continue; diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 74b1878b8bb8..06b0c3568f0b 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -137,16 +137,16 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) #ifdef CONFIG_LOCK_STAT static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats); -static int lock_contention_point(struct lock_class *class, unsigned long ip) +static int lock_point(unsigned long points[], unsigned long ip) { int i; - for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { - if (class->contention_point[i] == 0) { - class->contention_point[i] = ip; + for (i = 0; i < LOCKSTAT_POINTS; i++) { + if (points[i] == 0) { + points[i] = ip; break; } - if (class->contention_point[i] == ip) + if (points[i] == ip) break; } @@ -186,6 +186,9 @@ struct lock_class_stats lock_stats(struct lock_class *class) for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++) stats.contention_point[i] += pcs->contention_point[i]; + for (i = 0; i < ARRAY_SIZE(stats.contending_point); i++) + stats.contending_point[i] += pcs->contending_point[i]; + lock_time_add(&pcs->read_waittime, &stats.read_waittime); lock_time_add(&pcs->write_waittime, &stats.write_waittime); @@ -210,6 +213,7 @@ void clear_lock_stats(struct lock_class *class) memset(cpu_stats, 0, sizeof(struct lock_class_stats)); } memset(class->contention_point, 0, sizeof(class->contention_point)); + memset(class->contending_point, 0, sizeof(class->contending_point)); } static struct lock_class_stats *get_lock_stats(struct lock_class *class) @@ -288,14 +292,12 @@ void lockdep_off(void) { current->lockdep_recursion++; } - EXPORT_SYMBOL(lockdep_off); void lockdep_on(void) { current->lockdep_recursion--; } - EXPORT_SYMBOL(lockdep_on); /* @@ -577,7 +579,8 @@ static void print_lock_class_header(struct lock_class *class, int depth) /* * printk all lock dependencies starting at <entry>: */ -static void print_lock_dependencies(struct lock_class *class, int depth) +static void __used +print_lock_dependencies(struct lock_class *class, int depth) { struct lock_list *entry; @@ -2509,7 +2512,6 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, if (subclass) register_lock_class(lock, subclass, 1); } - EXPORT_SYMBOL_GPL(lockdep_init_map); /* @@ -2690,8 +2692,9 @@ static int check_unlock(struct task_struct *curr, struct lockdep_map *lock, } static int -__lock_set_subclass(struct lockdep_map *lock, - unsigned int subclass, unsigned long ip) +__lock_set_class(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, unsigned int subclass, + unsigned long ip) { struct task_struct *curr = current; struct held_lock *hlock, *prev_hlock; @@ -2718,6 +2721,7 @@ __lock_set_subclass(struct lockdep_map *lock, return print_unlock_inbalance_bug(curr, lock, ip); found_it: + lockdep_init_map(lock, name, key, 0); class = register_lock_class(lock, subclass, 0); hlock->class_idx = class - lock_classes + 1; @@ -2902,9 +2906,9 @@ static void check_flags(unsigned long flags) #endif } -void -lock_set_subclass(struct lockdep_map *lock, - unsigned int subclass, unsigned long ip) +void lock_set_class(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, unsigned int subclass, + unsigned long ip) { unsigned long flags; @@ -2914,13 +2918,12 @@ lock_set_subclass(struct lockdep_map *lock, raw_local_irq_save(flags); current->lockdep_recursion = 1; check_flags(flags); - if (__lock_set_subclass(lock, subclass, ip)) + if (__lock_set_class(lock, name, key, subclass, ip)) check_chain_key(current); current->lockdep_recursion = 0; raw_local_irq_restore(flags); } - -EXPORT_SYMBOL_GPL(lock_set_subclass); +EXPORT_SYMBOL_GPL(lock_set_class); /* * We are not always called with irqs disabled - do that here, @@ -2944,7 +2947,6 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, current->lockdep_recursion = 0; raw_local_irq_restore(flags); } - EXPORT_SYMBOL_GPL(lock_acquire); void lock_release(struct lockdep_map *lock, int nested, @@ -2962,7 +2964,6 @@ void lock_release(struct lockdep_map *lock, int nested, current->lockdep_recursion = 0; raw_local_irq_restore(flags); } - EXPORT_SYMBOL_GPL(lock_release); #ifdef CONFIG_LOCK_STAT @@ -3000,7 +3001,7 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) struct held_lock *hlock, *prev_hlock; struct lock_class_stats *stats; unsigned int depth; - int i, point; + int i, contention_point, contending_point; depth = curr->lockdep_depth; if (DEBUG_LOCKS_WARN_ON(!depth)) @@ -3024,18 +3025,22 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) found_it: hlock->waittime_stamp = sched_clock(); - point = lock_contention_point(hlock_class(hlock), ip); + contention_point = lock_point(hlock_class(hlock)->contention_point, ip); + contending_point = lock_point(hlock_class(hlock)->contending_point, + lock->ip); stats = get_lock_stats(hlock_class(hlock)); - if (point < ARRAY_SIZE(stats->contention_point)) - stats->contention_point[point]++; + if (contention_point < LOCKSTAT_POINTS) + stats->contention_point[contention_point]++; + if (contending_point < LOCKSTAT_POINTS) + stats->contending_point[contending_point]++; if (lock->cpu != smp_processor_id()) stats->bounces[bounce_contended + !!hlock->read]++; put_lock_stats(stats); } static void -__lock_acquired(struct lockdep_map *lock) +__lock_acquired(struct lockdep_map *lock, unsigned long ip) { struct task_struct *curr = current; struct held_lock *hlock, *prev_hlock; @@ -3084,6 +3089,7 @@ found_it: put_lock_stats(stats); lock->cpu = cpu; + lock->ip = ip; } void lock_contended(struct lockdep_map *lock, unsigned long ip) @@ -3105,7 +3111,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) } EXPORT_SYMBOL_GPL(lock_contended); -void lock_acquired(struct lockdep_map *lock) +void lock_acquired(struct lockdep_map *lock, unsigned long ip) { unsigned long flags; @@ -3118,7 +3124,7 @@ void lock_acquired(struct lockdep_map *lock) raw_local_irq_save(flags); check_flags(flags); current->lockdep_recursion = 1; - __lock_acquired(lock); + __lock_acquired(lock, ip); current->lockdep_recursion = 0; raw_local_irq_restore(flags); } @@ -3442,7 +3448,6 @@ retry: if (unlock) read_unlock(&tasklist_lock); } - EXPORT_SYMBOL_GPL(debug_show_all_locks); /* @@ -3463,7 +3468,6 @@ void debug_show_held_locks(struct task_struct *task) { __debug_show_held_locks(task); } - EXPORT_SYMBOL_GPL(debug_show_held_locks); void lockdep_sys_exit(void) diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index 20dbcbf9c7dd..13716b813896 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c @@ -470,11 +470,12 @@ static void seq_line(struct seq_file *m, char c, int offset, int length) static void snprint_time(char *buf, size_t bufsiz, s64 nr) { - unsigned long rem; + s64 div; + s32 rem; nr += 5; /* for display rounding */ - rem = do_div(nr, 1000); /* XXX: do_div_signed */ - snprintf(buf, bufsiz, "%lld.%02d", (long long)nr, (int)rem/10); + div = div_s64_rem(nr, 1000, &rem); + snprintf(buf, bufsiz, "%lld.%02d", (long long)div, (int)rem/10); } static void seq_time(struct seq_file *m, s64 time) @@ -556,7 +557,7 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) if (stats->read_holdtime.nr) namelen += 2; - for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { + for (i = 0; i < LOCKSTAT_POINTS; i++) { char sym[KSYM_SYMBOL_LEN]; char ip[32]; @@ -573,6 +574,23 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) stats->contention_point[i], ip, sym); } + for (i = 0; i < LOCKSTAT_POINTS; i++) { + char sym[KSYM_SYMBOL_LEN]; + char ip[32]; + + if (class->contending_point[i] == 0) + break; + + if (!i) + seq_line(m, '-', 40-namelen, namelen); + + sprint_symbol(sym, class->contending_point[i]); + snprintf(ip, sizeof(ip), "[<%p>]", + (void *)class->contending_point[i]); + seq_printf(m, "%40s %14lu %29s %s\n", name, + stats->contending_point[i], + ip, sym); + } if (i) { seq_puts(m, "\n"); seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1)); @@ -582,7 +600,7 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) static void seq_header(struct seq_file *m) { - seq_printf(m, "lock_stat version 0.2\n"); + seq_printf(m, "lock_stat version 0.3\n"); seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " "%14s %14s\n", diff --git a/kernel/mutex.c b/kernel/mutex.c index 12c779dc65d4..4f45d4b658ef 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -59,7 +59,7 @@ EXPORT_SYMBOL(__mutex_init); * We also put the fastpath first in the kernel image, to make sure the * branch is predicted by the CPU as default-untaken. */ -static void noinline __sched +static __used noinline void __sched __mutex_lock_slowpath(atomic_t *lock_count); /*** @@ -96,7 +96,7 @@ void inline __sched mutex_lock(struct mutex *lock) EXPORT_SYMBOL(mutex_lock); #endif -static noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count); +static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count); /*** * mutex_unlock - release the mutex @@ -184,7 +184,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, } done: - lock_acquired(&lock->dep_map); + lock_acquired(&lock->dep_map, ip); /* got the lock - rejoice! */ mutex_remove_waiter(lock, &waiter, task_thread_info(task)); debug_mutex_set_owner(lock, task_thread_info(task)); @@ -268,7 +268,7 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested) /* * Release the lock, slowpath: */ -static noinline void +static __used noinline void __mutex_unlock_slowpath(atomic_t *lock_count) { __mutex_unlock_common_slowpath(lock_count, 1); @@ -313,7 +313,7 @@ int __sched mutex_lock_killable(struct mutex *lock) } EXPORT_SYMBOL(mutex_lock_killable); -static noinline void __sched +static __used noinline void __sched __mutex_lock_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); diff --git a/kernel/notifier.c b/kernel/notifier.c index 4282c0a40a57..61d5aa5eced3 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -82,6 +82,14 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl, while (nb && nr_to_call) { next_nb = rcu_dereference(nb->next); + +#ifdef CONFIG_DEBUG_NOTIFIERS + if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) { + WARN(1, "Invalid notifier called!"); + nb = next_nb; + continue; + } +#endif ret = nb->notifier_call(nb, val, v); if (nr_calls) diff --git a/kernel/panic.c b/kernel/panic.c index 4d5088355bfe..13f06349a786 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -21,6 +21,7 @@ #include <linux/debug_locks.h> #include <linux/random.h> #include <linux/kallsyms.h> +#include <linux/dmi.h> int panic_on_oops; static unsigned long tainted_mask; @@ -321,36 +322,27 @@ void oops_exit(void) } #ifdef WANT_WARN_ON_SLOWPATH -void warn_on_slowpath(const char *file, int line) -{ - char function[KSYM_SYMBOL_LEN]; - unsigned long caller = (unsigned long) __builtin_return_address(0); - sprint_symbol(function, caller); - - printk(KERN_WARNING "------------[ cut here ]------------\n"); - printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, - line, function); - print_modules(); - dump_stack(); - print_oops_end_marker(); - add_taint(TAINT_WARN); -} -EXPORT_SYMBOL(warn_on_slowpath); - - void warn_slowpath(const char *file, int line, const char *fmt, ...) { va_list args; char function[KSYM_SYMBOL_LEN]; unsigned long caller = (unsigned long)__builtin_return_address(0); + const char *board; + sprint_symbol(function, caller); printk(KERN_WARNING "------------[ cut here ]------------\n"); printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, line, function); - va_start(args, fmt); - vprintk(fmt, args); - va_end(args); + board = dmi_get_system_info(DMI_PRODUCT_NAME); + if (board) + printk(KERN_WARNING "Hardware name: %s\n", board); + + if (fmt) { + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); + } print_modules(); dump_stack(); diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 4e5288a831de..157de3a47832 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -58,21 +58,21 @@ void thread_group_cputime( struct task_struct *tsk, struct task_cputime *times) { - struct signal_struct *sig; + struct task_cputime *totals, *tot; int i; - struct task_cputime *tot; - sig = tsk->signal; - if (unlikely(!sig) || !sig->cputime.totals) { + totals = tsk->signal->cputime.totals; + if (!totals) { times->utime = tsk->utime; times->stime = tsk->stime; times->sum_exec_runtime = tsk->se.sum_exec_runtime; return; } + times->stime = times->utime = cputime_zero; times->sum_exec_runtime = 0; for_each_possible_cpu(i) { - tot = per_cpu_ptr(tsk->signal->cputime.totals, i); + tot = per_cpu_ptr(totals, i); times->utime = cputime_add(times->utime, tot->utime); times->stime = cputime_add(times->stime, tot->stime); times->sum_exec_runtime += tot->sum_exec_runtime; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index a140e44eebba..887c63787de6 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -116,7 +116,7 @@ static DEFINE_SPINLOCK(idr_lock); * must supply functions here, even if the function just returns * ENOSYS. The standard POSIX timer management code assumes the * following: 1.) The k_itimer struct (sched.h) is used for the - * timer. 2.) The list, it_lock, it_clock, it_id and it_process + * timer. 2.) The list, it_lock, it_clock, it_id and it_pid * fields are not modified by timer code. * * At this time all functions EXCEPT clock_nanosleep can be @@ -319,7 +319,8 @@ void do_schedule_next_timer(struct siginfo *info) int posix_timer_event(struct k_itimer *timr, int si_private) { - int shared, ret; + struct task_struct *task; + int shared, ret = -1; /* * FIXME: if ->sigq is queued we can race with * dequeue_signal()->do_schedule_next_timer(). @@ -333,8 +334,13 @@ int posix_timer_event(struct k_itimer *timr, int si_private) */ timr->sigq->info.si_sys_private = si_private; - shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID); - ret = send_sigqueue(timr->sigq, timr->it_process, shared); + rcu_read_lock(); + task = pid_task(timr->it_pid, PIDTYPE_PID); + if (task) { + shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID); + ret = send_sigqueue(timr->sigq, task, shared); + } + rcu_read_unlock(); /* If we failed to send the signal the timer stops. */ return ret > 0; } @@ -411,7 +417,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer) return ret; } -static struct task_struct * good_sigevent(sigevent_t * event) +static struct pid *good_sigevent(sigevent_t * event) { struct task_struct *rtn = current->group_leader; @@ -425,7 +431,7 @@ static struct task_struct * good_sigevent(sigevent_t * event) ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) return NULL; - return rtn; + return task_pid(rtn); } void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock) @@ -464,6 +470,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) idr_remove(&posix_timers_id, tmr->it_id); spin_unlock_irqrestore(&idr_lock, flags); } + put_pid(tmr->it_pid); sigqueue_free(tmr->sigq); kmem_cache_free(posix_timers_cache, tmr); } @@ -477,7 +484,6 @@ sys_timer_create(const clockid_t which_clock, { struct k_itimer *new_timer; int error, new_timer_id; - struct task_struct *process; sigevent_t event; int it_id_set = IT_ID_NOT_SET; @@ -531,11 +537,9 @@ sys_timer_create(const clockid_t which_clock, goto out; } rcu_read_lock(); - process = good_sigevent(&event); - if (process) - get_task_struct(process); + new_timer->it_pid = get_pid(good_sigevent(&event)); rcu_read_unlock(); - if (!process) { + if (!new_timer->it_pid) { error = -EINVAL; goto out; } @@ -543,8 +547,7 @@ sys_timer_create(const clockid_t which_clock, event.sigev_notify = SIGEV_SIGNAL; event.sigev_signo = SIGALRM; event.sigev_value.sival_int = new_timer->it_id; - process = current->group_leader; - get_task_struct(process); + new_timer->it_pid = get_pid(task_tgid(current)); } new_timer->it_sigev_notify = event.sigev_notify; @@ -554,7 +557,7 @@ sys_timer_create(const clockid_t which_clock, new_timer->sigq->info.si_code = SI_TIMER; spin_lock_irq(¤t->sighand->siglock); - new_timer->it_process = process; + new_timer->it_signal = current->signal; list_add(&new_timer->list, ¤t->signal->posix_timers); spin_unlock_irq(¤t->sighand->siglock); @@ -589,8 +592,7 @@ static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags) timr = idr_find(&posix_timers_id, (int)timer_id); if (timr) { spin_lock(&timr->it_lock); - if (timr->it_process && - same_thread_group(timr->it_process, current)) { + if (timr->it_signal == current->signal) { spin_unlock(&idr_lock); return timr; } @@ -837,8 +839,7 @@ retry_delete: * This keeps any tasks waiting on the spin lock from thinking * they got something (see the lock code above). */ - put_task_struct(timer->it_process); - timer->it_process = NULL; + timer->it_signal = NULL; unlock_timer(timer, flags); release_posix_timer(timer, IT_ID_SET); @@ -864,8 +865,7 @@ retry_delete: * This keeps any tasks waiting on the spin lock from thinking * they got something (see the lock code above). */ - put_task_struct(timer->it_process); - timer->it_process = NULL; + timer->it_signal = NULL; unlock_timer(timer, flags); release_posix_timer(timer, IT_ID_SET); diff --git a/kernel/printk.c b/kernel/printk.c index f492f1583d77..e651ab05655f 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -662,7 +662,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) if (recursion_bug) { recursion_bug = 0; strcpy(printk_buf, recursion_bug_msg); - printed_len = sizeof(recursion_bug_msg); + printed_len = strlen(recursion_bug_msg); } /* Emit the output into the temporary buffer */ printed_len += vscnprintf(printk_buf + printed_len, diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index 37f72e551542..e503a002f330 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -191,7 +191,7 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) /* OK, time to rat on our buddy... */ - printk(KERN_ERR "RCU detected CPU stalls:"); + printk(KERN_ERR "INFO: RCU detected CPU stalls:"); for_each_possible_cpu(cpu) { if (cpu_isset(cpu, rcp->cpumask)) printk(" %d", cpu); @@ -204,7 +204,7 @@ static void print_cpu_stall(struct rcu_ctrlblk *rcp) { unsigned long flags; - printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu jiffies)\n", + printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu/%lu jiffies)\n", smp_processor_id(), jiffies, jiffies - rcp->gp_start); dump_stack(); diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index 59236e8b9daa..04982659875a 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c @@ -551,6 +551,16 @@ void rcu_irq_exit(void) } } +void rcu_nmi_enter(void) +{ + rcu_irq_enter(); +} + +void rcu_nmi_exit(void) +{ + rcu_irq_exit(); +} + static void dyntick_save_progress_counter(int cpu) { struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu); diff --git a/kernel/rcupreempt_trace.c b/kernel/rcupreempt_trace.c index 35c2d3360ecf..7c2665cac172 100644 --- a/kernel/rcupreempt_trace.c +++ b/kernel/rcupreempt_trace.c @@ -149,12 +149,12 @@ static void rcupreempt_trace_sum(struct rcupreempt_trace *sp) sp->done_length += cp->done_length; sp->done_add += cp->done_add; sp->done_remove += cp->done_remove; - atomic_set(&sp->done_invoked, atomic_read(&cp->done_invoked)); + atomic_add(atomic_read(&cp->done_invoked), &sp->done_invoked); sp->rcu_check_callbacks += cp->rcu_check_callbacks; - atomic_set(&sp->rcu_try_flip_1, - atomic_read(&cp->rcu_try_flip_1)); - atomic_set(&sp->rcu_try_flip_e1, - atomic_read(&cp->rcu_try_flip_e1)); + atomic_add(atomic_read(&cp->rcu_try_flip_1), + &sp->rcu_try_flip_1); + atomic_add(atomic_read(&cp->rcu_try_flip_e1), + &sp->rcu_try_flip_e1); sp->rcu_try_flip_i1 += cp->rcu_try_flip_i1; sp->rcu_try_flip_ie1 += cp->rcu_try_flip_ie1; sp->rcu_try_flip_g1 += cp->rcu_try_flip_g1; diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 85cb90588a55..b31065522104 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -39,6 +39,7 @@ #include <linux/moduleparam.h> #include <linux/percpu.h> #include <linux/notifier.h> +#include <linux/reboot.h> #include <linux/freezer.h> #include <linux/cpu.h> #include <linux/delay.h> @@ -108,7 +109,6 @@ struct rcu_torture { int rtort_mbtest; }; -static int fullstop = 0; /* stop generating callbacks at test end. */ static LIST_HEAD(rcu_torture_freelist); static struct rcu_torture *rcu_torture_current = NULL; static long rcu_torture_current_version = 0; @@ -136,6 +136,30 @@ static int stutter_pause_test = 0; #endif int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT; +#define FULLSTOP_SIGNALED 1 /* Bail due to signal. */ +#define FULLSTOP_CLEANUP 2 /* Orderly shutdown. */ +static int fullstop; /* stop generating callbacks at test end. */ +DEFINE_MUTEX(fullstop_mutex); /* protect fullstop transitions and */ + /* spawning of kthreads. */ + +/* + * Detect and respond to a signal-based shutdown. + */ +static int +rcutorture_shutdown_notify(struct notifier_block *unused1, + unsigned long unused2, void *unused3) +{ + if (fullstop) + return NOTIFY_DONE; + if (signal_pending(current)) { + mutex_lock(&fullstop_mutex); + if (!ACCESS_ONCE(fullstop)) + fullstop = FULLSTOP_SIGNALED; + mutex_unlock(&fullstop_mutex); + } + return NOTIFY_DONE; +} + /* * Allocate an element from the rcu_tortures pool. */ @@ -199,11 +223,12 @@ rcu_random(struct rcu_random_state *rrsp) static void rcu_stutter_wait(void) { - while (stutter_pause_test || !rcutorture_runnable) + while ((stutter_pause_test || !rcutorture_runnable) && !fullstop) { if (rcutorture_runnable) schedule_timeout_interruptible(1); else schedule_timeout_interruptible(round_jiffies_relative(HZ)); + } } /* @@ -599,7 +624,7 @@ rcu_torture_writer(void *arg) rcu_stutter_wait(); } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); - while (!kthread_should_stop()) + while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) schedule_timeout_uninterruptible(1); return 0; } @@ -624,7 +649,7 @@ rcu_torture_fakewriter(void *arg) } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); - while (!kthread_should_stop()) + while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) schedule_timeout_uninterruptible(1); return 0; } @@ -734,7 +759,7 @@ rcu_torture_reader(void *arg) VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping"); if (irqreader && cur_ops->irqcapable) del_timer_sync(&t); - while (!kthread_should_stop()) + while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) schedule_timeout_uninterruptible(1); return 0; } @@ -831,7 +856,7 @@ rcu_torture_stats(void *arg) do { schedule_timeout_interruptible(stat_interval * HZ); rcu_torture_stats_print(); - } while (!kthread_should_stop()); + } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping"); return 0; } @@ -899,7 +924,7 @@ rcu_torture_shuffle(void *arg) do { schedule_timeout_interruptible(shuffle_interval * HZ); rcu_torture_shuffle_tasks(); - } while (!kthread_should_stop()); + } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping"); return 0; } @@ -914,10 +939,10 @@ rcu_torture_stutter(void *arg) do { schedule_timeout_interruptible(stutter * HZ); stutter_pause_test = 1; - if (!kthread_should_stop()) + if (!kthread_should_stop() && !fullstop) schedule_timeout_interruptible(stutter * HZ); stutter_pause_test = 0; - } while (!kthread_should_stop()); + } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping"); return 0; } @@ -934,12 +959,27 @@ rcu_torture_print_module_parms(char *tag) stutter, irqreader); } +static struct notifier_block rcutorture_nb = { + .notifier_call = rcutorture_shutdown_notify, +}; + static void rcu_torture_cleanup(void) { int i; - fullstop = 1; + mutex_lock(&fullstop_mutex); + if (!fullstop) { + /* If being signaled, let it happen, then exit. */ + mutex_unlock(&fullstop_mutex); + schedule_timeout_interruptible(10 * HZ); + if (cur_ops->cb_barrier != NULL) + cur_ops->cb_barrier(); + return; + } + fullstop = FULLSTOP_CLEANUP; + mutex_unlock(&fullstop_mutex); + unregister_reboot_notifier(&rcutorture_nb); if (stutter_task) { VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task"); kthread_stop(stutter_task); @@ -1015,6 +1055,8 @@ rcu_torture_init(void) { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, &srcu_ops, &sched_ops, &sched_ops_sync, }; + mutex_lock(&fullstop_mutex); + /* Process args and tell the world that the torturer is on the job. */ for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { cur_ops = torture_ops[i]; @@ -1024,6 +1066,7 @@ rcu_torture_init(void) if (i == ARRAY_SIZE(torture_ops)) { printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n", torture_type); + mutex_unlock(&fullstop_mutex); return (-EINVAL); } if (cur_ops->init) @@ -1146,9 +1189,12 @@ rcu_torture_init(void) goto unwind; } } + register_reboot_notifier(&rcutorture_nb); + mutex_unlock(&fullstop_mutex); return 0; unwind: + mutex_unlock(&fullstop_mutex); rcu_torture_cleanup(); return firsterr; } diff --git a/kernel/rcutree.c b/kernel/rcutree.c new file mode 100644 index 000000000000..a342b032112c --- /dev/null +++ b/kernel/rcutree.c @@ -0,0 +1,1535 @@ +/* + * Read-Copy Update mechanism for mutual exclusion + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2008 + * + * Authors: Dipankar Sarma <dipankar@in.ibm.com> + * Manfred Spraul <manfred@colorfullife.com> + * Paul E. McKenney <paulmck@linux.vnet.ibm.com> Hierarchical version + * + * Based on the original work by Paul McKenney <paulmck@us.ibm.com> + * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. + * + * For detailed explanation of Read-Copy Update mechanism see - + * Documentation/RCU + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/mutex.h> +#include <linux/time.h> + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +static struct lock_class_key rcu_lock_key; +struct lockdep_map rcu_lock_map = + STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key); +EXPORT_SYMBOL_GPL(rcu_lock_map); +#endif + +/* Data structures. */ + +#define RCU_STATE_INITIALIZER(name) { \ + .level = { &name.node[0] }, \ + .levelcnt = { \ + NUM_RCU_LVL_0, /* root of hierarchy. */ \ + NUM_RCU_LVL_1, \ + NUM_RCU_LVL_2, \ + NUM_RCU_LVL_3, /* == MAX_RCU_LVLS */ \ + }, \ + .signaled = RCU_SIGNAL_INIT, \ + .gpnum = -300, \ + .completed = -300, \ + .onofflock = __SPIN_LOCK_UNLOCKED(&name.onofflock), \ + .fqslock = __SPIN_LOCK_UNLOCKED(&name.fqslock), \ + .n_force_qs = 0, \ + .n_force_qs_ngp = 0, \ +} + +struct rcu_state rcu_state = RCU_STATE_INITIALIZER(rcu_state); +DEFINE_PER_CPU(struct rcu_data, rcu_data); + +struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state); +DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); + +#ifdef CONFIG_NO_HZ +DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks); +#endif /* #ifdef CONFIG_NO_HZ */ + +static int blimit = 10; /* Maximum callbacks per softirq. */ +static int qhimark = 10000; /* If this many pending, ignore blimit. */ +static int qlowmark = 100; /* Once only this many pending, use blimit. */ + +static void force_quiescent_state(struct rcu_state *rsp, int relaxed); + +/* + * Return the number of RCU batches processed thus far for debug & stats. + */ +long rcu_batches_completed(void) +{ + return rcu_state.completed; +} +EXPORT_SYMBOL_GPL(rcu_batches_completed); + +/* + * Return the number of RCU BH batches processed thus far for debug & stats. + */ +long rcu_batches_completed_bh(void) +{ + return rcu_bh_state.completed; +} +EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); + +/* + * Does the CPU have callbacks ready to be invoked? + */ +static int +cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp) +{ + return &rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]; +} + +/* + * Does the current CPU require a yet-as-unscheduled grace period? + */ +static int +cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) +{ + /* ACCESS_ONCE() because we are accessing outside of lock. */ + return *rdp->nxttail[RCU_DONE_TAIL] && + ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum); +} + +/* + * Return the root node of the specified rcu_state structure. + */ +static struct rcu_node *rcu_get_root(struct rcu_state *rsp) +{ + return &rsp->node[0]; +} + +#ifdef CONFIG_SMP + +/* + * If the specified CPU is offline, tell the caller that it is in + * a quiescent state. Otherwise, whack it with a reschedule IPI. + * Grace periods can end up waiting on an offline CPU when that + * CPU is in the process of coming online -- it will be added to the + * rcu_node bitmasks before it actually makes it online. The same thing + * can happen while a CPU is in the process of coming online. Because this + * race is quite rare, we check for it after detecting that the grace + * period has been delayed rather than checking each and every CPU + * each and every time we start a new grace period. + */ +static int rcu_implicit_offline_qs(struct rcu_data *rdp) +{ + /* + * If the CPU is offline, it is in a quiescent state. We can + * trust its state not to change because interrupts are disabled. + */ + if (cpu_is_offline(rdp->cpu)) { + rdp->offline_fqs++; + return 1; + } + + /* The CPU is online, so send it a reschedule IPI. */ + if (rdp->cpu != smp_processor_id()) + smp_send_reschedule(rdp->cpu); + else + set_need_resched(); + rdp->resched_ipi++; + return 0; +} + +#endif /* #ifdef CONFIG_SMP */ + +#ifdef CONFIG_NO_HZ +static DEFINE_RATELIMIT_STATE(rcu_rs, 10 * HZ, 5); + +/** + * rcu_enter_nohz - inform RCU that current CPU is entering nohz + * + * Enter nohz mode, in other words, -leave- the mode in which RCU + * read-side critical sections can occur. (Though RCU read-side + * critical sections can occur in irq handlers in nohz mode, a possibility + * handled by rcu_irq_enter() and rcu_irq_exit()). + */ +void rcu_enter_nohz(void) +{ + unsigned long flags; + struct rcu_dynticks *rdtp; + + smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ + local_irq_save(flags); + rdtp = &__get_cpu_var(rcu_dynticks); + rdtp->dynticks++; + rdtp->dynticks_nesting--; + WARN_ON_RATELIMIT(rdtp->dynticks & 0x1, &rcu_rs); + local_irq_restore(flags); +} + +/* + * rcu_exit_nohz - inform RCU that current CPU is leaving nohz + * + * Exit nohz mode, in other words, -enter- the mode in which RCU + * read-side critical sections normally occur. + */ +void rcu_exit_nohz(void) +{ + unsigned long flags; + struct rcu_dynticks *rdtp; + + local_irq_save(flags); + rdtp = &__get_cpu_var(rcu_dynticks); + rdtp->dynticks++; + rdtp->dynticks_nesting++; + WARN_ON_RATELIMIT(!(rdtp->dynticks & 0x1), &rcu_rs); + local_irq_restore(flags); + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ +} + +/** + * rcu_nmi_enter - inform RCU of entry to NMI context + * + * If the CPU was idle with dynamic ticks active, and there is no + * irq handler running, this updates rdtp->dynticks_nmi to let the + * RCU grace-period handling know that the CPU is active. + */ +void rcu_nmi_enter(void) +{ + struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); + + if (rdtp->dynticks & 0x1) + return; + rdtp->dynticks_nmi++; + WARN_ON_RATELIMIT(!(rdtp->dynticks_nmi & 0x1), &rcu_rs); + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ +} + +/** + * rcu_nmi_exit - inform RCU of exit from NMI context + * + * If the CPU was idle with dynamic ticks active, and there is no + * irq handler running, this updates rdtp->dynticks_nmi to let the + * RCU grace-period handling know that the CPU is no longer active. + */ +void rcu_nmi_exit(void) +{ + struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); + + if (rdtp->dynticks & 0x1) + return; + smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ + rdtp->dynticks_nmi++; + WARN_ON_RATELIMIT(rdtp->dynticks_nmi & 0x1, &rcu_rs); +} + +/** + * rcu_irq_enter - inform RCU of entry to hard irq context + * + * If the CPU was idle with dynamic ticks active, this updates the + * rdtp->dynticks to let the RCU handling know that the CPU is active. + */ +void rcu_irq_enter(void) +{ + struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); + + if (rdtp->dynticks_nesting++) + return; + rdtp->dynticks++; + WARN_ON_RATELIMIT(!(rdtp->dynticks & 0x1), &rcu_rs); + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ +} + +/** + * rcu_irq_exit - inform RCU of exit from hard irq context + * + * If the CPU was idle with dynamic ticks active, update the rdp->dynticks + * to put let the RCU handling be aware that the CPU is going back to idle + * with no ticks. + */ +void rcu_irq_exit(void) +{ + struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); + + if (--rdtp->dynticks_nesting) + return; + smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ + rdtp->dynticks++; + WARN_ON_RATELIMIT(rdtp->dynticks & 0x1, &rcu_rs); + + /* If the interrupt queued a callback, get out of dyntick mode. */ + if (__get_cpu_var(rcu_data).nxtlist || + __get_cpu_var(rcu_bh_data).nxtlist) + set_need_resched(); +} + +/* + * Record the specified "completed" value, which is later used to validate + * dynticks counter manipulations. Specify "rsp->completed - 1" to + * unconditionally invalidate any future dynticks manipulations (which is + * useful at the beginning of a grace period). + */ +static void dyntick_record_completed(struct rcu_state *rsp, long comp) +{ + rsp->dynticks_completed = comp; +} + +#ifdef CONFIG_SMP + +/* + * Recall the previously recorded value of the completion for dynticks. + */ +static long dyntick_recall_completed(struct rcu_state *rsp) +{ + return rsp->dynticks_completed; +} + +/* + * Snapshot the specified CPU's dynticks counter so that we can later + * credit them with an implicit quiescent state. Return 1 if this CPU + * is already in a quiescent state courtesy of dynticks idle mode. + */ +static int dyntick_save_progress_counter(struct rcu_data *rdp) +{ + int ret; + int snap; + int snap_nmi; + + snap = rdp->dynticks->dynticks; + snap_nmi = rdp->dynticks->dynticks_nmi; + smp_mb(); /* Order sampling of snap with end of grace period. */ + rdp->dynticks_snap = snap; + rdp->dynticks_nmi_snap = snap_nmi; + ret = ((snap & 0x1) == 0) && ((snap_nmi & 0x1) == 0); + if (ret) + rdp->dynticks_fqs++; + return ret; +} + +/* + * Return true if the specified CPU has passed through a quiescent + * state by virtue of being in or having passed through an dynticks + * idle state since the last call to dyntick_save_progress_counter() + * for this same CPU. + */ +static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) +{ + long curr; + long curr_nmi; + long snap; + long snap_nmi; + + curr = rdp->dynticks->dynticks; + snap = rdp->dynticks_snap; + curr_nmi = rdp->dynticks->dynticks_nmi; + snap_nmi = rdp->dynticks_nmi_snap; + smp_mb(); /* force ordering with cpu entering/leaving dynticks. */ + + /* + * If the CPU passed through or entered a dynticks idle phase with + * no active irq/NMI handlers, then we can safely pretend that the CPU + * already acknowledged the request to pass through a quiescent + * state. Either way, that CPU cannot possibly be in an RCU + * read-side critical section that started before the beginning + * of the current RCU grace period. + */ + if ((curr != snap || (curr & 0x1) == 0) && + (curr_nmi != snap_nmi || (curr_nmi & 0x1) == 0)) { + rdp->dynticks_fqs++; + return 1; + } + + /* Go check for the CPU being offline. */ + return rcu_implicit_offline_qs(rdp); +} + +#endif /* #ifdef CONFIG_SMP */ + +#else /* #ifdef CONFIG_NO_HZ */ + +static void dyntick_record_completed(struct rcu_state *rsp, long comp) +{ +} + +#ifdef CONFIG_SMP + +/* + * If there are no dynticks, then the only way that a CPU can passively + * be in a quiescent state is to be offline. Unlike dynticks idle, which + * is a point in time during the prior (already finished) grace period, + * an offline CPU is always in a quiescent state, and thus can be + * unconditionally applied. So just return the current value of completed. + */ +static long dyntick_recall_completed(struct rcu_state *rsp) +{ + return rsp->completed; +} + +static int dyntick_save_progress_counter(struct rcu_data *rdp) +{ + return 0; +} + +static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) +{ + return rcu_implicit_offline_qs(rdp); +} + +#endif /* #ifdef CONFIG_SMP */ + +#endif /* #else #ifdef CONFIG_NO_HZ */ + +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + +static void record_gp_stall_check_time(struct rcu_state *rsp) +{ + rsp->gp_start = jiffies; + rsp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_CHECK; +} + +static void print_other_cpu_stall(struct rcu_state *rsp) +{ + int cpu; + long delta; + unsigned long flags; + struct rcu_node *rnp = rcu_get_root(rsp); + struct rcu_node *rnp_cur = rsp->level[NUM_RCU_LVLS - 1]; + struct rcu_node *rnp_end = &rsp->node[NUM_RCU_NODES]; + + /* Only let one CPU complain about others per time interval. */ + + spin_lock_irqsave(&rnp->lock, flags); + delta = jiffies - rsp->jiffies_stall; + if (delta < RCU_STALL_RAT_DELAY || rsp->gpnum == rsp->completed) { + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + rsp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_RECHECK; + spin_unlock_irqrestore(&rnp->lock, flags); + + /* OK, time to rat on our buddy... */ + + printk(KERN_ERR "INFO: RCU detected CPU stalls:"); + for (; rnp_cur < rnp_end; rnp_cur++) { + if (rnp_cur->qsmask == 0) + continue; + for (cpu = 0; cpu <= rnp_cur->grphi - rnp_cur->grplo; cpu++) + if (rnp_cur->qsmask & (1UL << cpu)) + printk(" %d", rnp_cur->grplo + cpu); + } + printk(" (detected by %d, t=%ld jiffies)\n", + smp_processor_id(), (long)(jiffies - rsp->gp_start)); + force_quiescent_state(rsp, 0); /* Kick them all. */ +} + +static void print_cpu_stall(struct rcu_state *rsp) +{ + unsigned long flags; + struct rcu_node *rnp = rcu_get_root(rsp); + + printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu jiffies)\n", + smp_processor_id(), jiffies - rsp->gp_start); + dump_stack(); + spin_lock_irqsave(&rnp->lock, flags); + if ((long)(jiffies - rsp->jiffies_stall) >= 0) + rsp->jiffies_stall = + jiffies + RCU_SECONDS_TILL_STALL_RECHECK; + spin_unlock_irqrestore(&rnp->lock, flags); + set_need_resched(); /* kick ourselves to get things going. */ +} + +static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) +{ + long delta; + struct rcu_node *rnp; + + delta = jiffies - rsp->jiffies_stall; + rnp = rdp->mynode; + if ((rnp->qsmask & rdp->grpmask) && delta >= 0) { + + /* We haven't checked in, so go dump stack. */ + print_cpu_stall(rsp); + + } else if (rsp->gpnum != rsp->completed && + delta >= RCU_STALL_RAT_DELAY) { + + /* They had two time units to dump stack, so complain. */ + print_other_cpu_stall(rsp); + } +} + +#else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + +static void record_gp_stall_check_time(struct rcu_state *rsp) +{ +} + +static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + +/* + * Update CPU-local rcu_data state to record the newly noticed grace period. + * This is used both when we started the grace period and when we notice + * that someone else started the grace period. + */ +static void note_new_gpnum(struct rcu_state *rsp, struct rcu_data *rdp) +{ + rdp->qs_pending = 1; + rdp->passed_quiesc = 0; + rdp->gpnum = rsp->gpnum; + rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending + + RCU_JIFFIES_TILL_FORCE_QS; +} + +/* + * Did someone else start a new RCU grace period start since we last + * checked? Update local state appropriately if so. Must be called + * on the CPU corresponding to rdp. + */ +static int +check_for_new_grace_period(struct rcu_state *rsp, struct rcu_data *rdp) +{ + unsigned long flags; + int ret = 0; + + local_irq_save(flags); + if (rdp->gpnum != rsp->gpnum) { + note_new_gpnum(rsp, rdp); + ret = 1; + } + local_irq_restore(flags); + return ret; +} + +/* + * Start a new RCU grace period if warranted, re-initializing the hierarchy + * in preparation for detecting the next grace period. The caller must hold + * the root node's ->lock, which is released before return. Hard irqs must + * be disabled. + */ +static void +rcu_start_gp(struct rcu_state *rsp, unsigned long flags) + __releases(rcu_get_root(rsp)->lock) +{ + struct rcu_data *rdp = rsp->rda[smp_processor_id()]; + struct rcu_node *rnp = rcu_get_root(rsp); + struct rcu_node *rnp_cur; + struct rcu_node *rnp_end; + + if (!cpu_needs_another_gp(rsp, rdp)) { + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + + /* Advance to a new grace period and initialize state. */ + rsp->gpnum++; + rsp->signaled = RCU_GP_INIT; /* Hold off force_quiescent_state. */ + rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; + rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending + + RCU_JIFFIES_TILL_FORCE_QS; + record_gp_stall_check_time(rsp); + dyntick_record_completed(rsp, rsp->completed - 1); + note_new_gpnum(rsp, rdp); + + /* + * Because we are first, we know that all our callbacks will + * be covered by this upcoming grace period, even the ones + * that were registered arbitrarily recently. + */ + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + + /* Special-case the common single-level case. */ + if (NUM_RCU_NODES == 1) { + rnp->qsmask = rnp->qsmaskinit; + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + + spin_unlock(&rnp->lock); /* leave irqs disabled. */ + + + /* Exclude any concurrent CPU-hotplug operations. */ + spin_lock(&rsp->onofflock); /* irqs already disabled. */ + + /* + * Set the quiescent-state-needed bits in all the non-leaf RCU + * nodes for all currently online CPUs. This operation relies + * on the layout of the hierarchy within the rsp->node[] array. + * Note that other CPUs will access only the leaves of the + * hierarchy, which still indicate that no grace period is in + * progress. In addition, we have excluded CPU-hotplug operations. + * + * We therefore do not need to hold any locks. Any required + * memory barriers will be supplied by the locks guarding the + * leaf rcu_nodes in the hierarchy. + */ + + rnp_end = rsp->level[NUM_RCU_LVLS - 1]; + for (rnp_cur = &rsp->node[0]; rnp_cur < rnp_end; rnp_cur++) + rnp_cur->qsmask = rnp_cur->qsmaskinit; + + /* + * Now set up the leaf nodes. Here we must be careful. First, + * we need to hold the lock in order to exclude other CPUs, which + * might be contending for the leaf nodes' locks. Second, as + * soon as we initialize a given leaf node, its CPUs might run + * up the rest of the hierarchy. We must therefore acquire locks + * for each node that we touch during this stage. (But we still + * are excluding CPU-hotplug operations.) + * + * Note that the grace period cannot complete until we finish + * the initialization process, as there will be at least one + * qsmask bit set in the root node until that time, namely the + * one corresponding to this CPU. + */ + rnp_end = &rsp->node[NUM_RCU_NODES]; + rnp_cur = rsp->level[NUM_RCU_LVLS - 1]; + for (; rnp_cur < rnp_end; rnp_cur++) { + spin_lock(&rnp_cur->lock); /* irqs already disabled. */ + rnp_cur->qsmask = rnp_cur->qsmaskinit; + spin_unlock(&rnp_cur->lock); /* irqs already disabled. */ + } + + rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state now OK. */ + spin_unlock_irqrestore(&rsp->onofflock, flags); +} + +/* + * Advance this CPU's callbacks, but only if the current grace period + * has ended. This may be called only from the CPU to whom the rdp + * belongs. + */ +static void +rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) +{ + long completed_snap; + unsigned long flags; + + local_irq_save(flags); + completed_snap = ACCESS_ONCE(rsp->completed); /* outside of lock. */ + + /* Did another grace period end? */ + if (rdp->completed != completed_snap) { + + /* Advance callbacks. No harm if list empty. */ + rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL]; + rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL]; + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + + /* Remember that we saw this grace-period completion. */ + rdp->completed = completed_snap; + } + local_irq_restore(flags); +} + +/* + * Similar to cpu_quiet(), for which it is a helper function. Allows + * a group of CPUs to be quieted at one go, though all the CPUs in the + * group must be represented by the same leaf rcu_node structure. + * That structure's lock must be held upon entry, and it is released + * before return. + */ +static void +cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp, + unsigned long flags) + __releases(rnp->lock) +{ + /* Walk up the rcu_node hierarchy. */ + for (;;) { + if (!(rnp->qsmask & mask)) { + + /* Our bit has already been cleared, so done. */ + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + rnp->qsmask &= ~mask; + if (rnp->qsmask != 0) { + + /* Other bits still set at this level, so done. */ + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + mask = rnp->grpmask; + if (rnp->parent == NULL) { + + /* No more levels. Exit loop holding root lock. */ + + break; + } + spin_unlock_irqrestore(&rnp->lock, flags); + rnp = rnp->parent; + spin_lock_irqsave(&rnp->lock, flags); + } + + /* + * Get here if we are the last CPU to pass through a quiescent + * state for this grace period. Clean up and let rcu_start_gp() + * start up the next grace period if one is needed. Note that + * we still hold rnp->lock, as required by rcu_start_gp(), which + * will release it. + */ + rsp->completed = rsp->gpnum; + rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]); + rcu_start_gp(rsp, flags); /* releases rnp->lock. */ +} + +/* + * Record a quiescent state for the specified CPU, which must either be + * the current CPU or an offline CPU. The lastcomp argument is used to + * make sure we are still in the grace period of interest. We don't want + * to end the current grace period based on quiescent states detected in + * an earlier grace period! + */ +static void +cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp) +{ + unsigned long flags; + unsigned long mask; + struct rcu_node *rnp; + + rnp = rdp->mynode; + spin_lock_irqsave(&rnp->lock, flags); + if (lastcomp != ACCESS_ONCE(rsp->completed)) { + + /* + * Someone beat us to it for this grace period, so leave. + * The race with GP start is resolved by the fact that we + * hold the leaf rcu_node lock, so that the per-CPU bits + * cannot yet be initialized -- so we would simply find our + * CPU's bit already cleared in cpu_quiet_msk() if this race + * occurred. + */ + rdp->passed_quiesc = 0; /* try again later! */ + spin_unlock_irqrestore(&rnp->lock, flags); + return; + } + mask = rdp->grpmask; + if ((rnp->qsmask & mask) == 0) { + spin_unlock_irqrestore(&rnp->lock, flags); + } else { + rdp->qs_pending = 0; + + /* + * This GP can't end until cpu checks in, so all of our + * callbacks can be processed during the next GP. + */ + rdp = rsp->rda[smp_processor_id()]; + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + + cpu_quiet_msk(mask, rsp, rnp, flags); /* releases rnp->lock */ + } +} + +/* + * Check to see if there is a new grace period of which this CPU + * is not yet aware, and if so, set up local rcu_data state for it. + * Otherwise, see if this CPU has just passed through its first + * quiescent state for this grace period, and record that fact if so. + */ +static void +rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp) +{ + /* If there is now a new grace period, record and return. */ + if (check_for_new_grace_period(rsp, rdp)) + return; + + /* + * Does this CPU still need to do its part for current grace period? + * If no, return and let the other CPUs do their part as well. + */ + if (!rdp->qs_pending) + return; + + /* + * Was there a quiescent state since the beginning of the grace + * period? If no, then exit and wait for the next call. + */ + if (!rdp->passed_quiesc) + return; + + /* Tell RCU we are done (but cpu_quiet() will be the judge of that). */ + cpu_quiet(rdp->cpu, rsp, rdp, rdp->passed_quiesc_completed); +} + +#ifdef CONFIG_HOTPLUG_CPU + +/* + * Remove the outgoing CPU from the bitmasks in the rcu_node hierarchy + * and move all callbacks from the outgoing CPU to the current one. + */ +static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) +{ + int i; + unsigned long flags; + long lastcomp; + unsigned long mask; + struct rcu_data *rdp = rsp->rda[cpu]; + struct rcu_data *rdp_me; + struct rcu_node *rnp; + + /* Exclude any attempts to start a new grace period. */ + spin_lock_irqsave(&rsp->onofflock, flags); + + /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ + rnp = rdp->mynode; + mask = rdp->grpmask; /* rnp->grplo is constant. */ + do { + spin_lock(&rnp->lock); /* irqs already disabled. */ + rnp->qsmaskinit &= ~mask; + if (rnp->qsmaskinit != 0) { + spin_unlock(&rnp->lock); /* irqs already disabled. */ + break; + } + mask = rnp->grpmask; + spin_unlock(&rnp->lock); /* irqs already disabled. */ + rnp = rnp->parent; + } while (rnp != NULL); + lastcomp = rsp->completed; + + spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ + + /* Being offline is a quiescent state, so go record it. */ + cpu_quiet(cpu, rsp, rdp, lastcomp); + + /* + * Move callbacks from the outgoing CPU to the running CPU. + * Note that the outgoing CPU is now quiscent, so it is now + * (uncharacteristically) safe to access it rcu_data structure. + * Note also that we must carefully retain the order of the + * outgoing CPU's callbacks in order for rcu_barrier() to work + * correctly. Finally, note that we start all the callbacks + * afresh, even those that have passed through a grace period + * and are therefore ready to invoke. The theory is that hotplug + * events are rare, and that if they are frequent enough to + * indefinitely delay callbacks, you have far worse things to + * be worrying about. + */ + rdp_me = rsp->rda[smp_processor_id()]; + if (rdp->nxtlist != NULL) { + *rdp_me->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist; + rdp_me->nxttail[RCU_NEXT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + rdp->nxtlist = NULL; + for (i = 0; i < RCU_NEXT_SIZE; i++) + rdp->nxttail[i] = &rdp->nxtlist; + rdp_me->qlen += rdp->qlen; + rdp->qlen = 0; + } + local_irq_restore(flags); +} + +/* + * Remove the specified CPU from the RCU hierarchy and move any pending + * callbacks that it might have to the current CPU. This code assumes + * that at least one CPU in the system will remain running at all times. + * Any attempt to offline -all- CPUs is likely to strand RCU callbacks. + */ +static void rcu_offline_cpu(int cpu) +{ + __rcu_offline_cpu(cpu, &rcu_state); + __rcu_offline_cpu(cpu, &rcu_bh_state); +} + +#else /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_offline_cpu(int cpu) +{ +} + +#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */ + +/* + * Invoke any RCU callbacks that have made it to the end of their grace + * period. Thottle as specified by rdp->blimit. + */ +static void rcu_do_batch(struct rcu_data *rdp) +{ + unsigned long flags; + struct rcu_head *next, *list, **tail; + int count; + + /* If no callbacks are ready, just return.*/ + if (!cpu_has_callbacks_ready_to_invoke(rdp)) + return; + + /* + * Extract the list of ready callbacks, disabling to prevent + * races with call_rcu() from interrupt handlers. + */ + local_irq_save(flags); + list = rdp->nxtlist; + rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL]; + *rdp->nxttail[RCU_DONE_TAIL] = NULL; + tail = rdp->nxttail[RCU_DONE_TAIL]; + for (count = RCU_NEXT_SIZE - 1; count >= 0; count--) + if (rdp->nxttail[count] == rdp->nxttail[RCU_DONE_TAIL]) + rdp->nxttail[count] = &rdp->nxtlist; + local_irq_restore(flags); + + /* Invoke callbacks. */ + count = 0; + while (list) { + next = list->next; + prefetch(next); + list->func(list); + list = next; + if (++count >= rdp->blimit) + break; + } + + local_irq_save(flags); + + /* Update count, and requeue any remaining callbacks. */ + rdp->qlen -= count; + if (list != NULL) { + *tail = rdp->nxtlist; + rdp->nxtlist = list; + for (count = 0; count < RCU_NEXT_SIZE; count++) + if (&rdp->nxtlist == rdp->nxttail[count]) + rdp->nxttail[count] = tail; + else + break; + } + + /* Reinstate batch limit if we have worked down the excess. */ + if (rdp->blimit == LONG_MAX && rdp->qlen <= qlowmark) + rdp->blimit = blimit; + + local_irq_restore(flags); + + /* Re-raise the RCU softirq if there are callbacks remaining. */ + if (cpu_has_callbacks_ready_to_invoke(rdp)) + raise_softirq(RCU_SOFTIRQ); +} + +/* + * Check to see if this CPU is in a non-context-switch quiescent state + * (user mode or idle loop for rcu, non-softirq execution for rcu_bh). + * Also schedule the RCU softirq handler. + * + * This function must be called with hardirqs disabled. It is normally + * invoked from the scheduling-clock interrupt. If rcu_pending returns + * false, there is no point in invoking rcu_check_callbacks(). + */ +void rcu_check_callbacks(int cpu, int user) +{ + if (user || + (idle_cpu(cpu) && !in_softirq() && + hardirq_count() <= (1 << HARDIRQ_SHIFT))) { + + /* + * Get here if this CPU took its interrupt from user + * mode or from the idle loop, and if this is not a + * nested interrupt. In this case, the CPU is in + * a quiescent state, so count it. + * + * No memory barrier is required here because both + * rcu_qsctr_inc() and rcu_bh_qsctr_inc() reference + * only CPU-local variables that other CPUs neither + * access nor modify, at least not while the corresponding + * CPU is online. + */ + + rcu_qsctr_inc(cpu); + rcu_bh_qsctr_inc(cpu); + + } else if (!in_softirq()) { + + /* + * Get here if this CPU did not take its interrupt from + * softirq, in other words, if it is not interrupting + * a rcu_bh read-side critical section. This is an _bh + * critical section, so count it. + */ + + rcu_bh_qsctr_inc(cpu); + } + raise_softirq(RCU_SOFTIRQ); +} + +#ifdef CONFIG_SMP + +/* + * Scan the leaf rcu_node structures, processing dyntick state for any that + * have not yet encountered a quiescent state, using the function specified. + * Returns 1 if the current grace period ends while scanning (possibly + * because we made it end). + */ +static int rcu_process_dyntick(struct rcu_state *rsp, long lastcomp, + int (*f)(struct rcu_data *)) +{ + unsigned long bit; + int cpu; + unsigned long flags; + unsigned long mask; + struct rcu_node *rnp_cur = rsp->level[NUM_RCU_LVLS - 1]; + struct rcu_node *rnp_end = &rsp->node[NUM_RCU_NODES]; + + for (; rnp_cur < rnp_end; rnp_cur++) { + mask = 0; + spin_lock_irqsave(&rnp_cur->lock, flags); + if (rsp->completed != lastcomp) { + spin_unlock_irqrestore(&rnp_cur->lock, flags); + return 1; + } + if (rnp_cur->qsmask == 0) { + spin_unlock_irqrestore(&rnp_cur->lock, flags); + continue; + } + cpu = rnp_cur->grplo; + bit = 1; + for (; cpu <= rnp_cur->grphi; cpu++, bit <<= 1) { + if ((rnp_cur->qsmask & bit) != 0 && f(rsp->rda[cpu])) + mask |= bit; + } + if (mask != 0 && rsp->completed == lastcomp) { + + /* cpu_quiet_msk() releases rnp_cur->lock. */ + cpu_quiet_msk(mask, rsp, rnp_cur, flags); + continue; + } + spin_unlock_irqrestore(&rnp_cur->lock, flags); + } + return 0; +} + +/* + * Force quiescent states on reluctant CPUs, and also detect which + * CPUs are in dyntick-idle mode. + */ +static void force_quiescent_state(struct rcu_state *rsp, int relaxed) +{ + unsigned long flags; + long lastcomp; + struct rcu_data *rdp = rsp->rda[smp_processor_id()]; + struct rcu_node *rnp = rcu_get_root(rsp); + u8 signaled; + + if (ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum)) + return; /* No grace period in progress, nothing to force. */ + if (!spin_trylock_irqsave(&rsp->fqslock, flags)) { + rsp->n_force_qs_lh++; /* Inexact, can lose counts. Tough! */ + return; /* Someone else is already on the job. */ + } + if (relaxed && + (long)(rsp->jiffies_force_qs - jiffies) >= 0 && + (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) >= 0) + goto unlock_ret; /* no emergency and done recently. */ + rsp->n_force_qs++; + spin_lock(&rnp->lock); + lastcomp = rsp->completed; + signaled = rsp->signaled; + rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; + rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending + + RCU_JIFFIES_TILL_FORCE_QS; + if (lastcomp == rsp->gpnum) { + rsp->n_force_qs_ngp++; + spin_unlock(&rnp->lock); + goto unlock_ret; /* no GP in progress, time updated. */ + } + spin_unlock(&rnp->lock); + switch (signaled) { + case RCU_GP_INIT: + + break; /* grace period still initializing, ignore. */ + + case RCU_SAVE_DYNTICK: + + if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) + break; /* So gcc recognizes the dead code. */ + + /* Record dyntick-idle state. */ + if (rcu_process_dyntick(rsp, lastcomp, + dyntick_save_progress_counter)) + goto unlock_ret; + + /* Update state, record completion counter. */ + spin_lock(&rnp->lock); + if (lastcomp == rsp->completed) { + rsp->signaled = RCU_FORCE_QS; + dyntick_record_completed(rsp, lastcomp); + } + spin_unlock(&rnp->lock); + break; + + case RCU_FORCE_QS: + + /* Check dyntick-idle state, send IPI to laggarts. */ + if (rcu_process_dyntick(rsp, dyntick_recall_completed(rsp), + rcu_implicit_dynticks_qs)) + goto unlock_ret; + + /* Leave state in case more forcing is required. */ + + break; + } +unlock_ret: + spin_unlock_irqrestore(&rsp->fqslock, flags); +} + +#else /* #ifdef CONFIG_SMP */ + +static void force_quiescent_state(struct rcu_state *rsp, int relaxed) +{ + set_need_resched(); +} + +#endif /* #else #ifdef CONFIG_SMP */ + +/* + * This does the RCU processing work from softirq context for the + * specified rcu_state and rcu_data structures. This may be called + * only from the CPU to whom the rdp belongs. + */ +static void +__rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) +{ + unsigned long flags; + + /* + * If an RCU GP has gone long enough, go check for dyntick + * idle CPUs and, if needed, send resched IPIs. + */ + if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 || + (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0) + force_quiescent_state(rsp, 1); + + /* + * Advance callbacks in response to end of earlier grace + * period that some other CPU ended. + */ + rcu_process_gp_end(rsp, rdp); + + /* Update RCU state based on any recent quiescent states. */ + rcu_check_quiescent_state(rsp, rdp); + + /* Does this CPU require a not-yet-started grace period? */ + if (cpu_needs_another_gp(rsp, rdp)) { + spin_lock_irqsave(&rcu_get_root(rsp)->lock, flags); + rcu_start_gp(rsp, flags); /* releases above lock */ + } + + /* If there are callbacks ready, invoke them. */ + rcu_do_batch(rdp); +} + +/* + * Do softirq processing for the current CPU. + */ +static void rcu_process_callbacks(struct softirq_action *unused) +{ + /* + * Memory references from any prior RCU read-side critical sections + * executed by the interrupted code must be seen before any RCU + * grace-period manipulations below. + */ + smp_mb(); /* See above block comment. */ + + __rcu_process_callbacks(&rcu_state, &__get_cpu_var(rcu_data)); + __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + + /* + * Memory references from any later RCU read-side critical sections + * executed by the interrupted code must be seen after any RCU + * grace-period manipulations above. + */ + smp_mb(); /* See above block comment. */ +} + +static void +__call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), + struct rcu_state *rsp) +{ + unsigned long flags; + struct rcu_data *rdp; + + head->func = func; + head->next = NULL; + + smp_mb(); /* Ensure RCU update seen before callback registry. */ + + /* + * Opportunistically note grace-period endings and beginnings. + * Note that we might see a beginning right after we see an + * end, but never vice versa, since this CPU has to pass through + * a quiescent state betweentimes. + */ + local_irq_save(flags); + rdp = rsp->rda[smp_processor_id()]; + rcu_process_gp_end(rsp, rdp); + check_for_new_grace_period(rsp, rdp); + + /* Add the callback to our list. */ + *rdp->nxttail[RCU_NEXT_TAIL] = head; + rdp->nxttail[RCU_NEXT_TAIL] = &head->next; + + /* Start a new grace period if one not already started. */ + if (ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum)) { + unsigned long nestflag; + struct rcu_node *rnp_root = rcu_get_root(rsp); + + spin_lock_irqsave(&rnp_root->lock, nestflag); + rcu_start_gp(rsp, nestflag); /* releases rnp_root->lock. */ + } + + /* Force the grace period if too many callbacks or too long waiting. */ + if (unlikely(++rdp->qlen > qhimark)) { + rdp->blimit = LONG_MAX; + force_quiescent_state(rsp, 0); + } else if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 || + (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0) + force_quiescent_state(rsp, 1); + local_irq_restore(flags); +} + +/* + * Queue an RCU callback for invocation after a grace period. + */ +void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) +{ + __call_rcu(head, func, &rcu_state); +} +EXPORT_SYMBOL_GPL(call_rcu); + +/* + * Queue an RCU for invocation after a quicker grace period. + */ +void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) +{ + __call_rcu(head, func, &rcu_bh_state); +} +EXPORT_SYMBOL_GPL(call_rcu_bh); + +/* + * Check to see if there is any immediate RCU-related work to be done + * by the current CPU, for the specified type of RCU, returning 1 if so. + * The checks are in order of increasing expense: checks that can be + * carried out against CPU-local state are performed first. However, + * we must check for CPU stalls first, else we might not get a chance. + */ +static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) +{ + rdp->n_rcu_pending++; + + /* Check for CPU stalls, if enabled. */ + check_cpu_stall(rsp, rdp); + + /* Is the RCU core waiting for a quiescent state from this CPU? */ + if (rdp->qs_pending) + return 1; + + /* Does this CPU have callbacks ready to invoke? */ + if (cpu_has_callbacks_ready_to_invoke(rdp)) + return 1; + + /* Has RCU gone idle with this CPU needing another grace period? */ + if (cpu_needs_another_gp(rsp, rdp)) + return 1; + + /* Has another RCU grace period completed? */ + if (ACCESS_ONCE(rsp->completed) != rdp->completed) /* outside of lock */ + return 1; + + /* Has a new RCU grace period started? */ + if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) /* outside of lock */ + return 1; + + /* Has an RCU GP gone long enough to send resched IPIs &c? */ + if (ACCESS_ONCE(rsp->completed) != ACCESS_ONCE(rsp->gpnum) && + ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 || + (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0)) + return 1; + + /* nothing to do */ + return 0; +} + +/* + * Check to see if there is any immediate RCU-related work to be done + * by the current CPU, returning 1 if so. This function is part of the + * RCU implementation; it is -not- an exported member of the RCU API. + */ +int rcu_pending(int cpu) +{ + return __rcu_pending(&rcu_state, &per_cpu(rcu_data, cpu)) || + __rcu_pending(&rcu_bh_state, &per_cpu(rcu_bh_data, cpu)); +} + +/* + * Check to see if any future RCU-related work will need to be done + * by the current CPU, even if none need be done immediately, returning + * 1 if so. This function is part of the RCU implementation; it is -not- + * an exported member of the RCU API. + */ +int rcu_needs_cpu(int cpu) +{ + /* RCU callbacks either ready or pending? */ + return per_cpu(rcu_data, cpu).nxtlist || + per_cpu(rcu_bh_data, cpu).nxtlist; +} + +/* + * Initialize a CPU's per-CPU RCU data. We take this "scorched earth" + * approach so that we don't have to worry about how long the CPU has + * been gone, or whether it ever was online previously. We do trust the + * ->mynode field, as it is constant for a given struct rcu_data and + * initialized during early boot. + * + * Note that only one online or offline event can be happening at a given + * time. Note also that we can accept some slop in the rsp->completed + * access due to the fact that this CPU cannot possibly have any RCU + * callbacks in flight yet. + */ +static void +rcu_init_percpu_data(int cpu, struct rcu_state *rsp) +{ + unsigned long flags; + int i; + long lastcomp; + unsigned long mask; + struct rcu_data *rdp = rsp->rda[cpu]; + struct rcu_node *rnp = rcu_get_root(rsp); + + /* Set up local state, ensuring consistent view of global state. */ + spin_lock_irqsave(&rnp->lock, flags); + lastcomp = rsp->completed; + rdp->completed = lastcomp; + rdp->gpnum = lastcomp; + rdp->passed_quiesc = 0; /* We could be racing with new GP, */ + rdp->qs_pending = 1; /* so set up to respond to current GP. */ + rdp->beenonline = 1; /* We have now been online. */ + rdp->passed_quiesc_completed = lastcomp - 1; + rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo); + rdp->nxtlist = NULL; + for (i = 0; i < RCU_NEXT_SIZE; i++) + rdp->nxttail[i] = &rdp->nxtlist; + rdp->qlen = 0; + rdp->blimit = blimit; +#ifdef CONFIG_NO_HZ + rdp->dynticks = &per_cpu(rcu_dynticks, cpu); +#endif /* #ifdef CONFIG_NO_HZ */ + rdp->cpu = cpu; + spin_unlock(&rnp->lock); /* irqs remain disabled. */ + + /* + * A new grace period might start here. If so, we won't be part + * of it, but that is OK, as we are currently in a quiescent state. + */ + + /* Exclude any attempts to start a new GP on large systems. */ + spin_lock(&rsp->onofflock); /* irqs already disabled. */ + + /* Add CPU to rcu_node bitmasks. */ + rnp = rdp->mynode; + mask = rdp->grpmask; + do { + /* Exclude any attempts to start a new GP on small systems. */ + spin_lock(&rnp->lock); /* irqs already disabled. */ + rnp->qsmaskinit |= mask; + mask = rnp->grpmask; + spin_unlock(&rnp->lock); /* irqs already disabled. */ + rnp = rnp->parent; + } while (rnp != NULL && !(rnp->qsmaskinit & mask)); + + spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ + + /* + * A new grace period might start here. If so, we will be part of + * it, and its gpnum will be greater than ours, so we will + * participate. It is also possible for the gpnum to have been + * incremented before this function was called, and the bitmasks + * to not be filled out until now, in which case we will also + * participate due to our gpnum being behind. + */ + + /* Since it is coming online, the CPU is in a quiescent state. */ + cpu_quiet(cpu, rsp, rdp, lastcomp); + local_irq_restore(flags); +} + +static void __cpuinit rcu_online_cpu(int cpu) +{ +#ifdef CONFIG_NO_HZ + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + + rdtp->dynticks_nesting = 1; + rdtp->dynticks |= 1; /* need consecutive #s even for hotplug. */ + rdtp->dynticks_nmi = (rdtp->dynticks_nmi + 1) & ~0x1; +#endif /* #ifdef CONFIG_NO_HZ */ + rcu_init_percpu_data(cpu, &rcu_state); + rcu_init_percpu_data(cpu, &rcu_bh_state); + open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); +} + +/* + * Handle CPU online/offline notifcation events. + */ +static int __cpuinit rcu_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + long cpu = (long)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + rcu_online_cpu(cpu); + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + rcu_offline_cpu(cpu); + break; + default: + break; + } + return NOTIFY_OK; +} + +/* + * Compute the per-level fanout, either using the exact fanout specified + * or balancing the tree, depending on CONFIG_RCU_FANOUT_EXACT. + */ +#ifdef CONFIG_RCU_FANOUT_EXACT +static void __init rcu_init_levelspread(struct rcu_state *rsp) +{ + int i; + + for (i = NUM_RCU_LVLS - 1; i >= 0; i--) + rsp->levelspread[i] = CONFIG_RCU_FANOUT; +} +#else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ +static void __init rcu_init_levelspread(struct rcu_state *rsp) +{ + int ccur; + int cprv; + int i; + + cprv = NR_CPUS; + for (i = NUM_RCU_LVLS - 1; i >= 0; i--) { + ccur = rsp->levelcnt[i]; + rsp->levelspread[i] = (cprv + ccur - 1) / ccur; + cprv = ccur; + } +} +#endif /* #else #ifdef CONFIG_RCU_FANOUT_EXACT */ + +/* + * Helper function for rcu_init() that initializes one rcu_state structure. + */ +static void __init rcu_init_one(struct rcu_state *rsp) +{ + int cpustride = 1; + int i; + int j; + struct rcu_node *rnp; + + /* Initialize the level-tracking arrays. */ + + for (i = 1; i < NUM_RCU_LVLS; i++) + rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1]; + rcu_init_levelspread(rsp); + + /* Initialize the elements themselves, starting from the leaves. */ + + for (i = NUM_RCU_LVLS - 1; i >= 0; i--) { + cpustride *= rsp->levelspread[i]; + rnp = rsp->level[i]; + for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) { + spin_lock_init(&rnp->lock); + rnp->qsmask = 0; + rnp->qsmaskinit = 0; + rnp->grplo = j * cpustride; + rnp->grphi = (j + 1) * cpustride - 1; + if (rnp->grphi >= NR_CPUS) + rnp->grphi = NR_CPUS - 1; + if (i == 0) { + rnp->grpnum = 0; + rnp->grpmask = 0; + rnp->parent = NULL; + } else { + rnp->grpnum = j % rsp->levelspread[i - 1]; + rnp->grpmask = 1UL << rnp->grpnum; + rnp->parent = rsp->level[i - 1] + + j / rsp->levelspread[i - 1]; + } + rnp->level = i; + } + } +} + +/* + * Helper macro for __rcu_init(). To be used nowhere else! + * Assigns leaf node pointers into each CPU's rcu_data structure. + */ +#define RCU_DATA_PTR_INIT(rsp, rcu_data) \ +do { \ + rnp = (rsp)->level[NUM_RCU_LVLS - 1]; \ + j = 0; \ + for_each_possible_cpu(i) { \ + if (i > rnp[j].grphi) \ + j++; \ + per_cpu(rcu_data, i).mynode = &rnp[j]; \ + (rsp)->rda[i] = &per_cpu(rcu_data, i); \ + } \ +} while (0) + +static struct notifier_block __cpuinitdata rcu_nb = { + .notifier_call = rcu_cpu_notify, +}; + +void __init __rcu_init(void) +{ + int i; /* All used by RCU_DATA_PTR_INIT(). */ + int j; + struct rcu_node *rnp; + + printk(KERN_WARNING "Experimental hierarchical RCU implementation.\n"); +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n"); +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + rcu_init_one(&rcu_state); + RCU_DATA_PTR_INIT(&rcu_state, rcu_data); + rcu_init_one(&rcu_bh_state); + RCU_DATA_PTR_INIT(&rcu_bh_state, rcu_bh_data); + + for_each_online_cpu(i) + rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i); + /* Register notifier for non-boot CPUs */ + register_cpu_notifier(&rcu_nb); + printk(KERN_WARNING "Experimental hierarchical RCU init done.\n"); +} + +module_param(blimit, int, 0); +module_param(qhimark, int, 0); +module_param(qlowmark, int, 0); diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c new file mode 100644 index 000000000000..d6db3e837826 --- /dev/null +++ b/kernel/rcutree_trace.c @@ -0,0 +1,271 @@ +/* + * Read-Copy Update tracing for classic implementation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2008 + * + * Papers: http://www.rdrop.com/users/paulmck/RCU + * + * For detailed explanation of Read-Copy Update mechanism see - + * Documentation/RCU + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) +{ + if (!rdp->beenonline) + return; + seq_printf(m, "%3d%cc=%ld g=%ld pq=%d pqc=%ld qp=%d rpfq=%ld rp=%x", + rdp->cpu, + cpu_is_offline(rdp->cpu) ? '!' : ' ', + rdp->completed, rdp->gpnum, + rdp->passed_quiesc, rdp->passed_quiesc_completed, + rdp->qs_pending, + rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending, + (int)(rdp->n_rcu_pending & 0xffff)); +#ifdef CONFIG_NO_HZ + seq_printf(m, " dt=%d/%d dn=%d df=%lu", + rdp->dynticks->dynticks, + rdp->dynticks->dynticks_nesting, + rdp->dynticks->dynticks_nmi, + rdp->dynticks_fqs); +#endif /* #ifdef CONFIG_NO_HZ */ + seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi); + seq_printf(m, " ql=%ld b=%ld\n", rdp->qlen, rdp->blimit); +} + +#define PRINT_RCU_DATA(name, func, m) \ + do { \ + int _p_r_d_i; \ + \ + for_each_possible_cpu(_p_r_d_i) \ + func(m, &per_cpu(name, _p_r_d_i)); \ + } while (0) + +static int show_rcudata(struct seq_file *m, void *unused) +{ + seq_puts(m, "rcu:\n"); + PRINT_RCU_DATA(rcu_data, print_one_rcu_data, m); + seq_puts(m, "rcu_bh:\n"); + PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data, m); + return 0; +} + +static int rcudata_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_rcudata, NULL); +} + +static struct file_operations rcudata_fops = { + .owner = THIS_MODULE, + .open = rcudata_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) +{ + if (!rdp->beenonline) + return; + seq_printf(m, "%d,%s,%ld,%ld,%d,%ld,%d,%ld,%ld", + rdp->cpu, + cpu_is_offline(rdp->cpu) ? "\"Y\"" : "\"N\"", + rdp->completed, rdp->gpnum, + rdp->passed_quiesc, rdp->passed_quiesc_completed, + rdp->qs_pending, + rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending, + rdp->n_rcu_pending); +#ifdef CONFIG_NO_HZ + seq_printf(m, ",%d,%d,%d,%lu", + rdp->dynticks->dynticks, + rdp->dynticks->dynticks_nesting, + rdp->dynticks->dynticks_nmi, + rdp->dynticks_fqs); +#endif /* #ifdef CONFIG_NO_HZ */ + seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi); + seq_printf(m, ",%ld,%ld\n", rdp->qlen, rdp->blimit); +} + +static int show_rcudata_csv(struct seq_file *m, void *unused) +{ + seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pqc\",\"pq\",\"rpfq\",\"rp\","); +#ifdef CONFIG_NO_HZ + seq_puts(m, "\"dt\",\"dt nesting\",\"dn\",\"df\","); +#endif /* #ifdef CONFIG_NO_HZ */ + seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\"\n"); + seq_puts(m, "\"rcu:\"\n"); + PRINT_RCU_DATA(rcu_data, print_one_rcu_data_csv, m); + seq_puts(m, "\"rcu_bh:\"\n"); + PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data_csv, m); + return 0; +} + +static int rcudata_csv_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_rcudata_csv, NULL); +} + +static struct file_operations rcudata_csv_fops = { + .owner = THIS_MODULE, + .open = rcudata_csv_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) +{ + int level = 0; + struct rcu_node *rnp; + + seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x " + "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n", + rsp->completed, rsp->gpnum, rsp->signaled, + (long)(rsp->jiffies_force_qs - jiffies), + (int)(jiffies & 0xffff), + rsp->n_force_qs, rsp->n_force_qs_ngp, + rsp->n_force_qs - rsp->n_force_qs_ngp, + rsp->n_force_qs_lh); + for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) { + if (rnp->level != level) { + seq_puts(m, "\n"); + level = rnp->level; + } + seq_printf(m, "%lx/%lx %d:%d ^%d ", + rnp->qsmask, rnp->qsmaskinit, + rnp->grplo, rnp->grphi, rnp->grpnum); + } + seq_puts(m, "\n"); +} + +static int show_rcuhier(struct seq_file *m, void *unused) +{ + seq_puts(m, "rcu:\n"); + print_one_rcu_state(m, &rcu_state); + seq_puts(m, "rcu_bh:\n"); + print_one_rcu_state(m, &rcu_bh_state); + return 0; +} + +static int rcuhier_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_rcuhier, NULL); +} + +static struct file_operations rcuhier_fops = { + .owner = THIS_MODULE, + .open = rcuhier_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int show_rcugp(struct seq_file *m, void *unused) +{ + seq_printf(m, "rcu: completed=%ld gpnum=%ld\n", + rcu_state.completed, rcu_state.gpnum); + seq_printf(m, "rcu_bh: completed=%ld gpnum=%ld\n", + rcu_bh_state.completed, rcu_bh_state.gpnum); + return 0; +} + +static int rcugp_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_rcugp, NULL); +} + +static struct file_operations rcugp_fops = { + .owner = THIS_MODULE, + .open = rcugp_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *rcudir, *datadir, *datadir_csv, *hierdir, *gpdir; +static int __init rcuclassic_trace_init(void) +{ + rcudir = debugfs_create_dir("rcu", NULL); + if (!rcudir) + goto out; + + datadir = debugfs_create_file("rcudata", 0444, rcudir, + NULL, &rcudata_fops); + if (!datadir) + goto free_out; + + datadir_csv = debugfs_create_file("rcudata.csv", 0444, rcudir, + NULL, &rcudata_csv_fops); + if (!datadir_csv) + goto free_out; + + gpdir = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops); + if (!gpdir) + goto free_out; + + hierdir = debugfs_create_file("rcuhier", 0444, rcudir, + NULL, &rcuhier_fops); + if (!hierdir) + goto free_out; + return 0; +free_out: + if (datadir) + debugfs_remove(datadir); + if (datadir_csv) + debugfs_remove(datadir_csv); + if (gpdir) + debugfs_remove(gpdir); + debugfs_remove(rcudir); +out: + return 1; +} + +static void __exit rcuclassic_trace_cleanup(void) +{ + debugfs_remove(datadir); + debugfs_remove(datadir_csv); + debugfs_remove(gpdir); + debugfs_remove(hierdir); + debugfs_remove(rcudir); +} + + +module_init(rcuclassic_trace_init); +module_exit(rcuclassic_trace_cleanup); + +MODULE_AUTHOR("Paul E. McKenney"); +MODULE_DESCRIPTION("Read-Copy Update tracing for hierarchical implementation"); +MODULE_LICENSE("GPL"); diff --git a/kernel/resource.c b/kernel/resource.c index 4337063663ef..e633106b12f6 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -853,6 +853,15 @@ int iomem_map_sanity_check(resource_size_t addr, unsigned long size) if (PFN_DOWN(p->start) <= PFN_DOWN(addr) && PFN_DOWN(p->end) >= PFN_DOWN(addr + size - 1)) continue; + /* + * if a resource is "BUSY", it's not a hardware resource + * but a driver mapping of such a resource; we don't want + * to warn for those; some drivers legitimately map only + * partial hardware resources. (example: vesafb) + */ + if (p->flags & IORESOURCE_BUSY) + continue; + printk(KERN_WARNING "resource map sanity check conflict: " "0x%llx 0x%llx 0x%llx 0x%llx %s\n", (unsigned long long)addr, diff --git a/kernel/sched.c b/kernel/sched.c index 748ff924a290..fff1c4a20b65 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -209,7 +209,6 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) hrtimer_init(&rt_b->rt_period_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); rt_b->rt_period_timer.function = sched_rt_period_timer; - rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; } static inline int rt_bandwidth_enabled(void) @@ -1139,7 +1138,6 @@ static void init_rq_hrtick(struct rq *rq) hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); rq->hrtick_timer.function = hrtick; - rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; } #else /* CONFIG_SCHED_HRTICK */ static inline void hrtick_clear(struct rq *rq) @@ -4192,7 +4190,6 @@ void account_steal_time(struct task_struct *p, cputime_t steal) if (p == rq->idle) { p->stime = cputime_add(p->stime, steal); - account_group_system_time(p, steal); if (atomic_read(&rq->nr_iowait) > 0) cpustat->iowait = cputime64_add(cpustat->iowait, tmp); else @@ -4328,7 +4325,7 @@ void __kprobes sub_preempt_count(int val) /* * Underflow? */ - if (DEBUG_LOCKS_WARN_ON(val > preempt_count())) + if (DEBUG_LOCKS_WARN_ON(val > preempt_count() - (!!kernel_locked()))) return; /* * Is the spinlock portion underflowing? diff --git a/kernel/softirq.c b/kernel/softirq.c index e7c69a720d69..466e75ce271a 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -102,20 +102,6 @@ void local_bh_disable(void) EXPORT_SYMBOL(local_bh_disable); -void __local_bh_enable(void) -{ - WARN_ON_ONCE(in_irq()); - - /* - * softirqs should never be enabled by __local_bh_enable(), - * it always nests inside local_bh_enable() sections: - */ - WARN_ON_ONCE(softirq_count() == SOFTIRQ_OFFSET); - - sub_preempt_count(SOFTIRQ_OFFSET); -} -EXPORT_SYMBOL_GPL(__local_bh_enable); - /* * Special-case - softirqs can safely be enabled in * cond_resched_softirq(), or by __do_softirq(), @@ -269,6 +255,7 @@ void irq_enter(void) { int cpu = smp_processor_id(); + rcu_irq_enter(); if (idle_cpu(cpu) && !in_interrupt()) { __irq_enter(); tick_check_idle(cpu); @@ -295,9 +282,9 @@ void irq_exit(void) #ifdef CONFIG_NO_HZ /* Make sure that timer wheel updates are propagated */ - if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched()) - tick_nohz_stop_sched_tick(0); rcu_irq_exit(); + if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched()) + tick_nohz_stop_sched_tick(0); #endif preempt_enable_no_resched(); } diff --git a/kernel/softlockup.c b/kernel/softlockup.c index dc0b3be6b7d5..1ab790c67b17 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -164,7 +164,7 @@ unsigned long __read_mostly sysctl_hung_task_check_count = 1024; /* * Zero means infinite timeout - no checking done: */ -unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120; +unsigned long __read_mostly sysctl_hung_task_timeout_secs = 480; unsigned long __read_mostly sysctl_hung_task_warnings = 10; diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c index 94b527ef1d1e..eb212f8f8bc8 100644 --- a/kernel/stacktrace.c +++ b/kernel/stacktrace.c @@ -6,6 +6,7 @@ * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> */ #include <linux/sched.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/stacktrace.h> @@ -24,3 +25,13 @@ void print_stack_trace(struct stack_trace *trace, int spaces) } EXPORT_SYMBOL_GPL(print_stack_trace); +/* + * Architectures that do not implement save_stack_trace_tsk get this + * weak alias and a once-per-bootup warning (whenever this facility + * is utilized - for example by procfs): + */ +__weak void +save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n"); +} diff --git a/kernel/sys.c b/kernel/sys.c index ebe65c2c9873..d356d79e84ac 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -907,8 +907,8 @@ void do_sys_times(struct tms *tms) struct task_cputime cputime; cputime_t cutime, cstime; - spin_lock_irq(¤t->sighand->siglock); thread_group_cputime(current, &cputime); + spin_lock_irq(¤t->sighand->siglock); cutime = current->signal->cutime; cstime = current->signal->cstime; spin_unlock_irq(¤t->sighand->siglock); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0b627d9c93d8..ff6d45c7626f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -121,6 +121,10 @@ extern int sg_big_buff; #include <asm/system.h> #endif +#ifdef CONFIG_SPARC64 +extern int sysctl_tsb_ratio; +#endif + #ifdef __hppa__ extern int pwrsw_enabled; extern int unaligned_enabled; @@ -451,6 +455,16 @@ static struct ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif +#ifdef CONFIG_SPARC64 + { + .ctl_name = CTL_UNNUMBERED, + .procname = "tsb-ratio", + .data = &sysctl_tsb_ratio, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif #ifdef __hppa__ { .ctl_name = KERN_HPPA_PWRSW, diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 8ff15e5d486b..f5f793d92415 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -131,7 +131,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) { enum hrtimer_restart res = HRTIMER_NORESTART; - write_seqlock_irq(&xtime_lock); + write_seqlock(&xtime_lock); switch (time_state) { case TIME_OK: @@ -164,7 +164,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) } update_vsyscall(&xtime, clock); - write_sequnlock_irq(&xtime_lock); + write_sequnlock(&xtime_lock); return res; } diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 342fc9ccab46..8f3fc2582d38 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -247,7 +247,7 @@ void tick_nohz_stop_sched_tick(int inidle) if (need_resched()) goto end; - if (unlikely(local_softirq_pending())) { + if (unlikely(local_softirq_pending() && cpu_online(cpu))) { static int ratelimit; if (ratelimit < 10) { @@ -282,8 +282,31 @@ void tick_nohz_stop_sched_tick(int inidle) /* Schedule the tick, if we are at least one jiffie off */ if ((long)delta_jiffies >= 1) { + /* + * calculate the expiry time for the next timer wheel + * timer + */ + expires = ktime_add_ns(last_update, tick_period.tv64 * + delta_jiffies); + + /* + * If this cpu is the one which updates jiffies, then + * give up the assignment and let it be taken by the + * cpu which runs the tick timer next, which might be + * this cpu as well. If we don't drop this here the + * jiffies might be stale and do_timer() never + * invoked. + */ + if (cpu == tick_do_timer_cpu) + tick_do_timer_cpu = TICK_DO_TIMER_NONE; + if (delta_jiffies > 1) cpu_set(cpu, nohz_cpu_mask); + + /* Skip reprogram of event if its not changed */ + if (ts->tick_stopped && ktime_equal(expires, dev->next_event)) + goto out; + /* * nohz_stop_sched_tick can be called several times before * the nohz_restart_sched_tick is called. This happens when @@ -306,17 +329,6 @@ void tick_nohz_stop_sched_tick(int inidle) rcu_enter_nohz(); } - /* - * If this cpu is the one which updates jiffies, then - * give up the assignment and let it be taken by the - * cpu which runs the tick timer next, which might be - * this cpu as well. If we don't drop this here the - * jiffies might be stale and do_timer() never - * invoked. - */ - if (cpu == tick_do_timer_cpu) - tick_do_timer_cpu = TICK_DO_TIMER_NONE; - ts->idle_sleeps++; /* @@ -332,12 +344,7 @@ void tick_nohz_stop_sched_tick(int inidle) goto out; } - /* - * calculate the expiry time for the next timer wheel - * timer - */ - expires = ktime_add_ns(last_update, tick_period.tv64 * - delta_jiffies); + /* Mark expiries */ ts->idle_expires = expires; if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { @@ -681,7 +688,6 @@ void tick_setup_sched_timer(void) */ hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); ts->sched_timer.function = tick_sched_timer; - ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; /* Get the next period (per cpu) */ hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 76f34c0ef29c..1d601a7c4587 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -69,6 +69,7 @@ void tracing_on(void) { set_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags); } +EXPORT_SYMBOL_GPL(tracing_on); /** * tracing_off - turn off all tracing buffers @@ -82,6 +83,7 @@ void tracing_off(void) { clear_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags); } +EXPORT_SYMBOL_GPL(tracing_off); /** * tracing_off_permanent - permanently disable ring buffers @@ -111,12 +113,14 @@ u64 ring_buffer_time_stamp(int cpu) return time; } +EXPORT_SYMBOL_GPL(ring_buffer_time_stamp); void ring_buffer_normalize_time_stamp(int cpu, u64 *ts) { /* Just stupid testing the normalize function and deltas */ *ts >>= DEBUG_SHIFT; } +EXPORT_SYMBOL_GPL(ring_buffer_normalize_time_stamp); #define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) #define RB_ALIGNMENT_SHIFT 2 @@ -166,6 +170,7 @@ unsigned ring_buffer_event_length(struct ring_buffer_event *event) { return rb_event_length(event); } +EXPORT_SYMBOL_GPL(ring_buffer_event_length); /* inline for ring buffer fast paths */ static inline void * @@ -187,6 +192,7 @@ void *ring_buffer_event_data(struct ring_buffer_event *event) { return rb_event_data(event); } +EXPORT_SYMBOL_GPL(ring_buffer_event_data); #define for_each_buffer_cpu(buffer, cpu) \ for_each_cpu_mask(cpu, buffer->cpumask) @@ -427,7 +433,7 @@ extern int ring_buffer_page_too_big(void); /** * ring_buffer_alloc - allocate a new ring_buffer - * @size: the size in bytes that is needed. + * @size: the size in bytes per cpu that is needed. * @flags: attributes to set for the ring buffer. * * Currently the only flag that is available is the RB_FL_OVERWRITE @@ -490,6 +496,7 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags) kfree(buffer); return NULL; } +EXPORT_SYMBOL_GPL(ring_buffer_alloc); /** * ring_buffer_free - free a ring buffer. @@ -505,6 +512,7 @@ ring_buffer_free(struct ring_buffer *buffer) kfree(buffer); } +EXPORT_SYMBOL_GPL(ring_buffer_free); static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer); @@ -680,6 +688,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) mutex_unlock(&buffer->mutex); return -ENOMEM; } +EXPORT_SYMBOL_GPL(ring_buffer_resize); static inline int rb_null_event(struct ring_buffer_event *event) { @@ -1304,6 +1313,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, ftrace_preempt_enable(resched); return NULL; } +EXPORT_SYMBOL_GPL(ring_buffer_lock_reserve); static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer, struct ring_buffer_event *event) @@ -1350,6 +1360,7 @@ int ring_buffer_unlock_commit(struct ring_buffer *buffer, return 0; } +EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit); /** * ring_buffer_write - write data to the buffer without reserving @@ -1411,6 +1422,7 @@ int ring_buffer_write(struct ring_buffer *buffer, return ret; } +EXPORT_SYMBOL_GPL(ring_buffer_write); static inline int rb_per_cpu_empty(struct ring_buffer_per_cpu *cpu_buffer) { @@ -1437,6 +1449,7 @@ void ring_buffer_record_disable(struct ring_buffer *buffer) { atomic_inc(&buffer->record_disabled); } +EXPORT_SYMBOL_GPL(ring_buffer_record_disable); /** * ring_buffer_record_enable - enable writes to the buffer @@ -1449,6 +1462,7 @@ void ring_buffer_record_enable(struct ring_buffer *buffer) { atomic_dec(&buffer->record_disabled); } +EXPORT_SYMBOL_GPL(ring_buffer_record_enable); /** * ring_buffer_record_disable_cpu - stop all writes into the cpu_buffer @@ -1470,6 +1484,7 @@ void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu) cpu_buffer = buffer->buffers[cpu]; atomic_inc(&cpu_buffer->record_disabled); } +EXPORT_SYMBOL_GPL(ring_buffer_record_disable_cpu); /** * ring_buffer_record_enable_cpu - enable writes to the buffer @@ -1489,6 +1504,7 @@ void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu) cpu_buffer = buffer->buffers[cpu]; atomic_dec(&cpu_buffer->record_disabled); } +EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu); /** * ring_buffer_entries_cpu - get the number of entries in a cpu buffer @@ -1505,6 +1521,7 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu) cpu_buffer = buffer->buffers[cpu]; return cpu_buffer->entries; } +EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu); /** * ring_buffer_overrun_cpu - get the number of overruns in a cpu_buffer @@ -1521,6 +1538,7 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu) cpu_buffer = buffer->buffers[cpu]; return cpu_buffer->overrun; } +EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu); /** * ring_buffer_entries - get the number of entries in a buffer @@ -1543,6 +1561,7 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer) return entries; } +EXPORT_SYMBOL_GPL(ring_buffer_entries); /** * ring_buffer_overrun_cpu - get the number of overruns in buffer @@ -1565,6 +1584,7 @@ unsigned long ring_buffer_overruns(struct ring_buffer *buffer) return overruns; } +EXPORT_SYMBOL_GPL(ring_buffer_overruns); static void rb_iter_reset(struct ring_buffer_iter *iter) { @@ -1600,6 +1620,7 @@ void ring_buffer_iter_reset(struct ring_buffer_iter *iter) rb_iter_reset(iter); spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); } +EXPORT_SYMBOL_GPL(ring_buffer_iter_reset); /** * ring_buffer_iter_empty - check if an iterator has no more to read @@ -1614,6 +1635,7 @@ int ring_buffer_iter_empty(struct ring_buffer_iter *iter) return iter->head_page == cpu_buffer->commit_page && iter->head == rb_commit_index(cpu_buffer); } +EXPORT_SYMBOL_GPL(ring_buffer_iter_empty); static void rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer, @@ -1880,6 +1902,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) return NULL; } +EXPORT_SYMBOL_GPL(ring_buffer_peek); static struct ring_buffer_event * rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) @@ -1940,6 +1963,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) return NULL; } +EXPORT_SYMBOL_GPL(ring_buffer_iter_peek); /** * ring_buffer_peek - peek at the next event to be read @@ -2017,6 +2041,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) return event; } +EXPORT_SYMBOL_GPL(ring_buffer_consume); /** * ring_buffer_read_start - start a non consuming read of the buffer @@ -2059,6 +2084,7 @@ ring_buffer_read_start(struct ring_buffer *buffer, int cpu) return iter; } +EXPORT_SYMBOL_GPL(ring_buffer_read_start); /** * ring_buffer_finish - finish reading the iterator of the buffer @@ -2075,6 +2101,7 @@ ring_buffer_read_finish(struct ring_buffer_iter *iter) atomic_dec(&cpu_buffer->record_disabled); kfree(iter); } +EXPORT_SYMBOL_GPL(ring_buffer_read_finish); /** * ring_buffer_read - read the next item in the ring buffer by the iterator @@ -2101,6 +2128,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) return event; } +EXPORT_SYMBOL_GPL(ring_buffer_read); /** * ring_buffer_size - return the size of the ring buffer (in bytes) @@ -2110,6 +2138,7 @@ unsigned long ring_buffer_size(struct ring_buffer *buffer) { return BUF_PAGE_SIZE * buffer->pages; } +EXPORT_SYMBOL_GPL(ring_buffer_size); static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) @@ -2156,6 +2185,7 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu) spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); } +EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); /** * ring_buffer_reset - reset a ring buffer @@ -2168,6 +2198,7 @@ void ring_buffer_reset(struct ring_buffer *buffer) for_each_buffer_cpu(buffer, cpu) ring_buffer_reset_cpu(buffer, cpu); } +EXPORT_SYMBOL_GPL(ring_buffer_reset); /** * rind_buffer_empty - is the ring buffer empty? @@ -2186,6 +2217,7 @@ int ring_buffer_empty(struct ring_buffer *buffer) } return 1; } +EXPORT_SYMBOL_GPL(ring_buffer_empty); /** * ring_buffer_empty_cpu - is a cpu buffer of a ring buffer empty? @@ -2202,6 +2234,7 @@ int ring_buffer_empty_cpu(struct ring_buffer *buffer, int cpu) cpu_buffer = buffer->buffers[cpu]; return rb_per_cpu_empty(cpu_buffer); } +EXPORT_SYMBOL_GPL(ring_buffer_empty_cpu); /** * ring_buffer_swap_cpu - swap a CPU buffer between two ring buffers @@ -2250,6 +2283,7 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a, return 0; } +EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu); static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_data_page *bpage) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index f4bb3800318b..4185d5221633 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -30,7 +30,6 @@ #include <linux/gfp.h> #include <linux/fs.h> #include <linux/kprobes.h> -#include <linux/seq_file.h> #include <linux/writeback.h> #include <linux/stacktrace.h> @@ -1310,7 +1309,7 @@ enum trace_file_type { TRACE_FILE_ANNOTATE = 2, }; -static void trace_iterator_increment(struct trace_iterator *iter, int cpu) +static void trace_iterator_increment(struct trace_iterator *iter) { /* Don't allow ftrace to trace into the ring buffers */ ftrace_disable_cpu(); @@ -1389,7 +1388,7 @@ static void *find_next_entry_inc(struct trace_iterator *iter) iter->ent = __find_next_entry(iter, &iter->cpu, &iter->ts); if (iter->ent) - trace_iterator_increment(iter, iter->cpu); + trace_iterator_increment(iter); return iter->ent ? iter : NULL; } diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index 01becf1f19ff..a5779bd975db 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c @@ -202,7 +202,6 @@ static void start_stack_timer(int cpu) hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer->function = stack_trace_timer_fn; - hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index b0f239e443bc..2e75478e9c69 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -252,6 +252,14 @@ config DEBUG_OBJECTS_TIMERS timer routines to track the life time of timer objects and validate the timer operations. +config DEBUG_OBJECTS_ENABLE_DEFAULT + int "debug_objects bootup default value (0-1)" + range 0 1 + default "1" + depends on DEBUG_OBJECTS + help + Debug objects boot parameter default value + config DEBUG_SLAB bool "Debug slab memory allocations" depends on DEBUG_KERNEL && SLAB @@ -545,6 +553,16 @@ config DEBUG_SG If unsure, say N. +config DEBUG_NOTIFIERS + bool "Debug notifier call chains" + depends on DEBUG_KERNEL + help + Enable this to turn on sanity checking for notifier call chains. + This is most useful for kernel developers to make sure that + modules properly unregister themselves from notifier chains. + This is a relatively cheap check but if you care about maximum + performance, say N. + config FRAME_POINTER bool "Compile the kernel with frame pointers" depends on DEBUG_KERNEL && \ @@ -619,6 +637,19 @@ config RCU_CPU_STALL_DETECTOR Say N if you are unsure. +config RCU_CPU_STALL_DETECTOR + bool "Check for stalled CPUs delaying RCU grace periods" + depends on CLASSIC_RCU || TREE_RCU + default n + help + This option causes RCU to printk information on which + CPUs are delaying the current grace period, but only when + the grace period extends for excessive time periods. + + Say Y if you want RCU to perform such checks. + + Say N if you are unsure. + config KPROBES_SANITY_TEST bool "Kprobes sanity tests" depends on DEBUG_KERNEL @@ -699,6 +730,7 @@ config FAULT_INJECTION config FAILSLAB bool "Fault-injection capability for kmalloc" depends on FAULT_INJECTION + depends on SLAB || SLUB help Provide fault-injection capability for kmalloc. diff --git a/lib/debugobjects.c b/lib/debugobjects.c index e3ab374e1334..5d99be1fd988 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -45,7 +45,9 @@ static struct kmem_cache *obj_cache; static int debug_objects_maxchain __read_mostly; static int debug_objects_fixups __read_mostly; static int debug_objects_warnings __read_mostly; -static int debug_objects_enabled __read_mostly; +static int debug_objects_enabled __read_mostly + = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT; + static struct debug_obj_descr *descr_test __read_mostly; static int __init enable_object_debug(char *str) diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 5f6c629a924d..fa2dc4e5f9ba 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -21,9 +21,12 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/spinlock.h> +#include <linux/swiotlb.h> #include <linux/string.h> +#include <linux/swiotlb.h> #include <linux/types.h> #include <linux/ctype.h> +#include <linux/highmem.h> #include <asm/io.h> #include <asm/dma.h> @@ -36,22 +39,6 @@ #define OFFSET(val,align) ((unsigned long) \ ( (val) & ( (align) - 1))) -#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg))) -#define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) - -/* - * Maximum allowable number of contiguous slabs to map, - * must be a power of 2. What is the appropriate value ? - * The complexity of {map,unmap}_single is linearly dependent on this value. - */ -#define IO_TLB_SEGSIZE 128 - -/* - * log of the size of each IO TLB slab. The number of slabs is command line - * controllable. - */ -#define IO_TLB_SHIFT 11 - #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT)) /* @@ -102,7 +89,10 @@ static unsigned int io_tlb_index; * We need to save away the original address corresponding to a mapped entry * for the sync operations. */ -static unsigned char **io_tlb_orig_addr; +static struct swiotlb_phys_addr { + struct page *page; + unsigned int offset; +} *io_tlb_orig_addr; /* * Protect the above data structures in the map and unmap calls @@ -126,6 +116,72 @@ setup_io_tlb_npages(char *str) __setup("swiotlb=", setup_io_tlb_npages); /* make io_tlb_overflow tunable too? */ +void * __weak swiotlb_alloc_boot(size_t size, unsigned long nslabs) +{ + return alloc_bootmem_low_pages(size); +} + +void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs) +{ + return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order); +} + +dma_addr_t __weak swiotlb_phys_to_bus(phys_addr_t paddr) +{ + return paddr; +} + +phys_addr_t __weak swiotlb_bus_to_phys(dma_addr_t baddr) +{ + return baddr; +} + +static dma_addr_t swiotlb_virt_to_bus(volatile void *address) +{ + return swiotlb_phys_to_bus(virt_to_phys(address)); +} + +static void *swiotlb_bus_to_virt(dma_addr_t address) +{ + return phys_to_virt(swiotlb_bus_to_phys(address)); +} + +int __weak swiotlb_arch_range_needs_mapping(void *ptr, size_t size) +{ + return 0; +} + +static dma_addr_t swiotlb_sg_to_bus(struct scatterlist *sg) +{ + return swiotlb_phys_to_bus(page_to_phys(sg_page(sg)) + sg->offset); +} + +static void swiotlb_print_info(unsigned long bytes) +{ + phys_addr_t pstart, pend; + dma_addr_t bstart, bend; + + pstart = virt_to_phys(io_tlb_start); + pend = virt_to_phys(io_tlb_end); + + bstart = swiotlb_phys_to_bus(pstart); + bend = swiotlb_phys_to_bus(pend); + + printk(KERN_INFO "Placing %luMB software IO TLB between %p - %p\n", + bytes >> 20, io_tlb_start, io_tlb_end); + if (pstart != bstart || pend != bend) + printk(KERN_INFO "software IO TLB at phys %#llx - %#llx" + " bus %#llx - %#llx\n", + (unsigned long long)pstart, + (unsigned long long)pend, + (unsigned long long)bstart, + (unsigned long long)bend); + else + printk(KERN_INFO "software IO TLB at phys %#llx - %#llx\n", + (unsigned long long)pstart, + (unsigned long long)pend); +} + /* * Statically reserve bounce buffer space and initialize bounce buffer data * structures for the software IO TLB used to implement the DMA API. @@ -145,7 +201,7 @@ swiotlb_init_with_default_size(size_t default_size) /* * Get IO TLB memory from the low pages */ - io_tlb_start = alloc_bootmem_low_pages(bytes); + io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs); if (!io_tlb_start) panic("Cannot allocate SWIOTLB buffer"); io_tlb_end = io_tlb_start + bytes; @@ -159,7 +215,7 @@ swiotlb_init_with_default_size(size_t default_size) for (i = 0; i < io_tlb_nslabs; i++) io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_index = 0; - io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); + io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr)); /* * Get the overflow emergency buffer @@ -168,8 +224,7 @@ swiotlb_init_with_default_size(size_t default_size) if (!io_tlb_overflow_buffer) panic("Cannot allocate SWIOTLB overflow buffer!\n"); - printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", - virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); + swiotlb_print_info(bytes); } void __init @@ -202,8 +257,7 @@ swiotlb_late_init_with_default_size(size_t default_size) bytes = io_tlb_nslabs << IO_TLB_SHIFT; while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { - io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN, - order); + io_tlb_start = swiotlb_alloc(order, io_tlb_nslabs); if (io_tlb_start) break; order--; @@ -235,12 +289,12 @@ swiotlb_late_init_with_default_size(size_t default_size) io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_index = 0; - io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL, - get_order(io_tlb_nslabs * sizeof(char *))); + io_tlb_orig_addr = (struct swiotlb_phys_addr *)__get_free_pages(GFP_KERNEL, + get_order(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr))); if (!io_tlb_orig_addr) goto cleanup3; - memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *)); + memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(struct swiotlb_phys_addr)); /* * Get the overflow emergency buffer @@ -250,9 +304,7 @@ swiotlb_late_init_with_default_size(size_t default_size) if (!io_tlb_overflow_buffer) goto cleanup4; - printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " - "0x%lx\n", bytes >> 20, - virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); + swiotlb_print_info(bytes); return 0; @@ -279,16 +331,69 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size) return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size); } +static inline int range_needs_mapping(void *ptr, size_t size) +{ + return swiotlb_force || swiotlb_arch_range_needs_mapping(ptr, size); +} + static int is_swiotlb_buffer(char *addr) { return addr >= io_tlb_start && addr < io_tlb_end; } +static struct swiotlb_phys_addr swiotlb_bus_to_phys_addr(char *dma_addr) +{ + int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; + struct swiotlb_phys_addr buffer = io_tlb_orig_addr[index]; + buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1); + buffer.page += buffer.offset >> PAGE_SHIFT; + buffer.offset &= PAGE_SIZE - 1; + return buffer; +} + +static void +__sync_single(struct swiotlb_phys_addr buffer, char *dma_addr, size_t size, int dir) +{ + if (PageHighMem(buffer.page)) { + size_t len, bytes; + char *dev, *host, *kmp; + + len = size; + while (len != 0) { + unsigned long flags; + + bytes = len; + if ((bytes + buffer.offset) > PAGE_SIZE) + bytes = PAGE_SIZE - buffer.offset; + local_irq_save(flags); /* protects KM_BOUNCE_READ */ + kmp = kmap_atomic(buffer.page, KM_BOUNCE_READ); + dev = dma_addr + size - len; + host = kmp + buffer.offset; + if (dir == DMA_FROM_DEVICE) + memcpy(host, dev, bytes); + else + memcpy(dev, host, bytes); + kunmap_atomic(kmp, KM_BOUNCE_READ); + local_irq_restore(flags); + len -= bytes; + buffer.page++; + buffer.offset = 0; + } + } else { + void *v = page_address(buffer.page) + buffer.offset; + + if (dir == DMA_TO_DEVICE) + memcpy(dma_addr, v, size); + else + memcpy(v, dma_addr, size); + } +} + /* * Allocates bounce buffer and returns its kernel virtual address. */ static void * -map_single(struct device *hwdev, char *buffer, size_t size, int dir) +map_single(struct device *hwdev, struct swiotlb_phys_addr buffer, size_t size, int dir) { unsigned long flags; char *dma_addr; @@ -298,11 +403,16 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir) unsigned long mask; unsigned long offset_slots; unsigned long max_slots; + struct swiotlb_phys_addr slot_buf; mask = dma_get_seg_boundary(hwdev); - start_dma_addr = virt_to_bus(io_tlb_start) & mask; + start_dma_addr = swiotlb_virt_to_bus(io_tlb_start) & mask; offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; + + /* + * Carefully handle integer overflow which can occur when mask == ~0UL. + */ max_slots = mask + 1 ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT); @@ -378,10 +488,15 @@ found: * This is needed when we sync the memory. Then we sync the buffer if * needed. */ - for (i = 0; i < nslots; i++) - io_tlb_orig_addr[index+i] = buffer + (i << IO_TLB_SHIFT); + slot_buf = buffer; + for (i = 0; i < nslots; i++) { + slot_buf.page += slot_buf.offset >> PAGE_SHIFT; + slot_buf.offset &= PAGE_SIZE - 1; + io_tlb_orig_addr[index+i] = slot_buf; + slot_buf.offset += 1 << IO_TLB_SHIFT; + } if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) - memcpy(dma_addr, buffer, size); + __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); return dma_addr; } @@ -395,17 +510,17 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir) unsigned long flags; int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; - char *buffer = io_tlb_orig_addr[index]; + struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr); /* * First, sync the memory before unmapping the entry */ - if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) /* * bounce... copy the data back into the original buffer * and * delete the bounce buffer. */ - memcpy(buffer, dma_addr, size); + __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); /* * Return the buffer to the free list by setting the corresponding @@ -437,21 +552,18 @@ static void sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir, int target) { - int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; - char *buffer = io_tlb_orig_addr[index]; - - buffer += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1)); + struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr); switch (target) { case SYNC_FOR_CPU: if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) - memcpy(buffer, dma_addr, size); + __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); else BUG_ON(dir != DMA_TO_DEVICE); break; case SYNC_FOR_DEVICE: if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) - memcpy(dma_addr, buffer, size); + __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); else BUG_ON(dir != DMA_FROM_DEVICE); break; @@ -473,7 +585,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, dma_mask = hwdev->coherent_dma_mask; ret = (void *)__get_free_pages(flags, order); - if (ret && !is_buffer_dma_capable(dma_mask, virt_to_bus(ret), size)) { + if (ret && !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(ret), size)) { /* * The allocated memory isn't reachable by the device. * Fall back on swiotlb_map_single(). @@ -488,13 +600,16 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, * swiotlb_map_single(), which will grab memory from * the lowest available address range. */ - ret = map_single(hwdev, NULL, size, DMA_FROM_DEVICE); + struct swiotlb_phys_addr buffer; + buffer.page = virt_to_page(NULL); + buffer.offset = 0; + ret = map_single(hwdev, buffer, size, DMA_FROM_DEVICE); if (!ret) return NULL; } memset(ret, 0, size); - dev_addr = virt_to_bus(ret); + dev_addr = swiotlb_virt_to_bus(ret); /* Confirm address can be DMA'd by device */ if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) { @@ -554,8 +669,9 @@ dma_addr_t swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size, int dir, struct dma_attrs *attrs) { - dma_addr_t dev_addr = virt_to_bus(ptr); + dma_addr_t dev_addr = swiotlb_virt_to_bus(ptr); void *map; + struct swiotlb_phys_addr buffer; BUG_ON(dir == DMA_NONE); /* @@ -563,19 +679,22 @@ swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size, * we can safely return the device addr and not worry about bounce * buffering it. */ - if (!address_needs_mapping(hwdev, dev_addr, size) && !swiotlb_force) + if (!address_needs_mapping(hwdev, dev_addr, size) && + !range_needs_mapping(ptr, size)) return dev_addr; /* * Oh well, have to allocate and map a bounce buffer. */ - map = map_single(hwdev, ptr, size, dir); + buffer.page = virt_to_page(ptr); + buffer.offset = (unsigned long)ptr & ~PAGE_MASK; + map = map_single(hwdev, buffer, size, dir); if (!map) { swiotlb_full(hwdev, size, dir, 1); map = io_tlb_overflow_buffer; } - dev_addr = virt_to_bus(map); + dev_addr = swiotlb_virt_to_bus(map); /* * Ensure that the address returned is DMA'ble @@ -605,7 +724,7 @@ void swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir, struct dma_attrs *attrs) { - char *dma_addr = bus_to_virt(dev_addr); + char *dma_addr = swiotlb_bus_to_virt(dev_addr); BUG_ON(dir == DMA_NONE); if (is_swiotlb_buffer(dma_addr)) @@ -635,7 +754,7 @@ static void swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir, int target) { - char *dma_addr = bus_to_virt(dev_addr); + char *dma_addr = swiotlb_bus_to_virt(dev_addr); BUG_ON(dir == DMA_NONE); if (is_swiotlb_buffer(dma_addr)) @@ -666,7 +785,7 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr, unsigned long offset, size_t size, int dir, int target) { - char *dma_addr = bus_to_virt(dev_addr) + offset; + char *dma_addr = swiotlb_bus_to_virt(dev_addr) + offset; BUG_ON(dir == DMA_NONE); if (is_swiotlb_buffer(dma_addr)) @@ -714,18 +833,20 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, int dir, struct dma_attrs *attrs) { struct scatterlist *sg; - void *addr; + struct swiotlb_phys_addr buffer; dma_addr_t dev_addr; int i; BUG_ON(dir == DMA_NONE); for_each_sg(sgl, sg, nelems, i) { - addr = SG_ENT_VIRT_ADDRESS(sg); - dev_addr = virt_to_bus(addr); - if (swiotlb_force || + dev_addr = swiotlb_sg_to_bus(sg); + if (range_needs_mapping(sg_virt(sg), sg->length) || address_needs_mapping(hwdev, dev_addr, sg->length)) { - void *map = map_single(hwdev, addr, sg->length, dir); + void *map; + buffer.page = sg_page(sg); + buffer.offset = sg->offset; + map = map_single(hwdev, buffer, sg->length, dir); if (!map) { /* Don't panic here, we expect map_sg users to do proper error handling. */ @@ -735,7 +856,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, sgl[0].dma_length = 0; return 0; } - sg->dma_address = virt_to_bus(map); + sg->dma_address = swiotlb_virt_to_bus(map); } else sg->dma_address = dev_addr; sg->dma_length = sg->length; @@ -765,11 +886,11 @@ swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, BUG_ON(dir == DMA_NONE); for_each_sg(sgl, sg, nelems, i) { - if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - unmap_single(hwdev, bus_to_virt(sg->dma_address), + if (sg->dma_address != swiotlb_sg_to_bus(sg)) + unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address), sg->dma_length, dir); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); + dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length); } } EXPORT_SYMBOL(swiotlb_unmap_sg_attrs); @@ -798,11 +919,11 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl, BUG_ON(dir == DMA_NONE); for_each_sg(sgl, sg, nelems, i) { - if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - sync_single(hwdev, bus_to_virt(sg->dma_address), + if (sg->dma_address != swiotlb_sg_to_bus(sg)) + sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address), sg->dma_length, dir, target); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); + dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length); } } @@ -823,7 +944,7 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr) { - return (dma_addr == virt_to_bus(io_tlb_overflow_buffer)); + return (dma_addr == swiotlb_virt_to_bus(io_tlb_overflow_buffer)); } /* @@ -835,7 +956,7 @@ swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr) int swiotlb_dma_supported(struct device *hwdev, u64 mask) { - return virt_to_bus(io_tlb_end - 1) <= mask; + return swiotlb_virt_to_bus(io_tlb_end - 1) <= mask; } EXPORT_SYMBOL(swiotlb_map_single); diff --git a/mm/Makefile b/mm/Makefile index c06b45a1ff5f..51c27709cc7c 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o obj-$(CONFIG_SLAB) += slab.o obj-$(CONFIG_SLUB) += slub.o +obj-$(CONFIG_FAILSLAB) += failslab.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o obj-$(CONFIG_FS_XIP) += filemap_xip.o obj-$(CONFIG_MIGRATION) += migrate.o diff --git a/mm/bounce.c b/mm/bounce.c index bf0cf7c8387b..e590272fe7a8 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -198,8 +198,13 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, /* * irk, bounce it */ - if (!bio) - bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt); + if (!bio) { + unsigned int cnt = (*bio_orig)->bi_vcnt; + + bio = bio_alloc(GFP_NOIO, cnt); + memset(bio->bi_io_vec, 0, cnt * sizeof(struct bio_vec)); + } + to = bio->bi_io_vec + i; diff --git a/mm/failslab.c b/mm/failslab.c new file mode 100644 index 000000000000..7c6ea6493f80 --- /dev/null +++ b/mm/failslab.c @@ -0,0 +1,59 @@ +#include <linux/fault-inject.h> + +static struct { + struct fault_attr attr; + u32 ignore_gfp_wait; +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + struct dentry *ignore_gfp_wait_file; +#endif +} failslab = { + .attr = FAULT_ATTR_INITIALIZER, + .ignore_gfp_wait = 1, +}; + +bool should_failslab(size_t size, gfp_t gfpflags) +{ + if (gfpflags & __GFP_NOFAIL) + return false; + + if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT)) + return false; + + return should_fail(&failslab.attr, size); +} + +static int __init setup_failslab(char *str) +{ + return setup_fault_attr(&failslab.attr, str); +} +__setup("failslab=", setup_failslab); + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + +static int __init failslab_debugfs_init(void) +{ + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + int err; + + err = init_fault_attr_dentries(&failslab.attr, "failslab"); + if (err) + return err; + dir = failslab.attr.dentries.dir; + + failslab.ignore_gfp_wait_file = + debugfs_create_bool("ignore-gfp-wait", mode, dir, + &failslab.ignore_gfp_wait); + + if (!failslab.ignore_gfp_wait_file) { + err = -ENOMEM; + debugfs_remove(failslab.ignore_gfp_wait_file); + cleanup_fault_attr_dentries(&failslab.attr); + } + + return err; +} + +late_initcall(failslab_debugfs_init); + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ diff --git a/mm/memory.c b/mm/memory.c index f01b7eed6e16..0a2010a9518c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3075,3 +3075,18 @@ void print_vma_addr(char *prefix, unsigned long ip) } up_read(¤t->mm->mmap_sem); } + +#ifdef CONFIG_PROVE_LOCKING +void might_fault(void) +{ + might_sleep(); + /* + * it would be nicer only to annotate paths which are not under + * pagefault_disable, however that requires a larger audit and + * providing helpers like get_user_atomic. + */ + if (!in_atomic() && current->mm) + might_lock_read(¤t->mm->mmap_sem); +} +EXPORT_SYMBOL(might_fault); +#endif diff --git a/mm/slab.c b/mm/slab.c index 09187517f9dc..f97e564bdf11 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2123,6 +2123,8 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep) * * @name must be valid until the cache is destroyed. This implies that * the module calling this has to destroy the cache before getting unloaded. + * Note that kmem_cache_name() is not guaranteed to return the same pointer, + * therefore applications must manage it themselves. * * The flags are * @@ -2609,7 +2611,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp, if (OFF_SLAB(cachep)) { /* Slab management obj is off-slab. */ slabp = kmem_cache_alloc_node(cachep->slabp_cache, - local_flags & ~GFP_THISNODE, nodeid); + local_flags, nodeid); if (!slabp) return NULL; } else { @@ -2997,7 +2999,7 @@ retry: * there must be at least one object available for * allocation. */ - BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num); + BUG_ON(slabp->inuse >= cachep->num); while (slabp->inuse < cachep->num && batchcount--) { STATS_INC_ALLOCED(cachep); @@ -3106,79 +3108,14 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) #endif -#ifdef CONFIG_FAILSLAB - -static struct failslab_attr { - - struct fault_attr attr; - - u32 ignore_gfp_wait; -#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS - struct dentry *ignore_gfp_wait_file; -#endif - -} failslab = { - .attr = FAULT_ATTR_INITIALIZER, - .ignore_gfp_wait = 1, -}; - -static int __init setup_failslab(char *str) -{ - return setup_fault_attr(&failslab.attr, str); -} -__setup("failslab=", setup_failslab); - -static int should_failslab(struct kmem_cache *cachep, gfp_t flags) +static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) { if (cachep == &cache_cache) - return 0; - if (flags & __GFP_NOFAIL) - return 0; - if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT)) - return 0; + return false; - return should_fail(&failslab.attr, obj_size(cachep)); + return should_failslab(obj_size(cachep), flags); } -#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS - -static int __init failslab_debugfs(void) -{ - mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; - struct dentry *dir; - int err; - - err = init_fault_attr_dentries(&failslab.attr, "failslab"); - if (err) - return err; - dir = failslab.attr.dentries.dir; - - failslab.ignore_gfp_wait_file = - debugfs_create_bool("ignore-gfp-wait", mode, dir, - &failslab.ignore_gfp_wait); - - if (!failslab.ignore_gfp_wait_file) { - err = -ENOMEM; - debugfs_remove(failslab.ignore_gfp_wait_file); - cleanup_fault_attr_dentries(&failslab.attr); - } - - return err; -} - -late_initcall(failslab_debugfs); - -#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ - -#else /* CONFIG_FAILSLAB */ - -static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags) -{ - return 0; -} - -#endif /* CONFIG_FAILSLAB */ - static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; @@ -3381,7 +3318,7 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, unsigned long save_flags; void *ptr; - if (should_failslab(cachep, flags)) + if (slab_should_failslab(cachep, flags)) return NULL; cache_alloc_debugcheck_before(cachep, flags); @@ -3457,7 +3394,7 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) unsigned long save_flags; void *objp; - if (should_failslab(cachep, flags)) + if (slab_should_failslab(cachep, flags)) return NULL; cache_alloc_debugcheck_before(cachep, flags); @@ -3686,9 +3623,9 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) EXPORT_SYMBOL(__kmalloc_node); void *__kmalloc_node_track_caller(size_t size, gfp_t flags, - int node, void *caller) + int node, unsigned long caller) { - return __do_kmalloc_node(size, flags, node, caller); + return __do_kmalloc_node(size, flags, node, (void *)caller); } EXPORT_SYMBOL(__kmalloc_node_track_caller); #else @@ -3730,9 +3667,9 @@ void *__kmalloc(size_t size, gfp_t flags) } EXPORT_SYMBOL(__kmalloc); -void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller) +void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller) { - return __do_kmalloc(size, flags, caller); + return __do_kmalloc(size, flags, (void *)caller); } EXPORT_SYMBOL(__kmalloc_track_caller); diff --git a/mm/slub.c b/mm/slub.c index a2cd47d89e0a..6cb7ad107852 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -24,6 +24,7 @@ #include <linux/kallsyms.h> #include <linux/memory.h> #include <linux/math64.h> +#include <linux/fault-inject.h> /* * Lock order: @@ -153,6 +154,10 @@ #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long) #endif +#define OO_SHIFT 16 +#define OO_MASK ((1 << OO_SHIFT) - 1) +#define MAX_OBJS_PER_PAGE 65535 /* since page.objects is u16 */ + /* Internal SLUB flags */ #define __OBJECT_POISON 0x80000000 /* Poison object */ #define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */ @@ -178,7 +183,7 @@ static LIST_HEAD(slab_caches); * Tracking user of a slab. */ struct track { - void *addr; /* Called from address */ + unsigned long addr; /* Called from address */ int cpu; /* Was running on cpu */ int pid; /* Pid context */ unsigned long when; /* When did the operation occur */ @@ -290,7 +295,7 @@ static inline struct kmem_cache_order_objects oo_make(int order, unsigned long size) { struct kmem_cache_order_objects x = { - (order << 16) + (PAGE_SIZE << order) / size + (order << OO_SHIFT) + (PAGE_SIZE << order) / size }; return x; @@ -298,12 +303,12 @@ static inline struct kmem_cache_order_objects oo_make(int order, static inline int oo_order(struct kmem_cache_order_objects x) { - return x.x >> 16; + return x.x >> OO_SHIFT; } static inline int oo_objects(struct kmem_cache_order_objects x) { - return x.x & ((1 << 16) - 1); + return x.x & OO_MASK; } #ifdef CONFIG_SLUB_DEBUG @@ -367,7 +372,7 @@ static struct track *get_track(struct kmem_cache *s, void *object, } static void set_track(struct kmem_cache *s, void *object, - enum track_item alloc, void *addr) + enum track_item alloc, unsigned long addr) { struct track *p; @@ -391,8 +396,8 @@ static void init_tracking(struct kmem_cache *s, void *object) if (!(s->flags & SLAB_STORE_USER)) return; - set_track(s, object, TRACK_FREE, NULL); - set_track(s, object, TRACK_ALLOC, NULL); + set_track(s, object, TRACK_FREE, 0UL); + set_track(s, object, TRACK_ALLOC, 0UL); } static void print_track(const char *s, struct track *t) @@ -401,7 +406,7 @@ static void print_track(const char *s, struct track *t) return; printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n", - s, t->addr, jiffies - t->when, t->cpu, t->pid); + s, (void *)t->addr, jiffies - t->when, t->cpu, t->pid); } static void print_tracking(struct kmem_cache *s, void *object) @@ -692,7 +697,7 @@ static int check_object(struct kmem_cache *s, struct page *page, if (!check_valid_pointer(s, page, get_freepointer(s, p))) { object_err(s, page, p, "Freepointer corrupt"); /* - * No choice but to zap it and thus loose the remainder + * No choice but to zap it and thus lose the remainder * of the free objects in this slab. May cause * another error because the object count is now wrong. */ @@ -764,8 +769,8 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) } max_objects = (PAGE_SIZE << compound_order(page)) / s->size; - if (max_objects > 65535) - max_objects = 65535; + if (max_objects > MAX_OBJS_PER_PAGE) + max_objects = MAX_OBJS_PER_PAGE; if (page->objects != max_objects) { slab_err(s, page, "Wrong number of objects. Found %d but " @@ -866,7 +871,7 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page, } static int alloc_debug_processing(struct kmem_cache *s, struct page *page, - void *object, void *addr) + void *object, unsigned long addr) { if (!check_slab(s, page)) goto bad; @@ -906,7 +911,7 @@ bad: } static int free_debug_processing(struct kmem_cache *s, struct page *page, - void *object, void *addr) + void *object, unsigned long addr) { if (!check_slab(s, page)) goto fail; @@ -1029,10 +1034,10 @@ static inline void setup_object_debug(struct kmem_cache *s, struct page *page, void *object) {} static inline int alloc_debug_processing(struct kmem_cache *s, - struct page *page, void *object, void *addr) { return 0; } + struct page *page, void *object, unsigned long addr) { return 0; } static inline int free_debug_processing(struct kmem_cache *s, - struct page *page, void *object, void *addr) { return 0; } + struct page *page, void *object, unsigned long addr) { return 0; } static inline int slab_pad_check(struct kmem_cache *s, struct page *page) { return 1; } @@ -1499,8 +1504,8 @@ static inline int node_match(struct kmem_cache_cpu *c, int node) * we need to allocate a new slab. This is the slowest path since it involves * a call to the page allocator and the setup of a new slab. */ -static void *__slab_alloc(struct kmem_cache *s, - gfp_t gfpflags, int node, void *addr, struct kmem_cache_cpu *c) +static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, + unsigned long addr, struct kmem_cache_cpu *c) { void **object; struct page *new; @@ -1584,13 +1589,18 @@ debug: * Otherwise we can simply pick the next object from the lockless free list. */ static __always_inline void *slab_alloc(struct kmem_cache *s, - gfp_t gfpflags, int node, void *addr) + gfp_t gfpflags, int node, unsigned long addr) { void **object; struct kmem_cache_cpu *c; unsigned long flags; unsigned int objsize; + might_sleep_if(gfpflags & __GFP_WAIT); + + if (should_failslab(s->objsize, gfpflags)) + return NULL; + local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); objsize = c->objsize; @@ -1613,14 +1623,14 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) { - return slab_alloc(s, gfpflags, -1, __builtin_return_address(0)); + return slab_alloc(s, gfpflags, -1, _RET_IP_); } EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_NUMA void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) { - return slab_alloc(s, gfpflags, node, __builtin_return_address(0)); + return slab_alloc(s, gfpflags, node, _RET_IP_); } EXPORT_SYMBOL(kmem_cache_alloc_node); #endif @@ -1634,7 +1644,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node); * handling required then we can return immediately. */ static void __slab_free(struct kmem_cache *s, struct page *page, - void *x, void *addr, unsigned int offset) + void *x, unsigned long addr, unsigned int offset) { void *prior; void **object = (void *)x; @@ -1704,7 +1714,7 @@ debug: * with all sorts of special processing. */ static __always_inline void slab_free(struct kmem_cache *s, - struct page *page, void *x, void *addr) + struct page *page, void *x, unsigned long addr) { void **object = (void *)x; struct kmem_cache_cpu *c; @@ -1731,11 +1741,11 @@ void kmem_cache_free(struct kmem_cache *s, void *x) page = virt_to_head_page(x); - slab_free(s, page, x, __builtin_return_address(0)); + slab_free(s, page, x, _RET_IP_); } EXPORT_SYMBOL(kmem_cache_free); -/* Figure out on which slab object the object resides */ +/* Figure out on which slab page the object resides */ static struct page *get_object_page(const void *x) { struct page *page = virt_to_head_page(x); @@ -1807,8 +1817,8 @@ static inline int slab_order(int size, int min_objects, int rem; int min_order = slub_min_order; - if ((PAGE_SIZE << min_order) / size > 65535) - return get_order(size * 65535) - 1; + if ((PAGE_SIZE << min_order) / size > MAX_OBJS_PER_PAGE) + return get_order(size * MAX_OBJS_PER_PAGE) - 1; for (order = max(min_order, fls(min_objects * size - 1) - PAGE_SHIFT); @@ -2073,8 +2083,7 @@ static inline int alloc_kmem_cache_cpus(struct kmem_cache *s, gfp_t flags) * when allocating for the kmalloc_node_cache. This is used for bootstrapping * memory on a fresh node that has no slab structures yet. */ -static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags, - int node) +static void early_kmem_cache_node_alloc(gfp_t gfpflags, int node) { struct page *page; struct kmem_cache_node *n; @@ -2112,7 +2121,6 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags, local_irq_save(flags); add_partial(n, page, 0); local_irq_restore(flags); - return n; } static void free_kmem_cache_nodes(struct kmem_cache *s) @@ -2144,8 +2152,7 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags) n = &s->local_node; else { if (slab_state == DOWN) { - n = early_kmem_cache_node_alloc(gfpflags, - node); + early_kmem_cache_node_alloc(gfpflags, node); continue; } n = kmem_cache_alloc_node(kmalloc_caches, @@ -2659,7 +2666,7 @@ void *__kmalloc(size_t size, gfp_t flags) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - return slab_alloc(s, flags, -1, __builtin_return_address(0)); + return slab_alloc(s, flags, -1, _RET_IP_); } EXPORT_SYMBOL(__kmalloc); @@ -2687,7 +2694,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - return slab_alloc(s, flags, node, __builtin_return_address(0)); + return slab_alloc(s, flags, node, _RET_IP_); } EXPORT_SYMBOL(__kmalloc_node); #endif @@ -2744,7 +2751,7 @@ void kfree(const void *x) put_page(page); return; } - slab_free(page->slab, page, object, __builtin_return_address(0)); + slab_free(page->slab, page, object, _RET_IP_); } EXPORT_SYMBOL(kfree); @@ -3123,8 +3130,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); up_write(&slub_lock); - if (sysfs_slab_alias(s, name)) + if (sysfs_slab_alias(s, name)) { + down_write(&slub_lock); + s->refcount--; + up_write(&slub_lock); goto err; + } return s; } @@ -3134,8 +3145,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size, align, flags, ctor)) { list_add(&s->list, &slab_caches); up_write(&slub_lock); - if (sysfs_slab_add(s)) + if (sysfs_slab_add(s)) { + down_write(&slub_lock); + list_del(&s->list); + up_write(&slub_lock); + kfree(s); goto err; + } return s; } kfree(s); @@ -3202,7 +3218,7 @@ static struct notifier_block __cpuinitdata slab_notifier = { #endif -void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller) +void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller) { struct kmem_cache *s; @@ -3218,7 +3234,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller) } void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, - int node, void *caller) + int node, unsigned long caller) { struct kmem_cache *s; @@ -3429,7 +3445,7 @@ static void resiliency_test(void) {}; struct location { unsigned long count; - void *addr; + unsigned long addr; long long sum_time; long min_time; long max_time; @@ -3477,7 +3493,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s, { long start, end, pos; struct location *l; - void *caddr; + unsigned long caddr; unsigned long age = jiffies - track->when; start = -1; @@ -4345,7 +4361,7 @@ static void sysfs_slab_remove(struct kmem_cache *s) /* * Need to buffer aliases during bootup until sysfs becomes - * available lest we loose that information. + * available lest we lose that information. */ struct saved_alias { struct kmem_cache *s; diff --git a/net/core/dev.c b/net/core/dev.c index 446424027d24..09c66a449da6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5066,13 +5066,14 @@ static struct pernet_operations __net_initdata netdev_net_ops = { static void __net_exit default_device_exit(struct net *net) { - struct net_device *dev, *next; + struct net_device *dev; /* * Push all migratable of the network devices back to the * initial network namespace */ rtnl_lock(); - for_each_netdev_safe(net, dev, next) { +restart: + for_each_netdev(net, dev) { int err; char fb_name[IFNAMSIZ]; @@ -5083,7 +5084,7 @@ static void __net_exit default_device_exit(struct net *net) /* Delete virtual devices */ if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) { dev->rtnl_link_ops->dellink(dev); - continue; + goto restart; } /* Push remaing network devices to init_net */ @@ -5094,6 +5095,7 @@ static void __net_exit default_device_exit(struct net *net) __func__, dev->name, err); BUG(); } + goto restart; } rtnl_unlock(); } diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9c3717a23cf7..f66c58df8953 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2414,7 +2414,7 @@ static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; @@ -2429,7 +2429,7 @@ static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos) struct neigh_table *tbl = pde->data; int cpu; - for (cpu = *pos; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index d5c2bacb713c..1747ccae8e8d 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -964,7 +964,6 @@ adjudge_to_death: state = sk->sk_state; sock_hold(sk); sock_orphan(sk); - percpu_counter_inc(sk->sk_prot->orphan_count); /* * It is the last release_sock in its life. It will remove backlog. @@ -978,6 +977,8 @@ adjudge_to_death: bh_lock_sock(sk); WARN_ON(sock_owned_by_user(sk)); + percpu_counter_inc(sk->sk_prot->orphan_count); + /* Have we already been destroyed by a softirq or backlog? */ if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) goto out; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index c7cda1ca8e65..f26ab38680de 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -633,8 +633,6 @@ void inet_csk_listen_stop(struct sock *sk) acc_req = req->dl_next; - percpu_counter_inc(sk->sk_prot->orphan_count); - local_bh_disable(); bh_lock_sock(child); WARN_ON(sock_owned_by_user(child)); @@ -644,6 +642,8 @@ void inet_csk_listen_stop(struct sock *sk) sock_orphan(child); + percpu_counter_inc(sk->sk_prot->orphan_count); + inet_csk_destroy_sock(child); bh_unlock_sock(child); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 313ebf00ee36..6ba5c557690c 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -291,7 +291,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; @@ -306,7 +306,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) struct net *net = seq_file_net(seq); int cpu; - for (cpu = *pos; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 614958b7c276..eb62e58bff79 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -38,6 +38,7 @@ #include <net/tcp.h> #include <net/udp.h> #include <net/udplite.h> +#include <linux/bottom_half.h> #include <linux/inetdevice.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> @@ -50,13 +51,17 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) { struct net *net = seq->private; + int orphans, sockets; + + local_bh_disable(); + orphans = percpu_counter_sum_positive(&tcp_orphan_count), + sockets = percpu_counter_sum_positive(&tcp_sockets_allocated), + local_bh_enable(); socket_seq_show(seq); seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n", - sock_prot_inuse_get(net, &tcp_prot), - (int)percpu_counter_sum_positive(&tcp_orphan_count), - tcp_death_row.tw_count, - (int)percpu_counter_sum_positive(&tcp_sockets_allocated), + sock_prot_inuse_get(net, &tcp_prot), orphans, + tcp_death_row.tw_count, sockets, atomic_read(&tcp_memory_allocated)); seq_printf(seq, "UDP: inuse %d mem %d\n", sock_prot_inuse_get(net, &udp_prot), diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 77bfba975959..97f71153584f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -429,7 +429,7 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; @@ -442,7 +442,7 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) { int cpu; - for (cpu = *pos; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu+1; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1f3d52946b3b..f28acf11fc67 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1836,7 +1836,6 @@ adjudge_to_death: state = sk->sk_state; sock_hold(sk); sock_orphan(sk); - percpu_counter_inc(sk->sk_prot->orphan_count); /* It is the last release_sock in its life. It will remove backlog. */ release_sock(sk); @@ -1849,6 +1848,8 @@ adjudge_to_death: bh_lock_sock(sk); WARN_ON(sock_owned_by_user(sk)); + percpu_counter_inc(sk->sk_prot->orphan_count); + /* Have we already been destroyed by a softirq or backlog? */ if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) goto out; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 10172487921b..9d839fa9331e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -51,6 +51,7 @@ */ +#include <linux/bottom_half.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/module.h> @@ -1797,7 +1798,9 @@ static int tcp_v4_init_sock(struct sock *sk) sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; + local_bh_disable(); percpu_counter_inc(&tcp_sockets_allocated); + local_bh_enable(); return 0; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8702b06cb60a..e8b8337a8310 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -23,6 +23,7 @@ * 2 of the License, or (at your option) any later version. */ +#include <linux/bottom_half.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/types.h> @@ -1830,7 +1831,9 @@ static int tcp_v6_init_sock(struct sock *sk) sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; + local_bh_disable(); percpu_counter_inc(&tcp_sockets_allocated); + local_bh_enable(); return 0; } diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 9394f539966a..3eb5e2660c49 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -507,7 +507,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) /* No cache entry or it is invalid, time to schedule */ dest = __ip_vs_lblc_schedule(svc); if (!dest) { - IP_VS_DBG(1, "no destination available\n"); + IP_VS_ERR_RL("LBLC: no destination available\n"); return NULL; } diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 92dc76a6842c..c04ce56c7f0f 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -690,7 +690,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) /* The cache entry is invalid, time to schedule */ dest = __ip_vs_lblcr_schedule(svc); if (!dest) { - IP_VS_DBG(1, "no destination available\n"); + IP_VS_ERR_RL("LBLCR: no destination available\n"); read_unlock(&svc->sched_lock); return NULL; } diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c index 51912cab777b..d0dadc8a65fd 100644 --- a/net/netfilter/ipvs/ip_vs_lc.c +++ b/net/netfilter/ipvs/ip_vs_lc.c @@ -66,11 +66,15 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) } } - if (least) - IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d inactconns %d\n", - IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), - atomic_read(&least->activeconns), - atomic_read(&least->inactconns)); + if (!least) + IP_VS_ERR_RL("LC: no destination available\n"); + else + IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d " + "inactconns %d\n", + IP_VS_DBG_ADDR(svc->af, &least->addr), + ntohs(least->port), + atomic_read(&least->activeconns), + atomic_read(&least->inactconns)); return least; } diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c index 6758ad2ceaaf..694952db5026 100644 --- a/net/netfilter/ipvs/ip_vs_nq.c +++ b/net/netfilter/ipvs/ip_vs_nq.c @@ -95,8 +95,10 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) } } - if (!least) + if (!least) { + IP_VS_ERR_RL("NQ: no destination available\n"); return NULL; + } out: IP_VS_DBG_BUF(6, "NQ: server %s:%u " diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c index 8fb51c169eb8..2d16ab7f8c1e 100644 --- a/net/netfilter/ipvs/ip_vs_rr.c +++ b/net/netfilter/ipvs/ip_vs_rr.c @@ -69,6 +69,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) q = q->next; } while (q != p); write_unlock(&svc->sched_lock); + IP_VS_ERR_RL("RR: no destination available\n"); return NULL; out: diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c index 691a6a0086e1..20e4657d2f3b 100644 --- a/net/netfilter/ipvs/ip_vs_sed.c +++ b/net/netfilter/ipvs/ip_vs_sed.c @@ -84,6 +84,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) goto nextstage; } } + IP_VS_ERR_RL("SED: no destination available\n"); return NULL; /* diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index 0e53955ef139..75709ebeb630 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c @@ -219,6 +219,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) || !(dest->flags & IP_VS_DEST_F_AVAILABLE) || atomic_read(&dest->weight) <= 0 || is_overloaded(dest)) { + IP_VS_ERR_RL("SH: no destination available\n"); return NULL; } diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c index 57b452bbb4ea..8e942565b47d 100644 --- a/net/netfilter/ipvs/ip_vs_wlc.c +++ b/net/netfilter/ipvs/ip_vs_wlc.c @@ -72,6 +72,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) goto nextstage; } } + IP_VS_ERR_RL("WLC: no destination available\n"); return NULL; /* diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c index 2f618dc29c5b..f7d74ef1ecf9 100644 --- a/net/netfilter/ipvs/ip_vs_wrr.c +++ b/net/netfilter/ipvs/ip_vs_wrr.c @@ -155,6 +155,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) if (mark->cl == mark->cl->next) { /* no dest entry */ + IP_VS_ERR_RL("WRR: no destination available: " + "no destinations present\n"); dest = NULL; goto out; } @@ -168,8 +170,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) */ if (mark->cw == 0) { mark->cl = &svc->destinations; - IP_VS_ERR_RL("ip_vs_wrr_schedule(): " - "no available servers\n"); + IP_VS_ERR_RL("WRR: no destination " + "available\n"); dest = NULL; goto out; } @@ -191,6 +193,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) /* back to the start, and no dest is found. It is only possible when all dests are OVERLOADED */ dest = NULL; + IP_VS_ERR_RL("WRR: no destination available: " + "all destinations are overloaded\n"); goto out; } } diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index f37b9b74c6a8..4da54b0b9233 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -200,7 +200,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu + 1; @@ -215,7 +215,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) struct net *net = seq_file_net(seq); int cpu; - for (cpu = *pos; cpu < NR_CPUS; ++cpu) { + for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu + 1; diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 4f7ef0db302b..929218a47620 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -335,9 +335,6 @@ config NET_CLS_CGROUP Say Y here if you want to classify packets based on the control cgroup of their process. - To compile this code as a module, choose M here: the - module will be called cls_cgroup. - config NET_EMATCH bool "Extended Matches" select NET_CLS diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 0d68b1975983..91a3db4a76f8 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -24,10 +24,16 @@ struct cgroup_cls_state u32 classid; }; -static inline struct cgroup_cls_state *net_cls_state(struct cgroup *cgrp) +static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp) { - return (struct cgroup_cls_state *) - cgroup_subsys_state(cgrp, net_cls_subsys_id); + return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id), + struct cgroup_cls_state, css); +} + +static inline struct cgroup_cls_state *task_cls_state(struct task_struct *p) +{ + return container_of(task_subsys_state(p, net_cls_subsys_id), + struct cgroup_cls_state, css); } static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, @@ -39,19 +45,19 @@ static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, return ERR_PTR(-ENOMEM); if (cgrp->parent) - cs->classid = net_cls_state(cgrp->parent)->classid; + cs->classid = cgrp_cls_state(cgrp->parent)->classid; return &cs->css; } static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp) { - kfree(ss); + kfree(cgrp_cls_state(cgrp)); } static u64 read_classid(struct cgroup *cgrp, struct cftype *cft) { - return net_cls_state(cgrp)->classid; + return cgrp_cls_state(cgrp)->classid; } static int write_classid(struct cgroup *cgrp, struct cftype *cft, u64 value) @@ -59,7 +65,7 @@ static int write_classid(struct cgroup *cgrp, struct cftype *cft, u64 value) if (!cgroup_lock_live_group(cgrp)) return -ENODEV; - net_cls_state(cgrp)->classid = (u32) value; + cgrp_cls_state(cgrp)->classid = (u32) value; cgroup_unlock(); @@ -115,8 +121,7 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp, return -1; rcu_read_lock(); - cs = (struct cgroup_cls_state *) task_subsys_state(current, - net_cls_subsys_id); + cs = task_cls_state(current); if (cs->classid && tcf_em_tree_match(skb, &head->ematches, NULL)) { res->classid = cs->classid; res->class = 0; diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index 284eaef1dbf2..a2adb51849a9 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -44,27 +44,14 @@ static struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_SENTINEL }; -static unsigned long -fold_field(void *mib[], int offt) -{ - unsigned long res = 0; - int i; - - for_each_possible_cpu(i) { - res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); - res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); - } - return res; -} - static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) { struct net *net = seq->private; int i; for (i=0; xfrm_mib_list[i].name; i++) seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, - fold_field((void **)net->mib.xfrm_statistics, - xfrm_mib_list[i].entry)); + snmp_fold_field((void **)net->mib.xfrm_statistics, + xfrm_mib_list[i].entry)); return 0; } diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 7c72baa02f2e..6688765bd8b9 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -838,11 +838,11 @@ static long get_instantiation_keyring(key_serial_t ringid, { key_ref_t dkref; + *_dest_keyring = NULL; + /* just return a NULL pointer if we weren't asked to make a link */ - if (ringid == 0) { - *_dest_keyring = NULL; + if (ringid == 0) return 0; - } /* if a specific keyring is nominated by ID, then use that */ if (ringid > 0) { diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 34c1d94f921e..ef6539eea579 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -22,7 +22,7 @@ #include <asm/irq.h> #include <mach/hardware.h> -#include <mach/pxa-regs.h> +#include <mach/regs-ac97.h> #include <mach/pxa2xx-gpio.h> #include <mach/audio.h> diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index c2635beb4c88..85cf591d4e11 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -22,6 +22,7 @@ #include <mach/hardware.h> #include <mach/pxa-regs.h> +#include <mach/regs-ac97.h> #include <mach/audio.h> #include "pxa2xx-pcm.h" diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h index 5c4a4d38a083..65f86b56ba42 100644 --- a/sound/arm/pxa2xx-pcm.h +++ b/sound/arm/pxa2xx-pcm.h @@ -9,7 +9,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <asm/dma.h> +#include <mach/dma.h> struct pxa2xx_runtime_data { int dma_ch; diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index c1d285921f80..34c7d48f5061 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -57,7 +57,6 @@ static int snd_hrtimer_open(struct snd_timer *t) return -ENOMEM; hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); stime->timer = t; - stime->hrt.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; stime->hrt.function = snd_hrtimer_callback; t->private_data = stime; return 0; diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 2a02f704f366..a4049eb94d35 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -96,7 +96,6 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return -EINVAL; hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; pcsp_chip.timer.function = pcsp_do_timer; card = snd_card_new(index, id, THIS_MODULE, 0); diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index c47842fad657..2c63bb9da74a 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c @@ -1483,16 +1483,14 @@ static void __exit unload_waveartist(struct address_info *hw) #define VNC_HANDSET_DETECT 0x40 #define VNC_DISABLE_AUTOSWITCH 0x80 -extern spinlock_t gpio_lock; - static inline void vnc_mute_spkr(wavnc_info *devc) { unsigned long flags; - spin_lock_irqsave(&gpio_lock, flags); - cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE); - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE); + spin_unlock_irqrestore(&nw_gpio_lock, flags); } static void diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 780db6757ad2..812c2b4d3e07 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -21,6 +21,7 @@ #include <mach/hardware.h> #include <mach/pxa-regs.h> +#include <mach/regs-ac97.h> #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c index 1bfce40bb2e4..5822d2dd49ba 100644 --- a/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/sound/soc/s3c24xx/s3c2443-ac97.c @@ -28,7 +28,7 @@ #include <sound/soc.h> #include <mach/hardware.h> -#include <asm/plat-s3c/regs-ac97.h> +#include <plat/regs-ac97.h> #include <mach/regs-gpio.h> #include <mach/regs-clock.h> #include <mach/audio.h> |