mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
Merge commit 'v2.6.28-rc2' into tracing/urgent
This commit is contained in:
commit
4944dd62de
11
CREDITS
11
CREDITS
@ -598,6 +598,11 @@ S: Tamsui town, Taipei county,
|
||||
S: Taiwan 251
|
||||
S: Republic of China
|
||||
|
||||
N: Reinette Chatre
|
||||
E: reinette.chatre@intel.com
|
||||
D: WiMedia Link Protocol implementation
|
||||
D: UWB stack bits and pieces
|
||||
|
||||
N: Michael Elizabeth Chastain
|
||||
E: mec@shout.net
|
||||
D: Configure, Menuconfig, xconfig
|
||||
@ -2695,6 +2700,12 @@ S: Demonstratsii 8-382
|
||||
S: Tula 300000
|
||||
S: Russia
|
||||
|
||||
N: Inaky Perez-Gonzalez
|
||||
E: inaky.perez-gonzalez@intel.com
|
||||
D: UWB stack, HWA-RC driver and HWA-HC drivers
|
||||
D: Wireless USB additions to the USB stack
|
||||
D: WiMedia Link Protocol bits and pieces
|
||||
|
||||
N: Gordon Peters
|
||||
E: GordPeters@smarttech.com
|
||||
D: Isochronous receive for IEEE 1394 driver (OHCI module).
|
||||
|
28
Documentation/ABI/testing/sysfs-bus-umc
Normal file
28
Documentation/ABI/testing/sysfs-bus-umc
Normal file
@ -0,0 +1,28 @@
|
||||
What: /sys/bus/umc/
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The Wireless Host Controller Interface (WHCI)
|
||||
specification describes a PCI-based device with
|
||||
multiple capabilities; the UWB Multi-interface
|
||||
Controller (UMC).
|
||||
|
||||
The umc bus presents each of the individual
|
||||
capabilties as a device.
|
||||
|
||||
What: /sys/bus/umc/devices/.../capability_id
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The ID of this capability, with 0 being the radio
|
||||
controller capability.
|
||||
|
||||
What: /sys/bus/umc/devices/.../version
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The specification version this capability's hardware
|
||||
interface complies with.
|
@ -101,3 +101,46 @@ Description:
|
||||
Users:
|
||||
USB PM tool
|
||||
git://git.moblin.org/users/sarah/usb-pm-tool/
|
||||
|
||||
What: /sys/bus/usb/device/.../authorized
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.26
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
Authorized devices are available for use by device
|
||||
drivers, non-authorized one are not. By default, wired
|
||||
USB devices are authorized.
|
||||
|
||||
Certified Wireless USB devices are not authorized
|
||||
initially and should be (by writing 1) after the
|
||||
device has been authenticated.
|
||||
|
||||
What: /sys/bus/usb/device/.../wusb_cdid
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
For Certified Wireless USB devices only.
|
||||
|
||||
A devices's CDID, as 16 space-separated hex octets.
|
||||
|
||||
What: /sys/bus/usb/device/.../wusb_ck
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
For Certified Wireless USB devices only.
|
||||
|
||||
Write the device's connection key (CK) to start the
|
||||
authentication of the device. The CK is 16
|
||||
space-separated hex octets.
|
||||
|
||||
What: /sys/bus/usb/device/.../wusb_disconnect
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
For Certified Wireless USB devices only.
|
||||
|
||||
Write a 1 to force the device to disconnect
|
||||
(equivalent to unplugging a wired USB device).
|
||||
|
25
Documentation/ABI/testing/sysfs-class-usb_host
Normal file
25
Documentation/ABI/testing/sysfs-class-usb_host
Normal file
@ -0,0 +1,25 @@
|
||||
What: /sys/class/usb_host/usb_hostN/wusb_chid
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
Write the CHID (16 space-separated hex octets) for this host controller.
|
||||
This starts the host controller, allowing it to accept connection from
|
||||
WUSB devices.
|
||||
|
||||
Set an all zero CHID to stop the host controller.
|
||||
|
||||
What: /sys/class/usb_host/usb_hostN/wusb_trust_timeout
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
Devices that haven't sent a WUSB packet to the host
|
||||
within 'wusb_trust_timeout' ms are considered to have
|
||||
disconnected and are removed. The default value of
|
||||
4000 ms is the value required by the WUSB
|
||||
specification.
|
||||
|
||||
Since this relates to security (specifically, the
|
||||
lifetime of PTKs and GTKs) it should not be changed
|
||||
from the default.
|
144
Documentation/ABI/testing/sysfs-class-uwb_rc
Normal file
144
Documentation/ABI/testing/sysfs-class-uwb_rc
Normal file
@ -0,0 +1,144 @@
|
||||
What: /sys/class/uwb_rc
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Interfaces for WiMedia Ultra Wideband Common Radio
|
||||
Platform (UWB) radio controllers.
|
||||
|
||||
Familiarity with the ECMA-368 'High Rate Ultra
|
||||
Wideband MAC and PHY Specification' is assumed.
|
||||
|
||||
What: /sys/class/uwb_rc/beacon_timeout_ms
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Description:
|
||||
If no beacons are received from a device for at least
|
||||
this time, the device will be considered to have gone
|
||||
and it will be removed. The default is 3 superframes
|
||||
(~197 ms) as required by the specification.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
An individual UWB radio controller.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/beacon
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Write:
|
||||
|
||||
<channel> [<bpst offset>]
|
||||
|
||||
to start beaconing on a specific channel, or stop
|
||||
beaconing if <channel> is -1. Valid channels depends
|
||||
on the radio controller's supported band groups.
|
||||
|
||||
<bpst offset> may be used to try and join a specific
|
||||
beacon group if more than one was found during a scan.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/scan
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Write:
|
||||
|
||||
<channel> <type> [<bpst offset>]
|
||||
|
||||
to start (or stop) scanning on a channel. <type> is one of:
|
||||
0 - scan
|
||||
1 - scan outside BP
|
||||
2 - scan while inactive
|
||||
3 - scanning disabled
|
||||
4 - scan (with start time of <bpst offset>)
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/mac_address
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
The EUI-48, in colon-separated hex octets, for this
|
||||
radio controller. A write will change the radio
|
||||
controller's EUI-48 but only do so while the device is
|
||||
not beaconing or scanning.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/wusbhc
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
A symlink to the device (if any) of the WUSB Host
|
||||
Controller PAL using this radio controller.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
A neighbour UWB device that has either been detected
|
||||
as part of a scan or is a member of the radio
|
||||
controllers beacon group.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/BPST
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
The time (using the radio controllers internal 1 ms
|
||||
interval superframe timer) of the last beacon from
|
||||
this device was received.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/DevAddr
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
The current DevAddr of this device in colon separated
|
||||
hex octets.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/EUI_48
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
|
||||
The EUI-48 of this device in colon separated hex
|
||||
octets.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/BPST
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/IEs
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
The latest IEs included in this device's beacon, in
|
||||
space separated hex octets with one IE per line.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/LQE
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Link Quality Estimate - the Signal to Noise Ratio
|
||||
(SNR) of all packets received from this device in dB.
|
||||
This gives an estimate on a suitable PHY rate. Refer
|
||||
to [ECMA-368] section 13.3 for more details.
|
||||
|
||||
What: /sys/class/uwb_rc/uwbN/<EUI-48>/RSSI
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Received Signal Strength Indication - the strength of
|
||||
the received signal in dB. LQE is a more useful
|
||||
measure of the radio link quality.
|
100
Documentation/ABI/testing/sysfs-wusb_cbaf
Normal file
100
Documentation/ABI/testing/sysfs-wusb_cbaf
Normal file
@ -0,0 +1,100 @@
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_*
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
Various files for managing Cable Based Association of
|
||||
(wireless) USB devices.
|
||||
|
||||
The sequence of operations should be:
|
||||
|
||||
1. Device is plugged in.
|
||||
|
||||
2. The connection manager (CM) sees a device with CBA capability.
|
||||
(the wusb_chid etc. files in /sys/devices/blah/OURDEVICE).
|
||||
|
||||
3. The CM writes the host name, supported band groups,
|
||||
and the CHID (host ID) into the wusb_host_name,
|
||||
wusb_host_band_groups and wusb_chid files. These
|
||||
get sent to the device and the CDID (if any) for
|
||||
this host is requested.
|
||||
|
||||
4. The CM can verify that the device's supported band
|
||||
groups (wusb_device_band_groups) are compatible
|
||||
with the host.
|
||||
|
||||
5. The CM reads the wusb_cdid file.
|
||||
|
||||
6. The CM looks it up its database.
|
||||
|
||||
- If it has a matching CHID,CDID entry, the device
|
||||
has been authorized before and nothing further
|
||||
needs to be done.
|
||||
|
||||
- If the CDID is zero (or the CM doesn't find a
|
||||
matching CDID in its database), the device is
|
||||
assumed to be not known. The CM may associate
|
||||
the host with device by: writing a randomly
|
||||
generated CDID to wusb_cdid and then a random CK
|
||||
to wusb_ck (this uploads the new CC to the
|
||||
device).
|
||||
|
||||
CMD may choose to prompt the user before
|
||||
associating with a new device.
|
||||
|
||||
7. Device is unplugged.
|
||||
|
||||
References:
|
||||
[WUSB-AM] Association Models Supplement to the
|
||||
Certified Wireless Universal Serial Bus
|
||||
Specification, version 1.0.
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_chid
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The CHID of the host formatted as 16 space-separated
|
||||
hex octets.
|
||||
|
||||
Writes fetches device's supported band groups and the
|
||||
the CDID for any existing association with this host.
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_name
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
A friendly name for the host as a UTF-8 encoded string.
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_band_groups
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The band groups supported by the host, in the format
|
||||
defined in [WUSB-AM].
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_device_band_groups
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The band groups supported by the device, in the format
|
||||
defined in [WUSB-AM].
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_cdid
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
The device's CDID formatted as 16 space-separated hex
|
||||
octets.
|
||||
|
||||
What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_ck
|
||||
Date: August 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: David Vrabel <david.vrabel@csr.com>
|
||||
Description:
|
||||
Write 16 space-separated random, hex octets to
|
||||
associate with the device.
|
@ -359,3 +359,11 @@ Why: The 2.6 kernel supports direct writing to ide CD drives, which
|
||||
eliminates the need for ide-scsi. The new method is more
|
||||
efficient in every way.
|
||||
Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
|
||||
When: 2.6.29 (ideally) or 2.6.30 (more likely)
|
||||
Why: Deprecated by the new (standard) device driver binding model. Use
|
||||
i2c_driver->probe() and ->remove() instead.
|
||||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
@ -8,7 +8,7 @@ Supported chips:
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/pf/LM/LM90.html
|
||||
* National Semiconductor LM89
|
||||
Prefix: 'lm99'
|
||||
Prefix: 'lm89' (no auto-detection)
|
||||
Addresses scanned: I2C 0x4c and 0x4d
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/mpf/LM/LM89.html
|
||||
|
@ -13,8 +13,9 @@ Supported adapters:
|
||||
* Intel 631xESB/632xESB (ESB2)
|
||||
* Intel 82801H (ICH8)
|
||||
* Intel 82801I (ICH9)
|
||||
* Intel Tolapai
|
||||
* Intel ICH10
|
||||
* Intel EP80579 (Tolapai)
|
||||
* Intel 82801JI (ICH10)
|
||||
* Intel PCH
|
||||
Datasheets: Publicly available at the Intel website
|
||||
|
||||
Authors:
|
||||
@ -32,7 +33,7 @@ Description
|
||||
-----------
|
||||
|
||||
The ICH (properly known as the 82801AA), ICH0 (82801AB), ICH2 (82801BA),
|
||||
ICH3 (82801CA/CAM) and later devices are Intel chips that are a part of
|
||||
ICH3 (82801CA/CAM) and later devices (PCH) are Intel chips that are a part of
|
||||
Intel's '810' chipset for Celeron-based PCs, '810E' chipset for
|
||||
Pentium-based PCs, '815E' chipset, and others.
|
||||
|
||||
|
@ -1,160 +0,0 @@
|
||||
Revision 7, 2007-04-19
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Greg KH <greg@kroah.com>
|
||||
|
||||
This is a guide on how to convert I2C chip drivers from Linux 2.4 to
|
||||
Linux 2.6. I have been using existing drivers (lm75, lm78) as examples.
|
||||
Then I converted a driver myself (lm83) and updated this document.
|
||||
Note that this guide is strongly oriented towards hardware monitoring
|
||||
drivers. Many points are still valid for other type of drivers, but
|
||||
others may be irrelevant.
|
||||
|
||||
There are two sets of points below. The first set concerns technical
|
||||
changes. The second set concerns coding policy. Both are mandatory.
|
||||
|
||||
Although reading this guide will help you porting drivers, I suggest
|
||||
you keep an eye on an already ported driver while porting your own
|
||||
driver. This will help you a lot understanding what this guide
|
||||
exactly means. Choose the chip driver that is the more similar to
|
||||
yours for best results.
|
||||
|
||||
Technical changes:
|
||||
|
||||
* [Driver type] Any driver that was relying on i2c-isa has to be
|
||||
converted to a proper isa, platform or pci driver. This is not
|
||||
covered by this guide.
|
||||
|
||||
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||
Includes typically look like that:
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||
#include <linux/err.h> /* for class registration */
|
||||
Please respect this inclusion order. Some extra headers may be
|
||||
required for a given driver (e.g. "lm75.h").
|
||||
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||
are no more handled by the i2c core. Address ranges are no more
|
||||
supported either, define each individual address separately.
|
||||
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
|
||||
|
||||
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||
register values (for example, temp_os becomes temp_max). You're
|
||||
still relatively free here, but you *have* to follow the standard
|
||||
names for sysfs files (see the Sysctl section below).
|
||||
|
||||
* [Function prototypes] The detect functions loses its flags
|
||||
parameter. Sysctl (e.g. lm75_temp) and miscellaneous functions
|
||||
are off the list of prototypes. This usually leaves five
|
||||
prototypes:
|
||||
static int lm75_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int lm75_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind);
|
||||
static void lm75_init_client(struct i2c_client *client);
|
||||
static int lm75_detach_client(struct i2c_client *client);
|
||||
static struct lm75_data lm75_update_device(struct device *dev);
|
||||
|
||||
* [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
|
||||
and functions). Instead, you have to define show and set functions for
|
||||
each sysfs file. Only define set for writable values. Take a look at an
|
||||
existing 2.6 driver for details (it87 for example). Don't forget
|
||||
to define the attributes for each file (this is that step that
|
||||
links callback functions). Use the file names specified in
|
||||
Documentation/hwmon/sysfs-interface for the individual files. Also
|
||||
convert the units these files read and write to the specified ones.
|
||||
If you need to add a new type of file, please discuss it on the
|
||||
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
||||
patch to the Documentation/hwmon/sysfs-interface file.
|
||||
|
||||
* [Attach] The attach function should make sure that the adapter's
|
||||
class has I2C_CLASS_HWMON (or whatever class is suitable for your
|
||||
driver), using the following construct:
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
Call i2c_probe() instead of i2c_detect().
|
||||
|
||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||
The type_name and client_name strings are replaced by a single
|
||||
name string, which will be filled with a lowercase, short string.
|
||||
The labels used for error paths are reduced to the number needed.
|
||||
It is advised that the labels are given descriptive names such as
|
||||
exit and exit_free. Don't forget to properly set err before
|
||||
jumping to error labels. By the way, labels should be left-aligned.
|
||||
Use kzalloc instead of kmalloc.
|
||||
Use i2c_set_clientdata to set the client data (as opposed to
|
||||
a direct access to client->data).
|
||||
Use strlcpy instead of strcpy or snprintf to copy the client name.
|
||||
Replace the sysctl directory registration by calls to
|
||||
device_create_file. Move the driver initialization before any
|
||||
sysfs file creation.
|
||||
Register the client with the hwmon class (using hwmon_device_register)
|
||||
if applicable.
|
||||
Drop client->id.
|
||||
Drop any 24RF08 corruption prevention you find, as this is now done
|
||||
at the i2c-core level, and doing it twice voids it.
|
||||
Don't add I2C_CLIENT_ALLOW_USE to client->flags, it's the default now.
|
||||
|
||||
* [Init] Limits must not be set by the driver (can be done later in
|
||||
user-space). Chip should not be reset default (although a module
|
||||
parameter may be used to force it), and initialization should be
|
||||
limited to the strictly necessary steps.
|
||||
|
||||
* [Detach] Remove the call to i2c_deregister_entry. Do not log an
|
||||
error message if i2c_detach_client fails, as i2c-core will now do
|
||||
it for you.
|
||||
Unregister from the hwmon class if applicable.
|
||||
|
||||
* [Update] The function prototype changed, it is now
|
||||
passed a device structure, which you have to convert to a client
|
||||
using to_i2c_client(dev). The update function should return a
|
||||
pointer to the client data.
|
||||
Don't access client->data directly, use i2c_get_clientdata(client)
|
||||
instead.
|
||||
Use time_after() instead of direct jiffies comparison.
|
||||
|
||||
* [Interface] Make sure there is a MODULE_LICENSE() line, at the bottom
|
||||
of the file (after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this
|
||||
order).
|
||||
|
||||
* [Driver] The flags field of the i2c_driver structure is gone.
|
||||
I2C_DF_NOTIFY is now the default behavior.
|
||||
The i2c_driver structure has a driver member, which is itself a
|
||||
structure, those name member should be initialized to a driver name
|
||||
string. i2c_driver itself has no name member anymore.
|
||||
|
||||
* [Driver model] Instead of shutdown or reboot notifiers, provide a
|
||||
shutdown() method in your driver.
|
||||
|
||||
* [Power management] Use the driver model suspend() and resume()
|
||||
callbacks instead of the obsolete pm_register() calls.
|
||||
|
||||
Coding policy:
|
||||
|
||||
* [Copyright] Use (C), not (c), for copyright.
|
||||
|
||||
* [Debug/log] Get rid of #ifdef DEBUG/#endif constructs whenever you
|
||||
can. Calls to printk for debugging purposes are replaced by calls to
|
||||
dev_dbg where possible, else to pr_debug. Here is an example of how
|
||||
to call it (taken from lm75_detect):
|
||||
dev_dbg(&client->dev, "Starting lm75 update\n");
|
||||
Replace other printk calls with the dev_info, dev_err or dev_warn
|
||||
function, as appropriate.
|
||||
|
||||
* [Constants] Constants defines (registers, conversions) should be
|
||||
aligned. This greatly improves readability.
|
||||
Alignments are achieved by the means of tabs, not spaces. Remember
|
||||
that tabs are set to 8 in the Linux kernel code.
|
||||
|
||||
* [Layout] Avoid extra empty lines between comments and what they
|
||||
comment. Respect the coding style (see Documentation/CodingStyle),
|
||||
in particular when it comes to placing curly braces.
|
||||
|
||||
* [Comments] Make sure that no comment refers to a file that isn't
|
||||
part of the Linux source tree (typically doc/chips/<chip name>),
|
||||
and that remaining comments still match the code. Merging comment
|
||||
lines when possible is encouraged.
|
@ -10,23 +10,21 @@ General remarks
|
||||
===============
|
||||
|
||||
Try to keep the kernel namespace as clean as possible. The best way to
|
||||
do this is to use a unique prefix for all global symbols. This is
|
||||
do this is to use a unique prefix for all global symbols. This is
|
||||
especially important for exported symbols, but it is a good idea to do
|
||||
it for non-exported symbols too. We will use the prefix `foo_' in this
|
||||
tutorial, and `FOO_' for preprocessor variables.
|
||||
tutorial.
|
||||
|
||||
|
||||
The driver structure
|
||||
====================
|
||||
|
||||
Usually, you will implement a single driver structure, and instantiate
|
||||
all clients from it. Remember, a driver structure contains general access
|
||||
all clients from it. Remember, a driver structure contains general access
|
||||
routines, and should be zero-initialized except for fields with data you
|
||||
provide. A client structure holds device-specific information like the
|
||||
driver model device node, and its I2C address.
|
||||
|
||||
/* iff driver uses driver model ("new style") binding model: */
|
||||
|
||||
static struct i2c_device_id foo_idtable[] = {
|
||||
{ "foo", my_id_for_foo },
|
||||
{ "bar", my_id_for_bar },
|
||||
@ -40,7 +38,6 @@ static struct i2c_driver foo_driver = {
|
||||
.name = "foo",
|
||||
},
|
||||
|
||||
/* iff driver uses driver model ("new style") binding model: */
|
||||
.id_table = foo_ids,
|
||||
.probe = foo_probe,
|
||||
.remove = foo_remove,
|
||||
@ -49,24 +46,19 @@ static struct i2c_driver foo_driver = {
|
||||
.detect = foo_detect,
|
||||
.address_data = &addr_data,
|
||||
|
||||
/* else, driver uses "legacy" binding model: */
|
||||
.attach_adapter = foo_attach_adapter,
|
||||
.detach_client = foo_detach_client,
|
||||
|
||||
/* these may be used regardless of the driver binding model */
|
||||
.shutdown = foo_shutdown, /* optional */
|
||||
.suspend = foo_suspend, /* optional */
|
||||
.resume = foo_resume, /* optional */
|
||||
.command = foo_command, /* optional */
|
||||
.command = foo_command, /* optional, deprecated */
|
||||
}
|
||||
|
||||
|
||||
The name field is the driver name, and must not contain spaces. It
|
||||
should match the module name (if the driver can be compiled as a module),
|
||||
although you can use MODULE_ALIAS (passing "foo" in this example) to add
|
||||
another name for the module. If the driver name doesn't match the module
|
||||
name, the module won't be automatically loaded (hotplug/coldplug).
|
||||
|
||||
All other fields are for call-back functions which will be explained
|
||||
All other fields are for call-back functions which will be explained
|
||||
below.
|
||||
|
||||
|
||||
@ -74,34 +66,13 @@ Extra client data
|
||||
=================
|
||||
|
||||
Each client structure has a special `data' field that can point to any
|
||||
structure at all. You should use this to keep device-specific data,
|
||||
especially in drivers that handle multiple I2C or SMBUS devices. You
|
||||
do not always need this, but especially for `sensors' drivers, it can
|
||||
be very useful.
|
||||
structure at all. You should use this to keep device-specific data.
|
||||
|
||||
/* store the value */
|
||||
void i2c_set_clientdata(struct i2c_client *client, void *data);
|
||||
|
||||
/* retrieve the value */
|
||||
void *i2c_get_clientdata(struct i2c_client *client);
|
||||
|
||||
An example structure is below.
|
||||
|
||||
struct foo_data {
|
||||
struct i2c_client client;
|
||||
enum chips type; /* To keep the chips type for `sensors' drivers. */
|
||||
|
||||
/* Because the i2c bus is slow, it is often useful to cache the read
|
||||
information of a chip for some time (for example, 1 or 2 seconds).
|
||||
It depends of course on the device whether this is really worthwhile
|
||||
or even sensible. */
|
||||
struct mutex update_lock; /* When we are reading lots of information,
|
||||
another process should not update the
|
||||
below information */
|
||||
char valid; /* != 0 if the following fields are valid. */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
/* Add the read information here too */
|
||||
};
|
||||
void *i2c_get_clientdata(const struct i2c_client *client);
|
||||
|
||||
|
||||
Accessing the client
|
||||
@ -109,11 +80,9 @@ Accessing the client
|
||||
|
||||
Let's say we have a valid client structure. At some time, we will need
|
||||
to gather information from the client, or write new information to the
|
||||
client. How we will export this information to user-space is less
|
||||
important at this moment (perhaps we do not need to do this at all for
|
||||
some obscure clients). But we need generic reading and writing routines.
|
||||
client.
|
||||
|
||||
I have found it useful to define foo_read and foo_write function for this.
|
||||
I have found it useful to define foo_read and foo_write functions for this.
|
||||
For some cases, it will be easier to call the i2c functions directly,
|
||||
but many chips have some kind of register-value idea that can easily
|
||||
be encapsulated.
|
||||
@ -121,33 +90,33 @@ be encapsulated.
|
||||
The below functions are simple examples, and should not be copied
|
||||
literally.
|
||||
|
||||
int foo_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
if (reg < 0x10) /* byte-sized register */
|
||||
return i2c_smbus_read_byte_data(client,reg);
|
||||
else /* word-sized register */
|
||||
return i2c_smbus_read_word_data(client,reg);
|
||||
}
|
||||
int foo_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
if (reg < 0x10) /* byte-sized register */
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
else /* word-sized register */
|
||||
return i2c_smbus_read_word_data(client, reg);
|
||||
}
|
||||
|
||||
int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (reg == 0x10) /* Impossible to write - driver error! */ {
|
||||
return -1;
|
||||
else if (reg < 0x10) /* byte-sized register */
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
else /* word-sized register */
|
||||
return i2c_smbus_write_word_data(client,reg,value);
|
||||
}
|
||||
int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (reg == 0x10) /* Impossible to write - driver error! */
|
||||
return -EINVAL;
|
||||
else if (reg < 0x10) /* byte-sized register */
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
else /* word-sized register */
|
||||
return i2c_smbus_write_word_data(client, reg, value);
|
||||
}
|
||||
|
||||
|
||||
Probing and attaching
|
||||
=====================
|
||||
|
||||
The Linux I2C stack was originally written to support access to hardware
|
||||
monitoring chips on PC motherboards, and thus it embeds some assumptions
|
||||
that are more appropriate to SMBus (and PCs) than to I2C. One of these
|
||||
assumptions is that most adapters and devices drivers support the SMBUS_QUICK
|
||||
protocol to probe device presence. Another is that devices and their drivers
|
||||
monitoring chips on PC motherboards, and thus used to embed some assumptions
|
||||
that were more appropriate to SMBus (and PCs) than to I2C. One of these
|
||||
assumptions was that most adapters and devices drivers support the SMBUS_QUICK
|
||||
protocol to probe device presence. Another was that devices and their drivers
|
||||
can be sufficiently configured using only such probe primitives.
|
||||
|
||||
As Linux and its I2C stack became more widely used in embedded systems
|
||||
@ -164,6 +133,9 @@ since the "legacy" model requires drivers to create "i2c_client" device
|
||||
objects after SMBus style probing, while the Linux driver model expects
|
||||
drivers to be given such device objects in their probe() routines.
|
||||
|
||||
The legacy model is deprecated now and will soon be removed, so we no
|
||||
longer document it here.
|
||||
|
||||
|
||||
Standard Driver Model Binding ("New Style")
|
||||
-------------------------------------------
|
||||
@ -193,8 +165,8 @@ matches the device's name. It is passed the entry that was matched so
|
||||
the driver knows which one in the table matched.
|
||||
|
||||
|
||||
Device Creation (Standard driver model)
|
||||
---------------------------------------
|
||||
Device Creation
|
||||
---------------
|
||||
|
||||
If you know for a fact that an I2C device is connected to a given I2C bus,
|
||||
you can instantiate that device by simply filling an i2c_board_info
|
||||
@ -221,8 +193,8 @@ in the I2C bus driver. You may want to save the returned i2c_client
|
||||
reference for later use.
|
||||
|
||||
|
||||
Device Detection (Standard driver model)
|
||||
----------------------------------------
|
||||
Device Detection
|
||||
----------------
|
||||
|
||||
Sometimes you do not know in advance which I2C devices are connected to
|
||||
a given I2C bus. This is for example the case of hardware monitoring
|
||||
@ -246,8 +218,8 @@ otherwise misdetections are likely to occur and things can get wrong
|
||||
quickly.
|
||||
|
||||
|
||||
Device Deletion (Standard driver model)
|
||||
---------------------------------------
|
||||
Device Deletion
|
||||
---------------
|
||||
|
||||
Each I2C device which has been created using i2c_new_device() or
|
||||
i2c_new_probed_device() can be unregistered by calling
|
||||
@ -256,264 +228,37 @@ called automatically before the underlying I2C bus itself is removed, as a
|
||||
device can't survive its parent in the device driver model.
|
||||
|
||||
|
||||
Legacy Driver Binding Model
|
||||
---------------------------
|
||||
Initializing the driver
|
||||
=======================
|
||||
|
||||
Most i2c devices can be present on several i2c addresses; for some this
|
||||
is determined in hardware (by soldering some chip pins to Vcc or Ground),
|
||||
for others this can be changed in software (by writing to specific client
|
||||
registers). Some devices are usually on a specific address, but not always;
|
||||
and some are even more tricky. So you will probably need to scan several
|
||||
i2c addresses for your clients, and do some sort of detection to see
|
||||
whether it is actually a device supported by your driver.
|
||||
When the kernel is booted, or when your foo driver module is inserted,
|
||||
you have to do some initializing. Fortunately, just registering the
|
||||
driver module is usually enough.
|
||||
|
||||
To give the user a maximum of possibilities, some default module parameters
|
||||
are defined to help determine what addresses are scanned. Several macros
|
||||
are defined in i2c.h to help you support them, as well as a generic
|
||||
detection algorithm.
|
||||
static int __init foo_init(void)
|
||||
{
|
||||
return i2c_add_driver(&foo_driver);
|
||||
}
|
||||
|
||||
You do not have to use this parameter interface; but don't try to use
|
||||
function i2c_probe() if you don't.
|
||||
static void __exit foo_cleanup(void)
|
||||
{
|
||||
i2c_del_driver(&foo_driver);
|
||||
}
|
||||
|
||||
/* Substitute your own name and email address */
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
|
||||
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
|
||||
|
||||
Probing classes (Legacy model)
|
||||
------------------------------
|
||||
/* a few non-GPL license types are also allowed */
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||
terminated by I2C_CLIENT_END.
|
||||
The following lists are used internally:
|
||||
module_init(foo_init);
|
||||
module_exit(foo_cleanup);
|
||||
|
||||
normal_i2c: filled in by the module writer.
|
||||
A list of I2C addresses which should normally be examined.
|
||||
probe: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the address. These addresses are also probed, as if they
|
||||
were in the 'normal' list.
|
||||
ignore: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. These addresses are never probed.
|
||||
This parameter overrules the 'normal_i2c' list only.
|
||||
force: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. A device is blindly assumed to be on
|
||||
the given address, no probing is done.
|
||||
|
||||
Additionally, kind-specific force lists may optionally be defined if
|
||||
the driver supports several chip kinds. They are grouped in a
|
||||
NULL-terminated list of pointers named forces, those first element if the
|
||||
generic force list mentioned above. Each additional list correspond to an
|
||||
insmod parameter of the form force_<kind>.
|
||||
|
||||
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||
parameter. The complete declaration could look like this:
|
||||
|
||||
/* Scan 0x4c to 0x4f */
|
||||
static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
I2C_CLIENT_END };
|
||||
|
||||
/* Magic definition of all other variables and things */
|
||||
I2C_CLIENT_INSMOD;
|
||||
/* Or, if your driver supports, say, 2 kind of devices: */
|
||||
I2C_CLIENT_INSMOD_2(foo, bar);
|
||||
|
||||
If you use the multi-kind form, an enum will be defined for you:
|
||||
enum chips { any_chip, foo, bar, ... }
|
||||
You can then (and certainly should) use it in the driver code.
|
||||
|
||||
Note that you *have* to call the defined variable `normal_i2c',
|
||||
without any prefix!
|
||||
|
||||
|
||||
Attaching to an adapter (Legacy model)
|
||||
--------------------------------------
|
||||
|
||||
Whenever a new adapter is inserted, or for all adapters if the driver is
|
||||
being registered, the callback attach_adapter() is called. Now is the
|
||||
time to determine what devices are present on the adapter, and to register
|
||||
a client for each of them.
|
||||
|
||||
The attach_adapter callback is really easy: we just call the generic
|
||||
detection function. This function will scan the bus for us, using the
|
||||
information as defined in the lists explained above. If a device is
|
||||
detected at a specific address, another callback is called.
|
||||
|
||||
int foo_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_probe(adapter,&addr_data,&foo_detect_client);
|
||||
}
|
||||
|
||||
Remember, structure `addr_data' is defined by the macros explained above,
|
||||
so you do not have to define it yourself.
|
||||
|
||||
The i2c_probe function will call the foo_detect_client
|
||||
function only for those i2c addresses that actually have a device on
|
||||
them (unless a `force' parameter was used). In addition, addresses that
|
||||
are already in use (by some other registered client) are skipped.
|
||||
|
||||
|
||||
The detect client function (Legacy model)
|
||||
-----------------------------------------
|
||||
|
||||
The detect client function is called by i2c_probe. The `kind' parameter
|
||||
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||
number for a forced detection with a chip type forced.
|
||||
|
||||
Returning an error different from -ENODEV in a detect function will cause
|
||||
the detection to stop: other addresses and adapters won't be scanned.
|
||||
This should only be done on fatal or internal errors, such as a memory
|
||||
shortage or i2c_attach_client failing.
|
||||
|
||||
For now, you can ignore the `flags' parameter. It is there for future use.
|
||||
|
||||
int foo_detect_client(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
struct i2c_client *client;
|
||||
struct foo_data *data;
|
||||
const char *name = "";
|
||||
|
||||
/* Let's see whether this adapter can support what we need.
|
||||
Please substitute the things you need here! */
|
||||
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access several i2c functions safely */
|
||||
|
||||
if (!(data = kzalloc(sizeof(struct foo_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
client = &data->client;
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
client->addr = address;
|
||||
client->adapter = adapter;
|
||||
client->driver = &foo_driver;
|
||||
|
||||
/* Now, we do the remaining detection. If no `force' parameter is used. */
|
||||
|
||||
/* First, the generic detection (if any), that is skipped if any force
|
||||
parameter was used. */
|
||||
if (kind < 0) {
|
||||
/* The below is of course bogus */
|
||||
if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Next, specific detection. This is especially important for `sensors'
|
||||
devices. */
|
||||
|
||||
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
|
||||
was used. */
|
||||
if (kind <= 0) {
|
||||
i = foo_read(client, FOO_REG_CHIPTYPE);
|
||||
if (i == FOO_TYPE_1)
|
||||
kind = chip1; /* As defined in the enum */
|
||||
else if (i == FOO_TYPE_2)
|
||||
kind = chip2;
|
||||
else {
|
||||
printk("foo: Ignoring 'force' parameter for unknown chip at "
|
||||
"adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);
|
||||
goto ERROR1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the type and chip names */
|
||||
if (kind == chip1) {
|
||||
name = "chip1";
|
||||
} else if (kind == chip2) {
|
||||
name = "chip2";
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields. */
|
||||
strlcpy(client->name, name, I2C_NAME_SIZE);
|
||||
data->type = kind;
|
||||
mutex_init(&data->update_lock); /* Only if you use this field */
|
||||
|
||||
/* Any other initializations in data must be done here too. */
|
||||
|
||||
/* This function can write default values to the client registers, if
|
||||
needed. */
|
||||
foo_init_client(client);
|
||||
|
||||
/* Tell the i2c layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(client)))
|
||||
goto ERROR1;
|
||||
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR1:
|
||||
kfree(data);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Removing the client (Legacy model)
|
||||
==================================
|
||||
|
||||
The detach_client call back function is called when a client should be
|
||||
removed. It may actually fail, but only when panicking. This code is
|
||||
much simpler than the attachment code, fortunately!
|
||||
|
||||
int foo_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Try to detach the client from i2c space */
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Initializing the module or kernel
|
||||
=================================
|
||||
|
||||
When the kernel is booted, or when your foo driver module is inserted,
|
||||
you have to do some initializing. Fortunately, just attaching (registering)
|
||||
the driver module is usually enough.
|
||||
|
||||
static int __init foo_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = i2c_add_driver(&foo_driver))) {
|
||||
printk("foo: Driver registration failed, module not inserted.\n");
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit foo_cleanup(void)
|
||||
{
|
||||
i2c_del_driver(&foo_driver);
|
||||
}
|
||||
|
||||
/* Substitute your own name and email address */
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
|
||||
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
|
||||
|
||||
/* a few non-GPL license types are also allowed */
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(foo_init);
|
||||
module_exit(foo_cleanup);
|
||||
|
||||
Note that some functions are marked by `__init', and some data structures
|
||||
by `__initdata'. These functions and structures can be removed after
|
||||
kernel booting (or module loading) is completed.
|
||||
Note that some functions are marked by `__init'. These functions can
|
||||
be removed after kernel booting (or module loading) is completed.
|
||||
Likewise, functions marked by `__exit' are dropped by the compiler when
|
||||
the code is built into the kernel, as they would never be called.
|
||||
|
||||
|
||||
Power Management
|
||||
@ -548,33 +293,35 @@ Command function
|
||||
|
||||
A generic ioctl-like function call back is supported. You will seldom
|
||||
need this, and its use is deprecated anyway, so newer design should not
|
||||
use it. Set it to NULL.
|
||||
use it.
|
||||
|
||||
|
||||
Sending and receiving
|
||||
=====================
|
||||
|
||||
If you want to communicate with your device, there are several functions
|
||||
to do this. You can find all of them in i2c.h.
|
||||
to do this. You can find all of them in <linux/i2c.h>.
|
||||
|
||||
If you can choose between plain i2c communication and SMBus level
|
||||
communication, please use the last. All adapters understand SMBus level
|
||||
commands, but only some of them understand plain i2c!
|
||||
If you can choose between plain I2C communication and SMBus level
|
||||
communication, please use the latter. All adapters understand SMBus level
|
||||
commands, but only some of them understand plain I2C!
|
||||
|
||||
|
||||
Plain i2c communication
|
||||
Plain I2C communication
|
||||
-----------------------
|
||||
|
||||
extern int i2c_master_send(struct i2c_client *,const char* ,int);
|
||||
extern int i2c_master_recv(struct i2c_client *,char* ,int);
|
||||
int i2c_master_send(struct i2c_client *client, const char *buf,
|
||||
int count);
|
||||
int i2c_master_recv(struct i2c_client *client, char *buf, int count);
|
||||
|
||||
These routines read and write some bytes from/to a client. The client
|
||||
contains the i2c address, so you do not have to include it. The second
|
||||
parameter contains the bytes the read/write, the third the length of the
|
||||
buffer. Returned is the actual number of bytes read/written.
|
||||
|
||||
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
int num);
|
||||
parameter contains the bytes to read/write, the third the number of bytes
|
||||
to read/write (must be less than the length of the buffer.) Returned is
|
||||
the actual number of bytes read/written.
|
||||
|
||||
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
int num);
|
||||
|
||||
This sends a series of messages. Each message can be a read or write,
|
||||
and they can be mixed in any way. The transactions are combined: no
|
||||
@ -583,49 +330,45 @@ for each message the client address, the number of bytes of the message
|
||||
and the message data itself.
|
||||
|
||||
You can read the file `i2c-protocol' for more information about the
|
||||
actual i2c protocol.
|
||||
actual I2C protocol.
|
||||
|
||||
|
||||
SMBus communication
|
||||
-------------------
|
||||
|
||||
extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
|
||||
unsigned short flags,
|
||||
char read_write, u8 command, int size,
|
||||
union i2c_smbus_data * data);
|
||||
s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data);
|
||||
|
||||
This is the generic SMBus function. All functions below are implemented
|
||||
in terms of it. Never use this function directly!
|
||||
This is the generic SMBus function. All functions below are implemented
|
||||
in terms of it. Never use this function directly!
|
||||
|
||||
|
||||
extern s32 i2c_smbus_read_byte(struct i2c_client * client);
|
||||
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
|
||||
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
|
||||
extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
|
||||
u8 command, u8 value);
|
||||
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
|
||||
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
|
||||
u8 command, u16 value);
|
||||
extern s32 i2c_smbus_process_call(struct i2c_client *client,
|
||||
u8 command, u16 value);
|
||||
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
|
||||
u8 command, u8 *values);
|
||||
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
|
||||
u8 command, u8 length,
|
||||
u8 *values);
|
||||
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
|
||||
u8 command, u8 length, u8 *values);
|
||||
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
|
||||
u8 command, u8 length,
|
||||
u8 *values);
|
||||
s32 i2c_smbus_read_byte(struct i2c_client *client);
|
||||
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);
|
||||
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);
|
||||
s32 i2c_smbus_write_byte_data(struct i2c_client *client,
|
||||
u8 command, u8 value);
|
||||
s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);
|
||||
s32 i2c_smbus_write_word_data(struct i2c_client *client,
|
||||
u8 command, u16 value);
|
||||
s32 i2c_smbus_process_call(struct i2c_client *client,
|
||||
u8 command, u16 value);
|
||||
s32 i2c_smbus_read_block_data(struct i2c_client *client,
|
||||
u8 command, u8 *values);
|
||||
s32 i2c_smbus_write_block_data(struct i2c_client *client,
|
||||
u8 command, u8 length, const u8 *values);
|
||||
s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client,
|
||||
u8 command, u8 length, u8 *values);
|
||||
s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
|
||||
u8 command, u8 length,
|
||||
const u8 *values);
|
||||
|
||||
These ones were removed from i2c-core because they had no users, but could
|
||||
be added back later if needed:
|
||||
|
||||
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
|
||||
extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
|
||||
u8 command, u8 length,
|
||||
u8 *values)
|
||||
s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value);
|
||||
s32 i2c_smbus_block_process_call(struct i2c_client *client,
|
||||
u8 command, u8 length, u8 *values);
|
||||
|
||||
All these transactions return a negative errno value on failure. The 'write'
|
||||
transactions return 0 on success; the 'read' transactions return the read
|
||||
@ -642,7 +385,5 @@ General purpose routines
|
||||
Below all general purpose routines are listed, that were not mentioned
|
||||
before.
|
||||
|
||||
/* This call returns a unique low identifier for each registered adapter.
|
||||
*/
|
||||
extern int i2c_adapter_id(struct i2c_adapter *adap);
|
||||
|
||||
/* Return the adapter number for a specific adapter */
|
||||
int i2c_adapter_id(struct i2c_adapter *adap);
|
||||
|
183
Documentation/ia64/xen.txt
Normal file
183
Documentation/ia64/xen.txt
Normal file
@ -0,0 +1,183 @@
|
||||
Recipe for getting/building/running Xen/ia64 with pv_ops
|
||||
--------------------------------------------------------
|
||||
|
||||
This recipe describes how to get xen-ia64 source and build it,
|
||||
and run domU with pv_ops.
|
||||
|
||||
============
|
||||
Requirements
|
||||
============
|
||||
|
||||
- python
|
||||
- mercurial
|
||||
it (aka "hg") is an open-source source code
|
||||
management software. See the below.
|
||||
http://www.selenic.com/mercurial/wiki/
|
||||
- git
|
||||
- bridge-utils
|
||||
|
||||
=================================
|
||||
Getting and Building Xen and Dom0
|
||||
=================================
|
||||
|
||||
My environment is;
|
||||
Machine : Tiger4
|
||||
Domain0 OS : RHEL5
|
||||
DomainU OS : RHEL5
|
||||
|
||||
1. Download source
|
||||
# hg clone http://xenbits.xensource.com/ext/ia64/xen-unstable.hg
|
||||
# cd xen-unstable.hg
|
||||
# hg clone http://xenbits.xensource.com/ext/ia64/linux-2.6.18-xen.hg
|
||||
|
||||
2. # make world
|
||||
|
||||
3. # make install-tools
|
||||
|
||||
4. copy kernels and xen
|
||||
# cp xen/xen.gz /boot/efi/efi/redhat/
|
||||
# cp build-linux-2.6.18-xen_ia64/vmlinux.gz \
|
||||
/boot/efi/efi/redhat/vmlinuz-2.6.18.8-xen
|
||||
|
||||
5. make initrd for Dom0/DomU
|
||||
# make -C linux-2.6.18-xen.hg ARCH=ia64 modules_install \
|
||||
O=$(/bin/pwd)/build-linux-2.6.18-xen_ia64
|
||||
# mkinitrd -f /boot/efi/efi/redhat/initrd-2.6.18.8-xen.img \
|
||||
2.6.18.8-xen --builtin mptspi --builtin mptbase \
|
||||
--builtin mptscsih --builtin uhci-hcd --builtin ohci-hcd \
|
||||
--builtin ehci-hcd
|
||||
|
||||
================================
|
||||
Making a disk image for guest OS
|
||||
================================
|
||||
|
||||
1. make file
|
||||
# dd if=/dev/zero of=/root/rhel5.img bs=1M seek=4096 count=0
|
||||
# mke2fs -F -j /root/rhel5.img
|
||||
# mount -o loop /root/rhel5.img /mnt
|
||||
# cp -ax /{dev,var,etc,usr,bin,sbin,lib} /mnt
|
||||
# mkdir /mnt/{root,proc,sys,home,tmp}
|
||||
|
||||
Note: You may miss some device files. If so, please create them
|
||||
with mknod. Or you can use tar instead of cp.
|
||||
|
||||
2. modify DomU's fstab
|
||||
# vi /mnt/etc/fstab
|
||||
/dev/xvda1 / ext3 defaults 1 1
|
||||
none /dev/pts devpts gid=5,mode=620 0 0
|
||||
none /dev/shm tmpfs defaults 0 0
|
||||
none /proc proc defaults 0 0
|
||||
none /sys sysfs defaults 0 0
|
||||
|
||||
3. modify inittab
|
||||
set runlevel to 3 to avoid X trying to start
|
||||
# vi /mnt/etc/inittab
|
||||
id:3:initdefault:
|
||||
Start a getty on the hvc0 console
|
||||
X0:2345:respawn:/sbin/mingetty hvc0
|
||||
tty1-6 mingetty can be commented out
|
||||
|
||||
4. add hvc0 into /etc/securetty
|
||||
# vi /mnt/etc/securetty (add hvc0)
|
||||
|
||||
5. umount
|
||||
# umount /mnt
|
||||
|
||||
FYI, virt-manager can also make a disk image for guest OS.
|
||||
It's GUI tools and easy to make it.
|
||||
|
||||
==================
|
||||
Boot Xen & Domain0
|
||||
==================
|
||||
|
||||
1. replace elilo
|
||||
elilo of RHEL5 can boot Xen and Dom0.
|
||||
If you use old elilo (e.g RHEL4), please download from the below
|
||||
http://elilo.sourceforge.net/cgi-bin/blosxom
|
||||
and copy into /boot/efi/efi/redhat/
|
||||
# cp elilo-3.6-ia64.efi /boot/efi/efi/redhat/elilo.efi
|
||||
|
||||
2. modify elilo.conf (like the below)
|
||||
# vi /boot/efi/efi/redhat/elilo.conf
|
||||
prompt
|
||||
timeout=20
|
||||
default=xen
|
||||
relocatable
|
||||
|
||||
image=vmlinuz-2.6.18.8-xen
|
||||
label=xen
|
||||
vmm=xen.gz
|
||||
initrd=initrd-2.6.18.8-xen.img
|
||||
read-only
|
||||
append=" -- rhgb root=/dev/sda2"
|
||||
|
||||
The append options before "--" are for xen hypervisor,
|
||||
the options after "--" are for dom0.
|
||||
|
||||
FYI, your machine may need console options like
|
||||
"com1=19200,8n1 console=vga,com1". For example,
|
||||
append="com1=19200,8n1 console=vga,com1 -- rhgb console=tty0 \
|
||||
console=ttyS0 root=/dev/sda2"
|
||||
|
||||
=====================================
|
||||
Getting and Building domU with pv_ops
|
||||
=====================================
|
||||
|
||||
1. get pv_ops tree
|
||||
# git clone http://people.valinux.co.jp/~yamahata/xen-ia64/linux-2.6-xen-ia64.git/
|
||||
|
||||
2. git branch (if necessary)
|
||||
# cd linux-2.6-xen-ia64/
|
||||
# git checkout -b your_branch origin/xen-ia64-domu-minimal-2008may19
|
||||
(Note: The current branch is xen-ia64-domu-minimal-2008may19.
|
||||
But you would find the new branch. You can see with
|
||||
"git branch -r" to get the branch lists.
|
||||
http://people.valinux.co.jp/~yamahata/xen-ia64/for_eagl/linux-2.6-ia64-pv-ops.git/
|
||||
is also available. The tree is based on
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6 test)
|
||||
|
||||
|
||||
3. copy .config for pv_ops of domU
|
||||
# cp arch/ia64/configs/xen_domu_wip_defconfig .config
|
||||
|
||||
4. make kernel with pv_ops
|
||||
# make oldconfig
|
||||
# make
|
||||
|
||||
5. install the kernel and initrd
|
||||
# cp vmlinux.gz /boot/efi/efi/redhat/vmlinuz-2.6-pv_ops-xenU
|
||||
# make modules_install
|
||||
# mkinitrd -f /boot/efi/efi/redhat/initrd-2.6-pv_ops-xenU.img \
|
||||
2.6.26-rc3xen-ia64-08941-g1b12161 --builtin mptspi \
|
||||
--builtin mptbase --builtin mptscsih --builtin uhci-hcd \
|
||||
--builtin ohci-hcd --builtin ehci-hcd
|
||||
|
||||
========================
|
||||
Boot DomainU with pv_ops
|
||||
========================
|
||||
|
||||
1. make config of DomU
|
||||
# vi /etc/xen/rhel5
|
||||
kernel = "/boot/efi/efi/redhat/vmlinuz-2.6-pv_ops-xenU"
|
||||
ramdisk = "/boot/efi/efi/redhat/initrd-2.6-pv_ops-xenU.img"
|
||||
vcpus = 1
|
||||
memory = 512
|
||||
name = "rhel5"
|
||||
disk = [ 'file:/root/rhel5.img,xvda1,w' ]
|
||||
root = "/dev/xvda1 ro"
|
||||
extra= "rhgb console=hvc0"
|
||||
|
||||
2. After boot xen and dom0, start xend
|
||||
# /etc/init.d/xend start
|
||||
( In the debugging case, # XEND_DEBUG=1 xend trace_start )
|
||||
|
||||
3. start domU
|
||||
# xm create -c rhel5
|
||||
|
||||
=========
|
||||
Reference
|
||||
=========
|
||||
- Wiki of Xen/IA64 upstream merge
|
||||
http://wiki.xensource.com/xenwiki/XenIA64/UpstreamMerge
|
||||
|
||||
Written by Akio Takebe <takebe_akio@jp.fujitsu.com> on 28 May 2008
|
@ -109,7 +109,8 @@ There are two possible methods of using Kdump.
|
||||
2) Or use the system kernel binary itself as dump-capture kernel and there is
|
||||
no need to build a separate dump-capture kernel. This is possible
|
||||
only with the architecutres which support a relocatable kernel. As
|
||||
of today, i386, x86_64 and ia64 architectures support relocatable kernel.
|
||||
of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
|
||||
kernel.
|
||||
|
||||
Building a relocatable kernel is advantageous from the point of view that
|
||||
one does not have to build a second kernel for capturing the dump. But
|
||||
@ -207,8 +208,15 @@ Dump-capture kernel config options (Arch Dependent, i386 and x86_64)
|
||||
Dump-capture kernel config options (Arch Dependent, ppc64)
|
||||
----------------------------------------------------------
|
||||
|
||||
* Make and install the kernel and its modules. DO NOT add this kernel
|
||||
to the boot loader configuration files.
|
||||
1) Enable "Build a kdump crash kernel" support under "Kernel" options:
|
||||
|
||||
CONFIG_CRASH_DUMP=y
|
||||
|
||||
2) Enable "Build a relocatable kernel" support
|
||||
|
||||
CONFIG_RELOCATABLE=y
|
||||
|
||||
Make and install the kernel and its modules.
|
||||
|
||||
Dump-capture kernel config options (Arch Dependent, ia64)
|
||||
----------------------------------------------------------
|
||||
|
@ -218,20 +218,47 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
acpi.debug_level= [HW,ACPI]
|
||||
Format: <int>
|
||||
Each bit of the <int> indicates an ACPI debug level,
|
||||
1: enable, 0: disable. It is useful for boot time
|
||||
debugging. After system has booted up, it can be set
|
||||
via /sys/module/acpi/parameters/debug_level.
|
||||
CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
|
||||
Available bits (add the numbers together) to enable different
|
||||
debug output levels of the ACPI subsystem:
|
||||
0x01 error 0x02 warn 0x04 init 0x08 debug object
|
||||
0x10 info 0x20 init names 0x40 parse 0x80 load
|
||||
0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
|
||||
0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
|
||||
0x10000 resources 0x20000 user requests 0x40000 package.
|
||||
The number can be in decimal or prefixed with 0x in hex.
|
||||
Warning: Many of these options can produce a lot of
|
||||
output and make your system unusable. Be very careful.
|
||||
which corresponds to the level in an ACPI_DEBUG_PRINT
|
||||
statement. After system has booted up, this mask
|
||||
can be set via /sys/module/acpi/parameters/debug_level.
|
||||
|
||||
CONFIG_ACPI_DEBUG must be enabled for this to produce
|
||||
any output. The number can be in decimal or prefixed
|
||||
with 0x in hex. Some of these options produce so much
|
||||
output that the system is unusable.
|
||||
|
||||
The following global components are defined by the
|
||||
ACPI CA:
|
||||
0x01 error
|
||||
0x02 warn
|
||||
0x04 init
|
||||
0x08 debug object
|
||||
0x10 info
|
||||
0x20 init names
|
||||
0x40 parse
|
||||
0x80 load
|
||||
0x100 dispatch
|
||||
0x200 execute
|
||||
0x400 names
|
||||
0x800 operation region
|
||||
0x1000 bfield
|
||||
0x2000 tables
|
||||
0x4000 values
|
||||
0x8000 objects
|
||||
0x10000 resources
|
||||
0x20000 user requests
|
||||
0x40000 package
|
||||
The number can be in decimal or prefixed with 0x in hex.
|
||||
Warning: Many of these options can produce a lot of
|
||||
output and make your system unusable. Be very careful.
|
||||
|
||||
acpi.power_nocheck= [HW,ACPI]
|
||||
Format: 1/0 enable/disable the check of power state.
|
||||
On some bogus BIOS the _PSC object/_STA object of
|
||||
power resource can't return the correct device power
|
||||
state. In such case it is unneccessary to check its
|
||||
power state again in power transition.
|
||||
1 : disable the power state check
|
||||
|
||||
acpi_pm_good [X86-32,X86-64]
|
||||
Override the pmtimer bug detection: force the kernel
|
||||
@ -1711,6 +1738,10 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
Override pmtimer IOPort with a hex value.
|
||||
e.g. pmtmr=0x508
|
||||
|
||||
pnp.debug [PNP]
|
||||
Enable PNP debug messages. This depends on the
|
||||
CONFIG_PNP_DEBUG_MESSAGES option.
|
||||
|
||||
pnpacpi= [ACPI]
|
||||
{ off }
|
||||
|
||||
@ -2208,7 +2239,7 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
|
||||
thermal.crt= [HW,ACPI]
|
||||
-1: disable all critical trip points in all thermal zones
|
||||
<degrees C>: lower all critical trip points
|
||||
<degrees C>: override all critical trip points
|
||||
|
||||
thermal.nocrt= [HW,ACPI]
|
||||
Set to disable actions on ACPI thermal zone
|
||||
|
@ -1,7 +1,7 @@
|
||||
Acer Laptop WMI Extras Driver
|
||||
http://code.google.com/p/aceracpi
|
||||
Version 0.1
|
||||
9th February 2008
|
||||
Version 0.2
|
||||
18th August 2008
|
||||
|
||||
Copyright 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
|
||||
|
||||
@ -87,17 +87,7 @@ acer-wmi come with built-in wireless. However, should you feel so inclined to
|
||||
ever wish to remove the card, or swap it out at some point, please get in touch
|
||||
with me, as we may well be able to gain some data on wireless card detection.
|
||||
|
||||
To read the status of the wireless radio (0=off, 1=on):
|
||||
cat /sys/devices/platform/acer-wmi/wireless
|
||||
|
||||
To enable the wireless radio:
|
||||
echo 1 > /sys/devices/platform/acer-wmi/wireless
|
||||
|
||||
To disable the wireless radio:
|
||||
echo 0 > /sys/devices/platform/acer-wmi/wireless
|
||||
|
||||
To set the state of the wireless radio when loading acer-wmi, pass:
|
||||
wireless=X (where X is 0 or 1)
|
||||
The wireless radio is exposed through rfkill.
|
||||
|
||||
Bluetooth
|
||||
*********
|
||||
@ -117,17 +107,7 @@ For the adventurously minded - if you want to buy an internal bluetooth
|
||||
module off the internet that is compatible with your laptop and fit it, then
|
||||
it will work just fine with acer-wmi.
|
||||
|
||||
To read the status of the bluetooth module (0=off, 1=on):
|
||||
cat /sys/devices/platform/acer-wmi/wireless
|
||||
|
||||
To enable the bluetooth module:
|
||||
echo 1 > /sys/devices/platform/acer-wmi/bluetooth
|
||||
|
||||
To disable the bluetooth module:
|
||||
echo 0 > /sys/devices/platform/acer-wmi/bluetooth
|
||||
|
||||
To set the state of the bluetooth module when loading acer-wmi, pass:
|
||||
bluetooth=X (where X is 0 or 1)
|
||||
Bluetooth is exposed through rfkill.
|
||||
|
||||
3G
|
||||
**
|
||||
|
@ -1917,6 +1917,8 @@ platforms are moved over to use the flattened-device-tree model.
|
||||
inverse clock polarity (CPOL) mode
|
||||
- spi-cpha - (optional) Empty property indicating device requires
|
||||
shifted clock phase (CPHA) mode
|
||||
- spi-cs-high - (optional) Empty property indicating device requires
|
||||
chip select active high
|
||||
|
||||
SPI example for an MPC5200 SPI bus:
|
||||
spi@f00 {
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- device_type : Should be "board-control"
|
||||
- compatible : Should be "fsl,<board>-bcsr"
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
Example:
|
||||
|
||||
bcsr@f8000000 {
|
||||
device_type = "board-control";
|
||||
compatible = "fsl,mpc8360mds-bcsr";
|
||||
reg = <f8000000 8000>;
|
||||
};
|
||||
|
||||
|
448
Documentation/usb/WUSB-Design-overview.txt
Normal file
448
Documentation/usb/WUSB-Design-overview.txt
Normal file
@ -0,0 +1,448 @@
|
||||
|
||||
Linux UWB + Wireless USB + WiNET
|
||||
|
||||
(C) 2005-2006 Intel Corporation
|
||||
Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Please visit http://bughost.org/thewiki/Design-overview.txt-1.8 for
|
||||
updated content.
|
||||
|
||||
* Design-overview.txt-1.8
|
||||
|
||||
This code implements a Ultra Wide Band stack for Linux, as well as
|
||||
drivers for the the USB based UWB radio controllers defined in the
|
||||
Wireless USB 1.0 specification (including Wireless USB host controller
|
||||
and an Intel WiNET controller).
|
||||
|
||||
1. Introduction
|
||||
1. HWA: Host Wire adapters, your Wireless USB dongle
|
||||
|
||||
2. DWA: Device Wired Adaptor, a Wireless USB hub for wired
|
||||
devices
|
||||
3. WHCI: Wireless Host Controller Interface, the PCI WUSB host
|
||||
adapter
|
||||
2. The UWB stack
|
||||
1. Devices and hosts: the basic structure
|
||||
|
||||
2. Host Controller life cycle
|
||||
|
||||
3. On the air: beacons and enumerating the radio neighborhood
|
||||
|
||||
4. Device lists
|
||||
5. Bandwidth allocation
|
||||
|
||||
3. Wireless USB Host Controller drivers
|
||||
|
||||
4. Glossary
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
UWB is a wide-band communication protocol that is to serve also as the
|
||||
low-level protocol for others (much like TCP sits on IP). Currently
|
||||
these others are Wireless USB and TCP/IP, but seems Bluetooth and
|
||||
Firewire/1394 are coming along.
|
||||
|
||||
UWB uses a band from roughly 3 to 10 GHz, transmitting at a max of
|
||||
~-41dB (or 0.074 uW/MHz--geography specific data is still being
|
||||
negotiated w/ regulators, so watch for changes). That band is divided in
|
||||
a bunch of ~1.5 GHz wide channels (or band groups) composed of three
|
||||
subbands/subchannels (528 MHz each). Each channel is independent of each
|
||||
other, so you could consider them different "busses". Initially this
|
||||
driver considers them all a single one.
|
||||
|
||||
Radio time is divided in 65536 us long /superframes/, each one divided
|
||||
in 256 256us long /MASs/ (Media Allocation Slots), which are the basic
|
||||
time/media allocation units for transferring data. At the beginning of
|
||||
each superframe there is a Beacon Period (BP), where every device
|
||||
transmit its beacon on a single MAS. The length of the BP depends on how
|
||||
many devices are present and the length of their beacons.
|
||||
|
||||
Devices have a MAC (fixed, 48 bit address) and a device (changeable, 16
|
||||
bit address) and send periodic beacons to advertise themselves and pass
|
||||
info on what they are and do. They advertise their capabilities and a
|
||||
bunch of other stuff.
|
||||
|
||||
The different logical parts of this driver are:
|
||||
|
||||
*
|
||||
|
||||
*UWB*: the Ultra-Wide-Band stack -- manages the radio and
|
||||
associated spectrum to allow for devices sharing it. Allows to
|
||||
control bandwidth assingment, beaconing, scanning, etc
|
||||
|
||||
*
|
||||
|
||||
*WUSB*: the layer that sits on top of UWB to provide Wireless USB.
|
||||
The Wireless USB spec defines means to control a UWB radio and to
|
||||
do the actual WUSB.
|
||||
|
||||
|
||||
HWA: Host Wire adapters, your Wireless USB dongle
|
||||
|
||||
WUSB also defines a device called a Host Wire Adaptor (HWA), which in
|
||||
mere terms is a USB dongle that enables your PC to have UWB and Wireless
|
||||
USB. The Wireless USB Host Controller in a HWA looks to the host like a
|
||||
[Wireless] USB controller connected via USB (!)
|
||||
|
||||
The HWA itself is broken in two or three main interfaces:
|
||||
|
||||
*
|
||||
|
||||
*RC*: Radio control -- this implements an interface to the
|
||||
Ultra-Wide-Band radio controller. The driver for this implements a
|
||||
USB-based UWB Radio Controller to the UWB stack.
|
||||
|
||||
*
|
||||
|
||||
*HC*: the wireless USB host controller. It looks like a USB host
|
||||
whose root port is the radio and the WUSB devices connect to it.
|
||||
To the system it looks like a separate USB host. The driver (will)
|
||||
implement a USB host controller (similar to UHCI, OHCI or EHCI)
|
||||
for which the root hub is the radio...To reiterate: it is a USB
|
||||
controller that is connected via USB instead of PCI.
|
||||
|
||||
*
|
||||
|
||||
*WINET*: some HW provide a WiNET interface (IP over UWB). This
|
||||
package provides a driver for it (it looks like a network
|
||||
interface, winetX). The driver detects when there is a link up for
|
||||
their type and kick into gear.
|
||||
|
||||
|
||||
DWA: Device Wired Adaptor, a Wireless USB hub for wired devices
|
||||
|
||||
These are the complement to HWAs. They are a USB host for connecting
|
||||
wired devices, but it is connected to your PC connected via Wireless
|
||||
USB. To the system it looks like yet another USB host. To the untrained
|
||||
eye, it looks like a hub that connects upstream wirelessly.
|
||||
|
||||
We still offer no support for this; however, it should share a lot of
|
||||
code with the HWA-RC driver; there is a bunch of factorization work that
|
||||
has been done to support that in upcoming releases.
|
||||
|
||||
|
||||
WHCI: Wireless Host Controller Interface, the PCI WUSB host adapter
|
||||
|
||||
This is your usual PCI device that implements WHCI. Similar in concept
|
||||
to EHCI, it allows your wireless USB devices (including DWAs) to connect
|
||||
to your host via a PCI interface. As in the case of the HWA, it has a
|
||||
Radio Control interface and the WUSB Host Controller interface per se.
|
||||
|
||||
There is still no driver support for this, but will be in upcoming
|
||||
releases.
|
||||
|
||||
|
||||
The UWB stack
|
||||
|
||||
The main mission of the UWB stack is to keep a tally of which devices
|
||||
are in radio proximity to allow drivers to connect to them. As well, it
|
||||
provides an API for controlling the local radio controllers (RCs from
|
||||
now on), such as to start/stop beaconing, scan, allocate bandwidth, etc.
|
||||
|
||||
|
||||
Devices and hosts: the basic structure
|
||||
|
||||
The main building block here is the UWB device (struct uwb_dev). For
|
||||
each device that pops up in radio presence (ie: the UWB host receives a
|
||||
beacon from it) you get a struct uwb_dev that will show up in
|
||||
/sys/class/uwb and in /sys/bus/uwb/devices.
|
||||
|
||||
For each RC that is detected, a new struct uwb_rc is created. In turn, a
|
||||
RC is also a device, so they also show in /sys/class/uwb and
|
||||
/sys/bus/uwb/devices, but at the same time, only radio controllers show
|
||||
up in /sys/class/uwb_rc.
|
||||
|
||||
*
|
||||
|
||||
[*] The reason for RCs being also devices is that not only we can
|
||||
see them while enumerating the system device tree, but also on the
|
||||
radio (their beacons and stuff), so the handling has to be
|
||||
likewise to that of a device.
|
||||
|
||||
Each RC driver is implemented by a separate driver that plugs into the
|
||||
interface that the UWB stack provides through a struct uwb_rc_ops. The
|
||||
spec creators have been nice enough to make the message format the same
|
||||
for HWA and WHCI RCs, so the driver is really a very thin transport that
|
||||
moves the requests from the UWB API to the device [/uwb_rc_ops->cmd()/]
|
||||
and sends the replies and notifications back to the API
|
||||
[/uwb_rc_neh_grok()/]. Notifications are handled to the UWB daemon, that
|
||||
is chartered, among other things, to keep the tab of how the UWB radio
|
||||
neighborhood looks, creating and destroying devices as they show up or
|
||||
dissapear.
|
||||
|
||||
Command execution is very simple: a command block is sent and a event
|
||||
block or reply is expected back. For sending/receiving command/events, a
|
||||
handle called /neh/ (Notification/Event Handle) is opened with
|
||||
/uwb_rc_neh_open()/.
|
||||
|
||||
The HWA-RC (USB dongle) driver (drivers/uwb/hwa-rc.c) does this job for
|
||||
the USB connected HWA. Eventually, drivers/whci-rc.c will do the same
|
||||
for the PCI connected WHCI controller.
|
||||
|
||||
|
||||
Host Controller life cycle
|
||||
|
||||
So let's say we connect a dongle to the system: it is detected and
|
||||
firmware uploaded if needed [for Intel's i1480
|
||||
/drivers/uwb/ptc/usb.c:ptc_usb_probe()/] and then it is reenumerated.
|
||||
Now we have a real HWA device connected and
|
||||
/drivers/uwb/hwa-rc.c:hwarc_probe()/ picks it up, that will set up the
|
||||
Wire-Adaptor environment and then suck it into the UWB stack's vision of
|
||||
the world [/drivers/uwb/lc-rc.c:uwb_rc_add()/].
|
||||
|
||||
*
|
||||
|
||||
[*] The stack should put a new RC to scan for devices
|
||||
[/uwb_rc_scan()/] so it finds what's available around and tries to
|
||||
connect to them, but this is policy stuff and should be driven
|
||||
from user space. As of now, the operator is expected to do it
|
||||
manually; see the release notes for documentation on the procedure.
|
||||
|
||||
When a dongle is disconnected, /drivers/uwb/hwa-rc.c:hwarc_disconnect()/
|
||||
takes time of tearing everything down safely (or not...).
|
||||
|
||||
|
||||
On the air: beacons and enumerating the radio neighborhood
|
||||
|
||||
So assuming we have devices and we have agreed for a channel to connect
|
||||
on (let's say 9), we put the new RC to beacon:
|
||||
|
||||
*
|
||||
|
||||
$ echo 9 0 > /sys/class/uwb_rc/uwb0/beacon
|
||||
|
||||
Now it is visible. If there were other devices in the same radio channel
|
||||
and beacon group (that's what the zero is for), the dongle's radio
|
||||
control interface will send beacon notifications on its
|
||||
notification/event endpoint (NEEP). The beacon notifications are part of
|
||||
the event stream that is funneled into the API with
|
||||
/drivers/uwb/neh.c:uwb_rc_neh_grok()/ and delivered to the UWBD, the UWB
|
||||
daemon through a notification list.
|
||||
|
||||
UWBD wakes up and scans the event list; finds a beacon and adds it to
|
||||
the BEACON CACHE (/uwb_beca/). If he receives a number of beacons from
|
||||
the same device, he considers it to be 'onair' and creates a new device
|
||||
[/drivers/uwb/lc-dev.c:uwbd_dev_onair()/]. Similarly, when no beacons
|
||||
are received in some time, the device is considered gone and wiped out
|
||||
[uwbd calls periodically /uwb/beacon.c:uwb_beca_purge()/ that will purge
|
||||
the beacon cache of dead devices].
|
||||
|
||||
|
||||
Device lists
|
||||
|
||||
All UWB devices are kept in the list of the struct bus_type uwb_bus.
|
||||
|
||||
|
||||
Bandwidth allocation
|
||||
|
||||
The UWB stack maintains a local copy of DRP availability through
|
||||
processing of incoming *DRP Availability Change* notifications. This
|
||||
local copy is currently used to present the current bandwidth
|
||||
availability to the user through the sysfs file
|
||||
/sys/class/uwb_rc/uwbx/bw_avail. In the future the bandwidth
|
||||
availability information will be used by the bandwidth reservation
|
||||
routines.
|
||||
|
||||
The bandwidth reservation routines are in progress and are thus not
|
||||
present in the current release. When completed they will enable a user
|
||||
to initiate DRP reservation requests through interaction with sysfs. DRP
|
||||
reservation requests from remote UWB devices will also be handled. The
|
||||
bandwidth management done by the UWB stack will include callbacks to the
|
||||
higher layers will enable the higher layers to use the reservations upon
|
||||
completion. [Note: The bandwidth reservation work is in progress and
|
||||
subject to change.]
|
||||
|
||||
|
||||
Wireless USB Host Controller drivers
|
||||
|
||||
*WARNING* This section needs a lot of work!
|
||||
|
||||
As explained above, there are three different types of HCs in the WUSB
|
||||
world: HWA-HC, DWA-HC and WHCI-HC.
|
||||
|
||||
HWA-HC and DWA-HC share that they are Wire-Adapters (USB or WUSB
|
||||
connected controllers), and their transfer management system is almost
|
||||
identical. So is their notification delivery system.
|
||||
|
||||
HWA-HC and WHCI-HC share that they are both WUSB host controllers, so
|
||||
they have to deal with WUSB device life cycle and maintenance, wireless
|
||||
root-hub
|
||||
|
||||
HWA exposes a Host Controller interface (HWA-HC 0xe0/02/02). This has
|
||||
three endpoints (Notifications, Data Transfer In and Data Transfer
|
||||
Out--known as NEP, DTI and DTO in the code).
|
||||
|
||||
We reserve UWB bandwidth for our Wireless USB Cluster, create a Cluster
|
||||
ID and tell the HC to use all that. Then we start it. This means the HC
|
||||
starts sending MMCs.
|
||||
|
||||
*
|
||||
|
||||
The MMCs are blocks of data defined somewhere in the WUSB1.0 spec
|
||||
that define a stream in the UWB channel time allocated for sending
|
||||
WUSB IEs (host to device commands/notifications) and Device
|
||||
Notifications (device initiated to host). Each host defines a
|
||||
unique Wireless USB cluster through MMCs. Devices can connect to a
|
||||
single cluster at the time. The IEs are Information Elements, and
|
||||
among them are the bandwidth allocations that tell each device
|
||||
when can they transmit or receive.
|
||||
|
||||
Now it all depends on external stimuli.
|
||||
|
||||
*New device connection*
|
||||
|
||||
A new device pops up, it scans the radio looking for MMCs that give out
|
||||
the existence of Wireless USB channels. Once one (or more) are found,
|
||||
selects which one to connect to. Sends a /DN_Connect/ (device
|
||||
notification connect) during the DNTS (Device Notification Time
|
||||
Slot--announced in the MMCs
|
||||
|
||||
HC picks the /DN_Connect/ out (nep module sends to notif.c for delivery
|
||||
into /devconnect/). This process starts the authentication process for
|
||||
the device. First we allocate a /fake port/ and assign an
|
||||
unauthenticated address (128 to 255--what we really do is
|
||||
0x80 | fake_port_idx). We fiddle with the fake port status and /khubd/
|
||||
sees a new connection, so he moves on to enable the fake port with a reset.
|
||||
|
||||
So now we are in the reset path -- we know we have a non-yet enumerated
|
||||
device with an unauthorized address; we ask user space to authenticate
|
||||
(FIXME: not yet done, similar to bluetooth pairing), then we do the key
|
||||
exchange (FIXME: not yet done) and issue a /set address 0/ to bring the
|
||||
device to the default state. Device is authenticated.
|
||||
|
||||
From here, the USB stack takes control through the usb_hcd ops. khubd
|
||||
has seen the port status changes, as we have been toggling them. It will
|
||||
start enumerating and doing transfers through usb_hcd->urb_enqueue() to
|
||||
read descriptors and move our data.
|
||||
|
||||
*Device life cycle and keep alives*
|
||||
|
||||
Everytime there is a succesful transfer to/from a device, we update a
|
||||
per-device activity timestamp. If not, every now and then we check and
|
||||
if the activity timestamp gets old, we ping the device by sending it a
|
||||
Keep Alive IE; it responds with a /DN_Alive/ pong during the DNTS (this
|
||||
arrives to us as a notification through
|
||||
devconnect.c:wusb_handle_dn_alive(). If a device times out, we
|
||||
disconnect it from the system (cleaning up internal information and
|
||||
toggling the bits in the fake hub port, which kicks khubd into removing
|
||||
the rest of the stuff).
|
||||
|
||||
This is done through devconnect:__wusb_check_devs(), which will scan the
|
||||
device list looking for whom needs refreshing.
|
||||
|
||||
If the device wants to disconnect, it will either die (ugly) or send a
|
||||
/DN_Disconnect/ that will prompt a disconnection from the system.
|
||||
|
||||
*Sending and receiving data*
|
||||
|
||||
Data is sent and received through /Remote Pipes/ (rpipes). An rpipe is
|
||||
/aimed/ at an endpoint in a WUSB device. This is the same for HWAs and
|
||||
DWAs.
|
||||
|
||||
Each HC has a number of rpipes and buffers that can be assigned to them;
|
||||
when doing a data transfer (xfer), first the rpipe has to be aimed and
|
||||
prepared (buffers assigned), then we can start queueing requests for
|
||||
data in or out.
|
||||
|
||||
Data buffers have to be segmented out before sending--so we send first a
|
||||
header (segment request) and then if there is any data, a data buffer
|
||||
immediately after to the DTI interface (yep, even the request). If our
|
||||
buffer is bigger than the max segment size, then we just do multiple
|
||||
requests.
|
||||
|
||||
[This sucks, because doing USB scatter gatter in Linux is resource
|
||||
intensive, if any...not that the current approach is not. It just has to
|
||||
be cleaned up a lot :)].
|
||||
|
||||
If reading, we don't send data buffers, just the segment headers saying
|
||||
we want to read segments.
|
||||
|
||||
When the xfer is executed, we receive a notification that says data is
|
||||
ready in the DTI endpoint (handled through
|
||||
xfer.c:wa_handle_notif_xfer()). In there we read from the DTI endpoint a
|
||||
descriptor that gives us the status of the transfer, its identification
|
||||
(given when we issued it) and the segment number. If it was a data read,
|
||||
we issue another URB to read into the destination buffer the chunk of
|
||||
data coming out of the remote endpoint. Done, wait for the next guy. The
|
||||
callbacks for the URBs issued from here are the ones that will declare
|
||||
the xfer complete at some point and call it's callback.
|
||||
|
||||
Seems simple, but the implementation is not trivial.
|
||||
|
||||
*
|
||||
|
||||
*WARNING* Old!!
|
||||
|
||||
The main xfer descriptor, wa_xfer (equivalent to a URB) contains an
|
||||
array of segments, tallys on segments and buffers and callback
|
||||
information. Buried in there is a lot of URBs for executing the segments
|
||||
and buffer transfers.
|
||||
|
||||
For OUT xfers, there is an array of segments, one URB for each, another
|
||||
one of buffer URB. When submitting, we submit URBs for segment request
|
||||
1, buffer 1, segment 2, buffer 2...etc. Then we wait on the DTI for xfer
|
||||
result data; when all the segments are complete, we call the callback to
|
||||
finalize the transfer.
|
||||
|
||||
For IN xfers, we only issue URBs for the segments we want to read and
|
||||
then wait for the xfer result data.
|
||||
|
||||
*URB mapping into xfers*
|
||||
|
||||
This is done by hwahc_op_urb_[en|de]queue(). In enqueue() we aim an
|
||||
rpipe to the endpoint where we have to transmit, create a transfer
|
||||
context (wa_xfer) and submit it. When the xfer is done, our callback is
|
||||
called and we assign the status bits and release the xfer resources.
|
||||
|
||||
In dequeue() we are basically cancelling/aborting the transfer. We issue
|
||||
a xfer abort request to the HC, cancell all the URBs we had submitted
|
||||
and not yet done and when all that is done, the xfer callback will be
|
||||
called--this will call the URB callback.
|
||||
|
||||
|
||||
Glossary
|
||||
|
||||
*DWA* -- Device Wire Adapter
|
||||
|
||||
USB host, wired for downstream devices, upstream connects wirelessly
|
||||
with Wireless USB.
|
||||
|
||||
*EVENT* -- Response to a command on the NEEP
|
||||
|
||||
*HWA* -- Host Wire Adapter / USB dongle for UWB and Wireless USB
|
||||
|
||||
*NEH* -- Notification/Event Handle
|
||||
|
||||
Handle/file descriptor for receiving notifications or events. The WA
|
||||
code requires you to get one of this to listen for notifications or
|
||||
events on the NEEP.
|
||||
|
||||
*NEEP* -- Notification/Event EndPoint
|
||||
|
||||
Stuff related to the management of the first endpoint of a HWA USB
|
||||
dongle that is used to deliver an stream of events and notifications to
|
||||
the host.
|
||||
|
||||
*NOTIFICATION* -- Message coming in the NEEP as response to something.
|
||||
|
||||
*RC* -- Radio Control
|
||||
|
||||
Design-overview.txt-1.8 (last edited 2006-11-04 12:22:24 by
|
||||
InakyPerezGonzalez)
|
||||
|
139
Documentation/usb/wusb-cbaf
Normal file
139
Documentation/usb/wusb-cbaf
Normal file
@ -0,0 +1,139 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
progname=$(basename $0)
|
||||
function help
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: $progname COMMAND DEVICEs [ARGS]
|
||||
|
||||
Command for manipulating the pairing/authentication credentials of a
|
||||
Wireless USB device that supports wired-mode Cable-Based-Association.
|
||||
|
||||
Works in conjunction with the wusb-cba.ko driver from http://linuxuwb.org.
|
||||
|
||||
|
||||
DEVICE
|
||||
|
||||
sysfs path to the device to authenticate; for example, both this
|
||||
guys are the same:
|
||||
|
||||
/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.1
|
||||
/sys/bus/usb/drivers/wusb-cbaf/1-4.4:1.1
|
||||
|
||||
COMMAND/ARGS are
|
||||
|
||||
start
|
||||
|
||||
Start a WUSB host controller (by setting up a CHID)
|
||||
|
||||
set-chid DEVICE HOST-CHID HOST-BANDGROUP HOST-NAME
|
||||
|
||||
Sets host information in the device; after this you can call the
|
||||
get-cdid to see how does this device report itself to us.
|
||||
|
||||
get-cdid DEVICE
|
||||
|
||||
Get the device ID associated to the HOST-CHDI we sent with
|
||||
'set-chid'. We might not know about it.
|
||||
|
||||
set-cc DEVICE
|
||||
|
||||
If we allow the device to connect, set a random new CDID and CK
|
||||
(connection key). Device saves them for the next time it wants to
|
||||
connect wireless. We save them for that next time also so we can
|
||||
authenticate the device (when we see the CDID he uses to id
|
||||
itself) and the CK to crypto talk to it.
|
||||
|
||||
CHID is always 16 hex bytes in 'XX YY ZZ...' form
|
||||
BANDGROUP is almost always 0001
|
||||
|
||||
Examples:
|
||||
|
||||
You can default most arguments to '' to get a sane value:
|
||||
|
||||
$ $progname set-chid '' '' '' "My host name"
|
||||
|
||||
A full sequence:
|
||||
|
||||
$ $progname set-chid '' '' '' "My host name"
|
||||
$ $progname get-cdid ''
|
||||
$ $progname set-cc ''
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# Defaults
|
||||
# FIXME: CHID should come from a database :), band group from the host
|
||||
host_CHID="00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"
|
||||
host_band_group="0001"
|
||||
host_name=$(hostname)
|
||||
|
||||
devs="$(echo /sys/bus/usb/drivers/wusb-cbaf/[0-9]*)"
|
||||
hdevs="$(for h in /sys/class/uwb_rc/*/wusbhc; do readlink -f $h; done)"
|
||||
|
||||
result=0
|
||||
case $1 in
|
||||
start)
|
||||
for dev in ${2:-$hdevs}
|
||||
do
|
||||
uwb_rc=$(readlink -f $dev/uwb_rc)
|
||||
if cat $uwb_rc/beacon | grep -q -- "-1"
|
||||
then
|
||||
echo 13 0 > $uwb_rc/beacon
|
||||
echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2
|
||||
fi
|
||||
echo $host_CHID > $dev/wusb_chid
|
||||
echo I: started host $(basename $dev) >&2
|
||||
done
|
||||
;;
|
||||
stop)
|
||||
for dev in ${2:-$hdevs}
|
||||
do
|
||||
echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid
|
||||
echo I: stopped host $(basename $dev) >&2
|
||||
uwb_rc=$(readlink -f $dev/uwb_rc)
|
||||
echo -1 | cat > $uwb_rc/beacon
|
||||
echo I: stopped beaconing on $(basename $uwb_rc) >&2
|
||||
done
|
||||
;;
|
||||
set-chid)
|
||||
shift
|
||||
for dev in ${2:-$devs}; do
|
||||
echo "${4:-$host_name}" > $dev/wusb_host_name
|
||||
echo "${3:-$host_band_group}" > $dev/wusb_host_band_groups
|
||||
echo ${2:-$host_CHID} > $dev/wusb_chid
|
||||
done
|
||||
;;
|
||||
get-cdid)
|
||||
for dev in ${2:-$devs}
|
||||
do
|
||||
cat $dev/wusb_cdid
|
||||
done
|
||||
;;
|
||||
set-cc)
|
||||
for dev in ${2:-$devs}; do
|
||||
shift
|
||||
CDID="$(head --bytes=16 /dev/urandom | od -tx1 -An)"
|
||||
CK="$(head --bytes=16 /dev/urandom | od -tx1 -An)"
|
||||
echo "$CDID" > $dev/wusb_cdid
|
||||
echo "$CK" > $dev/wusb_ck
|
||||
|
||||
echo I: CC set >&2
|
||||
echo "CHID: $(cat $dev/wusb_chid)"
|
||||
echo "CDID:$CDID"
|
||||
echo "CK: $CK"
|
||||
done
|
||||
;;
|
||||
help|h|--help|-h)
|
||||
help
|
||||
;;
|
||||
*)
|
||||
echo "E: Unknown usage" 1>&2
|
||||
help 1>&2
|
||||
result=1
|
||||
esac
|
||||
exit $result
|
53
MAINTAINERS
53
MAINTAINERS
@ -378,8 +378,9 @@ T: git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git
|
||||
S: Supported
|
||||
|
||||
AMD MICROCODE UPDATE SUPPORT
|
||||
P: Peter Oruba
|
||||
M: peter.oruba@amd.com
|
||||
P: Andreas Herrmann
|
||||
M: andeas.herrmann3@amd.com
|
||||
L: amd64-microcode@amd64.org
|
||||
S: Supported
|
||||
|
||||
AMS (Apple Motion Sensor) DRIVER
|
||||
@ -1053,6 +1054,12 @@ L: cbe-oss-dev@ozlabs.org
|
||||
W: http://www.ibm.com/developerworks/power/cell/
|
||||
S: Supported
|
||||
|
||||
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
|
||||
P: David Vrabel
|
||||
M: david.vrabel@csr.com
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
CFAG12864B LCD DRIVER
|
||||
P: Miguel Ojeda Sandonis
|
||||
M: miguel.ojeda.sandonis@gmail.com
|
||||
@ -1427,8 +1434,8 @@ M: rdunlap@xenotime.net
|
||||
S: Maintained
|
||||
|
||||
DOCKING STATION DRIVER
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
P: Shaohua Li
|
||||
M: shaohua.li@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
@ -2103,6 +2110,12 @@ L: linux-ide@vger.kernel.org
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Orphan
|
||||
|
||||
IDLE-I7300
|
||||
P: Andy Henroid
|
||||
M: andrew.d.henroid@intel.com
|
||||
L: linux-pm@lists.linux-foundation.org
|
||||
S: Supported
|
||||
|
||||
IEEE 1394 SUBSYSTEM (drivers/ieee1394)
|
||||
P: Ben Collins
|
||||
M: ben.collins@ubuntu.com
|
||||
@ -2176,6 +2189,13 @@ M: maciej.sosnowski@intel.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
INTEL IOMMU (VT-d)
|
||||
P: David Woodhouse
|
||||
M: dwmw2@infradead.org
|
||||
L: iommu@lists.linux-foundation.org
|
||||
T: git://git.infradead.org/iommu-2.6.git
|
||||
S: Supported
|
||||
|
||||
INTEL IOP-ADMA DMA DRIVER
|
||||
P: Dan Williams
|
||||
M: dan.j.williams@intel.com
|
||||
@ -2928,9 +2948,9 @@ S: Maintained
|
||||
|
||||
NETEFFECT IWARP RNIC DRIVER (IW_NES)
|
||||
P: Faisal Latif
|
||||
M: flatif@neteffect.com
|
||||
M: faisal.latif@intel.com
|
||||
P: Chien Tung
|
||||
M: ctung@neteffect.com
|
||||
M: chien.tin.tung@intel.com
|
||||
L: general@lists.openfabrics.org
|
||||
W: http://www.neteffect.com
|
||||
S: Supported
|
||||
@ -3173,6 +3193,11 @@ M: olof@lixom.net
|
||||
L: i2c@lm-sensors.org
|
||||
S: Maintained
|
||||
|
||||
PANASONIC LAPTOP ACPI EXTRAS DRIVER
|
||||
P: Harald Welte
|
||||
M: laforge@gnumonks.org
|
||||
S: Maintained
|
||||
|
||||
PANASONIC MN10300/AM33 PORT
|
||||
P: David Howells
|
||||
M: dhowells@redhat.com
|
||||
@ -3244,11 +3269,6 @@ L: linux-pci@vger.kernel.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
|
||||
S: Supported
|
||||
|
||||
PCI HOTPLUG CORE
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
S: Supported
|
||||
|
||||
PCIE HOTPLUG DRIVER
|
||||
P: Kristen Carlson Accardi
|
||||
M: kristen.c.accardi@intel.com
|
||||
@ -4191,6 +4211,12 @@ L: sparclinux@vger.kernel.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
|
||||
S: Maintained
|
||||
|
||||
ULTRA-WIDEBAND (UWB) SUBSYSTEM:
|
||||
P: David Vrabel
|
||||
M: david.vrabel@csr.com
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
UNIFORM CDROM DRIVER
|
||||
P: Jens Axboe
|
||||
M: axboe@kernel.dk
|
||||
@ -4616,6 +4642,11 @@ M: zaga@fly.cc.fer.hr
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
|
||||
P: David Vrabel
|
||||
M: david.vrabel@csr.com
|
||||
S: Maintained
|
||||
|
||||
WISTRON LAPTOP BUTTON DRIVER
|
||||
P: Miloslav Trmac
|
||||
M: mitr@volny.cz
|
||||
|
8
Makefile
8
Makefile
@ -1,8 +1,8 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 27
|
||||
EXTRAVERSION =
|
||||
NAME = Rotary Wombat
|
||||
SUBLEVEL = 28
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Killer Bat of Doom
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
@ -437,7 +437,7 @@ ifeq ($(config-targets),1)
|
||||
# KBUILD_DEFCONFIG may point out an alternative default configuration
|
||||
# used for 'make defconfig'
|
||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
||||
export KBUILD_DEFCONFIG
|
||||
export KBUILD_DEFCONFIG KBUILD_KCONFIG
|
||||
|
||||
config %config: scripts_basic outputmakefile FORCE
|
||||
$(Q)mkdir -p include/linux include/config
|
||||
|
@ -165,14 +165,11 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
|
||||
buf.error = 0;
|
||||
|
||||
error = vfs_readdir(file, osf_filldir, &buf);
|
||||
if (error < 0)
|
||||
goto out_putf;
|
||||
|
||||
error = buf.error;
|
||||
if (error >= 0)
|
||||
error = buf.error;
|
||||
if (count != buf.count)
|
||||
error = count - buf.count;
|
||||
|
||||
out_putf:
|
||||
fput(file);
|
||||
out:
|
||||
return error;
|
||||
@ -986,10 +983,12 @@ asmlinkage int
|
||||
osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
|
||||
struct timeval32 __user *tvp)
|
||||
{
|
||||
s64 timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
struct timespec end_time, *to = NULL;
|
||||
if (tvp) {
|
||||
time_t sec, usec;
|
||||
|
||||
to = &end_time;
|
||||
|
||||
if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
|
||||
|| __get_user(sec, &tvp->tv_sec)
|
||||
|| __get_user(usec, &tvp->tv_usec)) {
|
||||
@ -999,14 +998,13 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
|
||||
if (sec < 0 || usec < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if ((unsigned long) sec < MAX_SELECT_SECONDS) {
|
||||
timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
|
||||
timeout += sec * (unsigned long) HZ;
|
||||
}
|
||||
if (poll_select_set_timeout(to, sec, usec * NSEC_PER_USEC))
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
/* OSF does not copy back the remaining time. */
|
||||
return core_sys_select(n, inp, outp, exp, &timeout);
|
||||
return core_sys_select(n, inp, outp, exp, to);
|
||||
}
|
||||
|
||||
struct rusage32 {
|
||||
|
@ -106,7 +106,7 @@ op_axp_stop(void)
|
||||
}
|
||||
|
||||
static int
|
||||
op_axp_create_files(struct super_block * sb, struct dentry * root)
|
||||
op_axp_create_files(struct super_block *sb, struct dentry *root)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -355,7 +355,7 @@ config ARCH_IXP4XX
|
||||
select GENERIC_GPIO
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ZONE_DMA if PCI
|
||||
select DMABOUNCE if PCI
|
||||
help
|
||||
Support for Intel's IXP4XX (XScale) family of processors.
|
||||
|
||||
@ -539,16 +539,15 @@ config ARCH_OMAP
|
||||
help
|
||||
Support for TI's OMAP platform (OMAP1 and OMAP2).
|
||||
|
||||
config ARCH_MSM7X00A
|
||||
bool "Qualcomm MSM7X00A"
|
||||
config ARCH_MSM
|
||||
bool "Qualcomm MSM"
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Qualcomm MSM7X00A based systems. This runs on the ARM11
|
||||
apps processor of the MSM7X00A and depends on a shared memory
|
||||
Support for Qualcomm MSM7K based systems. This runs on the ARM11
|
||||
apps processor of the MSM7K and depends on a shared memory
|
||||
interface to the ARM9 modem processor which runs the baseband stack
|
||||
and controls some vital subsystems (clock and power control, etc).
|
||||
<http://www.cdmatech.com/products/msm7200_chipset_solution.jsp>
|
||||
|
||||
endchoice
|
||||
|
||||
@ -1255,6 +1254,8 @@ source "drivers/hid/Kconfig"
|
||||
|
||||
source "drivers/usb/Kconfig"
|
||||
|
||||
source "drivers/uwb/Kconfig"
|
||||
|
||||
source "drivers/mmc/Kconfig"
|
||||
|
||||
source "drivers/memstick/Kconfig"
|
||||
|
@ -141,7 +141,7 @@ endif
|
||||
machine-$(CONFIG_ARCH_MX3) := mx3
|
||||
machine-$(CONFIG_ARCH_ORION5X) := orion5x
|
||||
plat-$(CONFIG_PLAT_ORION) := orion
|
||||
machine-$(CONFIG_ARCH_MSM7X00A) := msm
|
||||
machine-$(CONFIG_ARCH_MSM) := msm
|
||||
machine-$(CONFIG_ARCH_LOKI) := loki
|
||||
machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
|
||||
|
||||
|
@ -13,10 +13,10 @@ config ICST307
|
||||
config SA1111
|
||||
bool
|
||||
select DMABOUNCE if !ARCH_PXA
|
||||
select ZONE_DMA if !ARCH_PXA
|
||||
|
||||
config DMABOUNCE
|
||||
bool
|
||||
select ZONE_DMA
|
||||
|
||||
config TIMER_ACORN
|
||||
bool
|
||||
|
@ -581,6 +581,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DMABOUNCE
|
||||
/*
|
||||
* If the parent device has a DMA mask associated with it,
|
||||
* propagate it down to the children.
|
||||
@ -598,6 +599,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@ -937,7 +939,7 @@ static int sa1111_resume(struct platform_device *dev)
|
||||
#define sa1111_resume NULL
|
||||
#endif
|
||||
|
||||
static int sa1111_probe(struct platform_device *pdev)
|
||||
static int __devinit sa1111_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -133,7 +133,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
# CONFIG_ARCH_LH7A40X is not set
|
||||
# CONFIG_ARCH_DAVINCI is not set
|
||||
# CONFIG_ARCH_OMAP is not set
|
||||
CONFIG_ARCH_MSM7X00A=y
|
||||
CONFIG_ARCH_MSM=y
|
||||
|
||||
#
|
||||
# Boot options
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -147,6 +147,7 @@ CONFIG_ARCH_PXA=y
|
||||
# CONFIG_MACH_MAINSTONE is not set
|
||||
# CONFIG_ARCH_PXA_IDP is not set
|
||||
# CONFIG_PXA_SHARPSL is not set
|
||||
CONFIG_TRIZEPS_PXA=y
|
||||
CONFIG_MACH_TRIZEPS4=y
|
||||
CONFIG_MACH_TRIZEPS4_CONXS=y
|
||||
# CONFIG_MACH_TRIZEPS4_ANY is not set
|
||||
|
@ -165,7 +165,7 @@
|
||||
__res = __m; \
|
||||
asm ( "umlal %Q0, %R0, %Q1, %Q2\n\t" \
|
||||
"mov %Q0, #0" \
|
||||
: "+r" (__res) \
|
||||
: "+&r" (__res) \
|
||||
: "r" (__m), "r" (__n) \
|
||||
: "cc" ); \
|
||||
} else { \
|
||||
@ -182,7 +182,7 @@
|
||||
"umlal %R0, %Q0, %Q1, %R2\n\t" \
|
||||
"mov %R0, #0\n\t" \
|
||||
"umlal %Q0, %R0, %R1, %R2" \
|
||||
: "+r" (__res) \
|
||||
: "+&r" (__res) \
|
||||
: "r" (__m), "r" (__n) \
|
||||
: "cc" ); \
|
||||
} else { \
|
||||
@ -192,7 +192,7 @@
|
||||
"adds %Q0, %1, %Q0\n\t" \
|
||||
"adc %R0, %R0, #0\n\t" \
|
||||
"umlal %Q0, %R0, %R2, %R3" \
|
||||
: "+r" (__res), "+r" (__z) \
|
||||
: "+&r" (__res), "+&r" (__z) \
|
||||
: "r" (__m), "r" (__n) \
|
||||
: "cc" ); \
|
||||
} \
|
||||
|
@ -404,6 +404,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
}
|
||||
|
||||
pin = bank->chipbase;
|
||||
gpio = &irq_desc[pin];
|
||||
|
||||
while (isr) {
|
||||
if (isr & 1) {
|
||||
|
@ -89,6 +89,8 @@
|
||||
* node 3: 0xd8000000 - 0xdfffffff
|
||||
*/
|
||||
#define NODE_MEM_SIZE_BITS 24
|
||||
#define SECTION_SIZE_BITS 24
|
||||
#define MAX_PHYSMEM_BITS 32
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -167,11 +167,6 @@ config MACH_GTWX5715
|
||||
|
||||
comment "IXP4xx Options"
|
||||
|
||||
config DMABOUNCE
|
||||
bool
|
||||
default y
|
||||
depends on PCI
|
||||
|
||||
config IXP4XX_INDIRECT_PCI
|
||||
bool "Use indirect PCI memory access"
|
||||
depends on PCI
|
||||
|
@ -2,4 +2,4 @@ obj-y += common.o addr-map.o irq.o pcie.o
|
||||
|
||||
obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6281-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/spi/orion_spi.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/mach/map.h>
|
||||
@ -151,6 +152,40 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet switch
|
||||
****************************************************************************/
|
||||
static struct resource kirkwood_switch_resources[] = {
|
||||
{
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device kirkwood_switch_device = {
|
||||
.name = "dsa",
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
.resource = kirkwood_switch_resources,
|
||||
};
|
||||
|
||||
void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq)
|
||||
{
|
||||
if (irq != NO_IRQ) {
|
||||
kirkwood_switch_resources[0].start = irq;
|
||||
kirkwood_switch_resources[0].end = irq;
|
||||
kirkwood_switch_device.num_resources = 1;
|
||||
}
|
||||
|
||||
d->mii_bus = &kirkwood_ge00_shared.dev;
|
||||
d->netdev = &kirkwood_ge00.dev;
|
||||
kirkwood_switch_device.dev.platform_data = d;
|
||||
|
||||
platform_device_register(&kirkwood_switch_device);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* SoC RTC
|
||||
****************************************************************************/
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef __ARCH_KIRKWOOD_COMMON_H
|
||||
#define __ARCH_KIRKWOOD_COMMON_H
|
||||
|
||||
struct dsa_platform_data;
|
||||
struct mv643xx_eth_platform_data;
|
||||
struct mv_sata_platform_data;
|
||||
|
||||
@ -29,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_ge00_switch_init(struct dsa_platform_data *d, int irq);
|
||||
void kirkwood_pcie_init(void);
|
||||
void kirkwood_rtc_init(void);
|
||||
void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
@ -74,6 +75,15 @@ static struct mv643xx_eth_platform_data rd88f6281_ge00_data = {
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct dsa_platform_data rd88f6281_switch_data = {
|
||||
.port_names[0] = "lan1",
|
||||
.port_names[1] = "lan2",
|
||||
.port_names[2] = "lan3",
|
||||
.port_names[3] = "lan4",
|
||||
.port_names[4] = "wan",
|
||||
.port_names[5] = "cpu",
|
||||
};
|
||||
|
||||
static struct mv_sata_platform_data rd88f6281_sata_data = {
|
||||
.n_ports = 2,
|
||||
};
|
||||
@ -87,6 +97,7 @@ static void __init rd88f6281_init(void)
|
||||
|
||||
kirkwood_ehci_init();
|
||||
kirkwood_ge00_init(&rd88f6281_ge00_data);
|
||||
kirkwood_ge00_switch_init(&rd88f6281_switch_data, NO_IRQ);
|
||||
kirkwood_rtc_init();
|
||||
kirkwood_sata_init(&rd88f6281_sata_data);
|
||||
kirkwood_uart0_init();
|
||||
|
@ -1,18 +1,13 @@
|
||||
if ARCH_MSM7X00A
|
||||
if ARCH_MSM
|
||||
|
||||
comment "MSM7X00A Board Type"
|
||||
depends on ARCH_MSM7X00A
|
||||
comment "MSM Board Type"
|
||||
depends on ARCH_MSM
|
||||
|
||||
config MACH_HALIBUT
|
||||
depends on ARCH_MSM7X00A
|
||||
depends on ARCH_MSM
|
||||
default y
|
||||
bool "Halibut Board (QCT SURF7200A)"
|
||||
bool "Halibut Board (QCT SURF7201A)"
|
||||
help
|
||||
Support for the Qualcomm SURF7200A eval board.
|
||||
|
||||
config MSM7X00A_IDLE
|
||||
depends on ARCH_MSM7X00A
|
||||
default y
|
||||
bool "Idle Support for MSM7X00A"
|
||||
Support for the Qualcomm SURF7201A eval board.
|
||||
|
||||
endif
|
||||
|
@ -1,7 +1,8 @@
|
||||
obj-y += io.o idle.o irq.o timer.o dma.o
|
||||
|
||||
# Common code for board init
|
||||
obj-y += common.o
|
||||
obj-y += devices.o
|
||||
obj-y += proc_comm.o
|
||||
obj-y += vreg.o
|
||||
obj-y += clock.o clock-7x01a.o
|
||||
|
||||
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include "devices.h"
|
||||
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x9C004300,
|
||||
@ -53,31 +55,12 @@ static struct platform_device smc91x_device = {
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
|
||||
static void mddi0_panel_power(int on)
|
||||
{
|
||||
}
|
||||
|
||||
static struct msm_mddi_platform_data msm_mddi0_pdata = {
|
||||
.panel_power = mddi0_panel_power,
|
||||
.has_vsync_irq = 0,
|
||||
};
|
||||
|
||||
static struct platform_device msm_mddi0_device = {
|
||||
.name = "msm_mddi",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &msm_mddi0_pdata
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_serial0_device = {
|
||||
.name = "msm_serial",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&msm_serial0_device,
|
||||
&msm_mddi0_device,
|
||||
&msm_device_uart3,
|
||||
&msm_device_smd,
|
||||
&msm_device_nand,
|
||||
&msm_device_hsusb,
|
||||
&msm_device_i2c,
|
||||
&smc91x_device,
|
||||
};
|
||||
|
||||
@ -91,20 +74,15 @@ static void __init halibut_init_irq(void)
|
||||
static void __init halibut_init(void)
|
||||
{
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
msm_add_devices();
|
||||
}
|
||||
|
||||
static void __init halibut_map_io(void)
|
||||
{
|
||||
msm_map_common_io();
|
||||
msm_clock_init();
|
||||
}
|
||||
|
||||
MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
|
||||
|
||||
/* UART for LL DEBUG */
|
||||
.phys_io = MSM_UART1_PHYS,
|
||||
.io_pg_offst = ((MSM_UART1_BASE) >> 18) & 0xfffc,
|
||||
|
||||
.boot_params = 0x10000100,
|
||||
.map_io = halibut_map_io,
|
||||
.init_irq = halibut_init_irq,
|
||||
|
126
arch/arm/mach-msm/clock-7x01a.c
Normal file
126
arch/arm/mach-msm/clock-7x01a.c
Normal file
@ -0,0 +1,126 @@
|
||||
/* arch/arm/mach-msm/clock-7x01a.c
|
||||
*
|
||||
* Clock tables for MSM7X01A
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "devices.h"
|
||||
|
||||
/* clock IDs used by the modem processor */
|
||||
|
||||
#define ACPU_CLK 0 /* Applications processor clock */
|
||||
#define ADM_CLK 1 /* Applications data mover clock */
|
||||
#define ADSP_CLK 2 /* ADSP clock */
|
||||
#define EBI1_CLK 3 /* External bus interface 1 clock */
|
||||
#define EBI2_CLK 4 /* External bus interface 2 clock */
|
||||
#define ECODEC_CLK 5 /* External CODEC clock */
|
||||
#define EMDH_CLK 6 /* External MDDI host clock */
|
||||
#define GP_CLK 7 /* General purpose clock */
|
||||
#define GRP_CLK 8 /* Graphics clock */
|
||||
#define I2C_CLK 9 /* I2C clock */
|
||||
#define ICODEC_RX_CLK 10 /* Internal CODEX RX clock */
|
||||
#define ICODEC_TX_CLK 11 /* Internal CODEX TX clock */
|
||||
#define IMEM_CLK 12 /* Internal graphics memory clock */
|
||||
#define MDC_CLK 13 /* MDDI client clock */
|
||||
#define MDP_CLK 14 /* Mobile display processor clock */
|
||||
#define PBUS_CLK 15 /* Peripheral bus clock */
|
||||
#define PCM_CLK 16 /* PCM clock */
|
||||
#define PMDH_CLK 17 /* Primary MDDI host clock */
|
||||
#define SDAC_CLK 18 /* Stereo DAC clock */
|
||||
#define SDC1_CLK 19 /* Secure Digital Card clocks */
|
||||
#define SDC1_PCLK 20
|
||||
#define SDC2_CLK 21
|
||||
#define SDC2_PCLK 22
|
||||
#define SDC3_CLK 23
|
||||
#define SDC3_PCLK 24
|
||||
#define SDC4_CLK 25
|
||||
#define SDC4_PCLK 26
|
||||
#define TSIF_CLK 27 /* Transport Stream Interface clocks */
|
||||
#define TSIF_REF_CLK 28
|
||||
#define TV_DAC_CLK 29 /* TV clocks */
|
||||
#define TV_ENC_CLK 30
|
||||
#define UART1_CLK 31 /* UART clocks */
|
||||
#define UART2_CLK 32
|
||||
#define UART3_CLK 33
|
||||
#define UART1DM_CLK 34
|
||||
#define UART2DM_CLK 35
|
||||
#define USB_HS_CLK 36 /* High speed USB core clock */
|
||||
#define USB_HS_PCLK 37 /* High speed USB pbus clock */
|
||||
#define USB_OTG_CLK 38 /* Full speed USB clock */
|
||||
#define VDC_CLK 39 /* Video controller clock */
|
||||
#define VFE_CLK 40 /* Camera / Video Front End clock */
|
||||
#define VFE_MDC_CLK 41 /* VFE MDDI client clock */
|
||||
|
||||
#define NR_CLKS 42
|
||||
|
||||
#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) { \
|
||||
.name = clk_name, \
|
||||
.id = clk_id, \
|
||||
.flags = clk_flags, \
|
||||
.dev = clk_dev, \
|
||||
}
|
||||
|
||||
#define OFF CLKFLAG_AUTO_OFF
|
||||
#define MINMAX CLKFLAG_USE_MIN_MAX_TO_SET
|
||||
|
||||
struct clk msm_clocks[] = {
|
||||
CLOCK("adm_clk", ADM_CLK, NULL, 0),
|
||||
CLOCK("adsp_clk", ADSP_CLK, NULL, 0),
|
||||
CLOCK("ebi1_clk", EBI1_CLK, NULL, 0),
|
||||
CLOCK("ebi2_clk", EBI2_CLK, NULL, 0),
|
||||
CLOCK("ecodec_clk", ECODEC_CLK, NULL, 0),
|
||||
CLOCK("emdh_clk", EMDH_CLK, NULL, OFF),
|
||||
CLOCK("gp_clk", GP_CLK, NULL, 0),
|
||||
CLOCK("grp_clk", GRP_CLK, NULL, OFF),
|
||||
CLOCK("i2c_clk", I2C_CLK, &msm_device_i2c.dev, 0),
|
||||
CLOCK("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0),
|
||||
CLOCK("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0),
|
||||
CLOCK("imem_clk", IMEM_CLK, NULL, OFF),
|
||||
CLOCK("mdc_clk", MDC_CLK, NULL, 0),
|
||||
CLOCK("mdp_clk", MDP_CLK, NULL, OFF),
|
||||
CLOCK("pbus_clk", PBUS_CLK, NULL, 0),
|
||||
CLOCK("pcm_clk", PCM_CLK, NULL, 0),
|
||||
CLOCK("pmdh_clk", PMDH_CLK, NULL, OFF | MINMAX),
|
||||
CLOCK("sdac_clk", SDAC_CLK, NULL, OFF),
|
||||
CLOCK("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
|
||||
CLOCK("sdc_pclk", SDC1_PCLK, &msm_device_sdc1.dev, OFF),
|
||||
CLOCK("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
|
||||
CLOCK("sdc_pclk", SDC2_PCLK, &msm_device_sdc2.dev, OFF),
|
||||
CLOCK("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
|
||||
CLOCK("sdc_pclk", SDC3_PCLK, &msm_device_sdc3.dev, OFF),
|
||||
CLOCK("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
|
||||
CLOCK("sdc_pclk", SDC4_PCLK, &msm_device_sdc4.dev, OFF),
|
||||
CLOCK("tsif_clk", TSIF_CLK, NULL, 0),
|
||||
CLOCK("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
|
||||
CLOCK("tv_dac_clk", TV_DAC_CLK, NULL, 0),
|
||||
CLOCK("tv_enc_clk", TV_ENC_CLK, NULL, 0),
|
||||
CLOCK("uart_clk", UART1_CLK, &msm_device_uart1.dev, OFF),
|
||||
CLOCK("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
|
||||
CLOCK("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
|
||||
CLOCK("uart1dm_clk", UART1DM_CLK, NULL, OFF),
|
||||
CLOCK("uart2dm_clk", UART2DM_CLK, NULL, 0),
|
||||
CLOCK("usb_hs_clk", USB_HS_CLK, &msm_device_hsusb.dev, OFF),
|
||||
CLOCK("usb_hs_pclk", USB_HS_PCLK, &msm_device_hsusb.dev, OFF),
|
||||
CLOCK("usb_otg_clk", USB_OTG_CLK, NULL, 0),
|
||||
CLOCK("vdc_clk", VDC_CLK, NULL, OFF | MINMAX),
|
||||
CLOCK("vfe_clk", VFE_CLK, NULL, OFF),
|
||||
CLOCK("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF),
|
||||
};
|
||||
|
||||
unsigned msm_num_clocks = ARRAY_SIZE(msm_clocks);
|
218
arch/arm/mach-msm/clock.c
Normal file
218
arch/arm/mach-msm/clock.c
Normal file
@ -0,0 +1,218 @@
|
||||
/* arch/arm/mach-msm/clock.c
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "proc_comm.h"
|
||||
|
||||
static DEFINE_MUTEX(clocks_mutex);
|
||||
static DEFINE_SPINLOCK(clocks_lock);
|
||||
static LIST_HEAD(clocks);
|
||||
|
||||
/*
|
||||
* glue for the proc_comm interface
|
||||
*/
|
||||
static inline int pc_clk_enable(unsigned id)
|
||||
{
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
|
||||
}
|
||||
|
||||
static inline void pc_clk_disable(unsigned id)
|
||||
{
|
||||
msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
|
||||
}
|
||||
|
||||
static inline int pc_clk_set_rate(unsigned id, unsigned rate)
|
||||
{
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
|
||||
}
|
||||
|
||||
static inline int pc_clk_set_min_rate(unsigned id, unsigned rate)
|
||||
{
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
|
||||
}
|
||||
|
||||
static inline int pc_clk_set_max_rate(unsigned id, unsigned rate)
|
||||
{
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
|
||||
}
|
||||
|
||||
static inline int pc_clk_set_flags(unsigned id, unsigned flags)
|
||||
{
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags);
|
||||
}
|
||||
|
||||
static inline unsigned pc_clk_get_rate(unsigned id)
|
||||
{
|
||||
if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
|
||||
return 0;
|
||||
else
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline unsigned pc_clk_is_enabled(unsigned id)
|
||||
{
|
||||
if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
|
||||
return 0;
|
||||
else
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int pc_pll_request(unsigned id, unsigned on)
|
||||
{
|
||||
on = !!on;
|
||||
return msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard clock functions defined in include/linux/clk.h
|
||||
*/
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
mutex_lock(&clocks_mutex);
|
||||
|
||||
list_for_each_entry(clk, &clocks, list)
|
||||
if (!strcmp(id, clk->name) && clk->dev == dev)
|
||||
goto found_it;
|
||||
|
||||
list_for_each_entry(clk, &clocks, list)
|
||||
if (!strcmp(id, clk->name) && clk->dev == NULL)
|
||||
goto found_it;
|
||||
|
||||
clk = ERR_PTR(-ENOENT);
|
||||
found_it:
|
||||
mutex_unlock(&clocks_mutex);
|
||||
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;
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
clk->count++;
|
||||
if (clk->count == 1)
|
||||
pc_clk_enable(clk->id);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
BUG_ON(clk->count == 0);
|
||||
clk->count--;
|
||||
if (clk->count == 0)
|
||||
pc_clk_disable(clk->id);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return pc_clk_get_rate(clk->id);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int ret;
|
||||
if (clk->flags & CLKFLAG_USE_MIN_MAX_TO_SET) {
|
||||
ret = pc_clk_set_max_rate(clk->id, rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
return pc_clk_set_min_rate(clk->id, rate);
|
||||
}
|
||||
return pc_clk_set_rate(clk->id, rate);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_parent);
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_parent);
|
||||
|
||||
int clk_set_flags(struct clk *clk, unsigned long flags)
|
||||
{
|
||||
if (clk == NULL || IS_ERR(clk))
|
||||
return -EINVAL;
|
||||
return pc_clk_set_flags(clk->id, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_flags);
|
||||
|
||||
|
||||
void __init msm_clock_init(void)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
spin_lock_init(&clocks_lock);
|
||||
mutex_lock(&clocks_mutex);
|
||||
for (n = 0; n < msm_num_clocks; n++)
|
||||
list_add_tail(&msm_clocks[n].list, &clocks);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
|
||||
/* The bootloader and/or AMSS may have left various clocks enabled.
|
||||
* Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
|
||||
* not been explicitly enabled by a clk_enable() call.
|
||||
*/
|
||||
static int __init clock_late_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct clk *clk;
|
||||
unsigned count = 0;
|
||||
|
||||
mutex_lock(&clocks_mutex);
|
||||
list_for_each_entry(clk, &clocks, list) {
|
||||
if (clk->flags & CLKFLAG_AUTO_OFF) {
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
if (!clk->count) {
|
||||
count++;
|
||||
pc_clk_disable(clk->id);
|
||||
}
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&clocks_mutex);
|
||||
pr_info("clock_late_init() disabled %d unused clocks\n", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(clock_late_init);
|
48
arch/arm/mach-msm/clock.h
Normal file
48
arch/arm/mach-msm/clock.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* arch/arm/mach-msm/clock.h
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
|
||||
#define __ARCH_ARM_MACH_MSM_CLOCK_H
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#define CLKFLAG_INVERT 0x00000001
|
||||
#define CLKFLAG_NOINVERT 0x00000002
|
||||
#define CLKFLAG_NONEST 0x00000004
|
||||
#define CLKFLAG_NORESET 0x00000008
|
||||
|
||||
#define CLK_FIRST_AVAILABLE_FLAG 0x00000100
|
||||
#define CLKFLAG_USE_MIN_MAX_TO_SET 0x00000200
|
||||
#define CLKFLAG_AUTO_OFF 0x00000400
|
||||
|
||||
struct clk {
|
||||
uint32_t id;
|
||||
uint32_t count;
|
||||
uint32_t flags;
|
||||
const char *name;
|
||||
struct list_head list;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
|
||||
#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
|
||||
#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
|
||||
|
||||
extern struct clk msm_clocks[];
|
||||
extern unsigned msm_num_clocks;
|
||||
|
||||
#endif
|
||||
|
@ -1,116 +0,0 @@
|
||||
/* linux/arch/arm/mach-msm/common.c
|
||||
*
|
||||
* Common setup code for MSM7K Boards
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
|
||||
struct flash_platform_data msm_nand_data = {
|
||||
.parts = 0,
|
||||
.nr_parts = 0,
|
||||
};
|
||||
|
||||
static struct resource msm_nand_resources[] = {
|
||||
[0] = {
|
||||
.start = 7,
|
||||
.end = 7,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_nand_device = {
|
||||
.name = "msm_nand",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(msm_nand_resources),
|
||||
.resource = msm_nand_resources,
|
||||
.dev = {
|
||||
.platform_data = &msm_nand_data,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_smd_device = {
|
||||
.name = "msm_smd",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct resource msm_i2c_resources[] = {
|
||||
{
|
||||
.start = MSM_I2C_BASE,
|
||||
.end = MSM_I2C_BASE + MSM_I2C_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_PWB_I2C,
|
||||
.end = INT_PWB_I2C,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_i2c_device = {
|
||||
.name = "msm_i2c",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_i2c_resources),
|
||||
.resource = msm_i2c_resources,
|
||||
};
|
||||
|
||||
static struct resource usb_resources[] = {
|
||||
{
|
||||
.start = MSM_HSUSB_PHYS,
|
||||
.end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_USB_HS,
|
||||
.end = INT_USB_HS,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_hsusb_device = {
|
||||
.name = "msm_hsusb",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(usb_resources),
|
||||
.resource = usb_resources,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&msm_nand_device,
|
||||
&msm_smd_device,
|
||||
&msm_i2c_device,
|
||||
&msm_hsusb_device,
|
||||
};
|
||||
|
||||
void __init msm_add_devices(void)
|
||||
{
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
267
arch/arm/mach-msm/devices.c
Normal file
267
arch/arm/mach-msm/devices.c
Normal file
@ -0,0 +1,267 @@
|
||||
/* linux/arch/arm/mach-msm/devices.c
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include "devices.h"
|
||||
|
||||
#include <asm/mach/flash.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
static struct resource resources_uart1[] = {
|
||||
{
|
||||
.start = INT_UART1,
|
||||
.end = INT_UART1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = MSM_UART1_PHYS,
|
||||
.end = MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource resources_uart2[] = {
|
||||
{
|
||||
.start = INT_UART2,
|
||||
.end = INT_UART2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = MSM_UART2_PHYS,
|
||||
.end = MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource resources_uart3[] = {
|
||||
{
|
||||
.start = INT_UART3,
|
||||
.end = INT_UART3,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = MSM_UART3_PHYS,
|
||||
.end = MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_uart1 = {
|
||||
.name = "msm_serial",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(resources_uart1),
|
||||
.resource = resources_uart1,
|
||||
};
|
||||
|
||||
struct platform_device msm_device_uart2 = {
|
||||
.name = "msm_serial",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(resources_uart2),
|
||||
.resource = resources_uart2,
|
||||
};
|
||||
|
||||
struct platform_device msm_device_uart3 = {
|
||||
.name = "msm_serial",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(resources_uart3),
|
||||
.resource = resources_uart3,
|
||||
};
|
||||
|
||||
static struct resource resources_i2c[] = {
|
||||
{
|
||||
.start = MSM_I2C_PHYS,
|
||||
.end = MSM_I2C_PHYS + MSM_I2C_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_PWB_I2C,
|
||||
.end = INT_PWB_I2C,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_i2c = {
|
||||
.name = "msm_i2c",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(resources_i2c),
|
||||
.resource = resources_i2c,
|
||||
};
|
||||
|
||||
static struct resource resources_hsusb[] = {
|
||||
{
|
||||
.start = MSM_HSUSB_PHYS,
|
||||
.end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_USB_HS,
|
||||
.end = INT_USB_HS,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_hsusb = {
|
||||
.name = "msm_hsusb",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(resources_hsusb),
|
||||
.resource = resources_hsusb,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
struct flash_platform_data msm_nand_data = {
|
||||
.parts = NULL,
|
||||
.nr_parts = 0,
|
||||
};
|
||||
|
||||
static struct resource resources_nand[] = {
|
||||
[0] = {
|
||||
.start = 7,
|
||||
.end = 7,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_nand = {
|
||||
.name = "msm_nand",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(resources_nand),
|
||||
.resource = resources_nand,
|
||||
.dev = {
|
||||
.platform_data = &msm_nand_data,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_smd = {
|
||||
.name = "msm_smd",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct resource resources_sdc1[] = {
|
||||
{
|
||||
.start = MSM_SDC1_PHYS,
|
||||
.end = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_SDC1_0,
|
||||
.end = INT_SDC1_1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = 8,
|
||||
.end = 8,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource resources_sdc2[] = {
|
||||
{
|
||||
.start = MSM_SDC2_PHYS,
|
||||
.end = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_SDC2_0,
|
||||
.end = INT_SDC2_1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = 8,
|
||||
.end = 8,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource resources_sdc3[] = {
|
||||
{
|
||||
.start = MSM_SDC3_PHYS,
|
||||
.end = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_SDC3_0,
|
||||
.end = INT_SDC3_1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = 8,
|
||||
.end = 8,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource resources_sdc4[] = {
|
||||
{
|
||||
.start = MSM_SDC4_PHYS,
|
||||
.end = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_SDC4_0,
|
||||
.end = INT_SDC4_1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = 8,
|
||||
.end = 8,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_sdc1 = {
|
||||
.name = "msm_sdcc",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(resources_sdc1),
|
||||
.resource = resources_sdc1,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_sdc2 = {
|
||||
.name = "msm_sdcc",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(resources_sdc2),
|
||||
.resource = resources_sdc2,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_sdc3 = {
|
||||
.name = "msm_sdcc",
|
||||
.id = 3,
|
||||
.num_resources = ARRAY_SIZE(resources_sdc3),
|
||||
.resource = resources_sdc3,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_device_sdc4 = {
|
||||
.name = "msm_sdcc",
|
||||
.id = 4,
|
||||
.num_resources = ARRAY_SIZE(resources_sdc4),
|
||||
.resource = resources_sdc4,
|
||||
.dev = {
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
36
arch/arm/mach-msm/devices.h
Normal file
36
arch/arm/mach-msm/devices.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* linux/arch/arm/mach-msm/devices.h
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_MSM_DEVICES_H
|
||||
#define __ARCH_ARM_MACH_MSM_DEVICES_H
|
||||
|
||||
extern struct platform_device msm_device_uart1;
|
||||
extern struct platform_device msm_device_uart2;
|
||||
extern struct platform_device msm_device_uart3;
|
||||
|
||||
extern struct platform_device msm_device_sdc1;
|
||||
extern struct platform_device msm_device_sdc2;
|
||||
extern struct platform_device msm_device_sdc3;
|
||||
extern struct platform_device msm_device_sdc4;
|
||||
|
||||
extern struct platform_device msm_device_hsusb;
|
||||
|
||||
extern struct platform_device msm_device_i2c;
|
||||
|
||||
extern struct platform_device msm_device_smd;
|
||||
|
||||
extern struct platform_device msm_device_nand;
|
||||
|
||||
#endif
|
@ -26,7 +26,7 @@ enum {
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(msm_dmov_lock);
|
||||
static struct msm_dmov_cmd active_command;
|
||||
static unsigned int channel_active;
|
||||
static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
|
||||
static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
|
||||
unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
|
||||
@ -43,6 +43,11 @@ unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
|
||||
#define PRINT_FLOW(format, args...) \
|
||||
MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args);
|
||||
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
|
||||
{
|
||||
writel((graceful << 31), DMOV_FLUSH0(id));
|
||||
}
|
||||
|
||||
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
@ -60,6 +65,9 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
|
||||
#endif
|
||||
PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status);
|
||||
list_add_tail(&cmd->list, &active_commands[id]);
|
||||
if (!channel_active)
|
||||
enable_irq(INT_ADM_AARM);
|
||||
channel_active |= 1U << id;
|
||||
writel(cmd->cmdptr, DMOV_CMD_PTR(id));
|
||||
} else {
|
||||
if (list_empty(&active_commands[id]))
|
||||
@ -76,21 +84,19 @@ struct msm_dmov_exec_cmdptr_cmd {
|
||||
struct completion complete;
|
||||
unsigned id;
|
||||
unsigned int result;
|
||||
unsigned int flush[6];
|
||||
struct msm_dmov_errdata err;
|
||||
};
|
||||
|
||||
static void dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, unsigned int result)
|
||||
static void
|
||||
dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd,
|
||||
unsigned int result,
|
||||
struct msm_dmov_errdata *err)
|
||||
{
|
||||
struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd);
|
||||
cmd->result = result;
|
||||
if (result != 0x80000002) {
|
||||
cmd->flush[0] = readl(DMOV_FLUSH0(cmd->id));
|
||||
cmd->flush[1] = readl(DMOV_FLUSH1(cmd->id));
|
||||
cmd->flush[2] = readl(DMOV_FLUSH2(cmd->id));
|
||||
cmd->flush[3] = readl(DMOV_FLUSH3(cmd->id));
|
||||
cmd->flush[4] = readl(DMOV_FLUSH4(cmd->id));
|
||||
cmd->flush[5] = readl(DMOV_FLUSH5(cmd->id));
|
||||
}
|
||||
if (result != 0x80000002 && err)
|
||||
memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata));
|
||||
|
||||
complete(&cmd->complete);
|
||||
}
|
||||
|
||||
@ -111,7 +117,7 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
|
||||
if (cmd.result != 0x80000002) {
|
||||
PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result);
|
||||
PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n",
|
||||
id, cmd.flush[0], cmd.flush[1], cmd.flush[2], cmd.flush[3]);
|
||||
id, cmd.err.flush[0], cmd.err.flush[1], cmd.err.flush[2], cmd.err.flush[3]);
|
||||
return -EIO;
|
||||
}
|
||||
PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr);
|
||||
@ -159,25 +165,40 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
|
||||
"for %p, result %x\n", id, cmd, ch_result);
|
||||
if (cmd) {
|
||||
list_del(&cmd->list);
|
||||
cmd->complete_func(cmd, ch_result);
|
||||
cmd->complete_func(cmd, ch_result, NULL);
|
||||
}
|
||||
}
|
||||
if (ch_result & DMOV_RSLT_FLUSH) {
|
||||
unsigned int flush0 = readl(DMOV_FLUSH0(id));
|
||||
struct msm_dmov_errdata errdata;
|
||||
|
||||
errdata.flush[0] = readl(DMOV_FLUSH0(id));
|
||||
errdata.flush[1] = readl(DMOV_FLUSH1(id));
|
||||
errdata.flush[2] = readl(DMOV_FLUSH2(id));
|
||||
errdata.flush[3] = readl(DMOV_FLUSH3(id));
|
||||
errdata.flush[4] = readl(DMOV_FLUSH4(id));
|
||||
errdata.flush[5] = readl(DMOV_FLUSH5(id));
|
||||
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
|
||||
PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, flush0);
|
||||
PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
|
||||
if (cmd) {
|
||||
list_del(&cmd->list);
|
||||
cmd->complete_func(cmd, ch_result);
|
||||
cmd->complete_func(cmd, ch_result, &errdata);
|
||||
}
|
||||
}
|
||||
if (ch_result & DMOV_RSLT_ERROR) {
|
||||
unsigned int flush0 = readl(DMOV_FLUSH0(id));
|
||||
struct msm_dmov_errdata errdata;
|
||||
|
||||
errdata.flush[0] = readl(DMOV_FLUSH0(id));
|
||||
errdata.flush[1] = readl(DMOV_FLUSH1(id));
|
||||
errdata.flush[2] = readl(DMOV_FLUSH2(id));
|
||||
errdata.flush[3] = readl(DMOV_FLUSH3(id));
|
||||
errdata.flush[4] = readl(DMOV_FLUSH4(id));
|
||||
errdata.flush[5] = readl(DMOV_FLUSH5(id));
|
||||
|
||||
PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
|
||||
PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, flush0);
|
||||
PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
|
||||
if (cmd) {
|
||||
list_del(&cmd->list);
|
||||
cmd->complete_func(cmd, ch_result);
|
||||
cmd->complete_func(cmd, ch_result, &errdata);
|
||||
}
|
||||
/* this does not seem to work, once we get an error */
|
||||
/* the datamover will no longer accept commands */
|
||||
@ -193,8 +214,14 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
|
||||
writel(cmd->cmdptr, DMOV_CMD_PTR(id));
|
||||
}
|
||||
} while (ch_status & DMOV_STATUS_RSLT_VALID);
|
||||
if (list_empty(&active_commands[id]) && list_empty(&ready_commands[id]))
|
||||
channel_active &= ~(1U << id);
|
||||
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
|
||||
}
|
||||
|
||||
if (!channel_active)
|
||||
disable_irq(INT_ADM_AARM);
|
||||
|
||||
spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -202,12 +229,17 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
|
||||
static int __init msm_init_datamover(void)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) {
|
||||
INIT_LIST_HEAD(&ready_commands[i]);
|
||||
INIT_LIST_HEAD(&active_commands[i]);
|
||||
writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i));
|
||||
}
|
||||
return request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
|
||||
ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
disable_irq(INT_ADM_AARM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(msm_init_datamover);
|
||||
|
@ -33,5 +33,6 @@ void __init msm_add_devices(void);
|
||||
void __init msm_map_common_io(void);
|
||||
void __init msm_init_irq(void);
|
||||
void __init msm_init_gpio(void);
|
||||
void __init msm_clock_init(void);
|
||||
|
||||
#endif
|
||||
|
@ -22,18 +22,22 @@
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1
|
||||
ldreq \rx, =MSM_UART1_PHYS
|
||||
ldrne \rx, =MSM_UART1_BASE
|
||||
movne \rx, #0
|
||||
.endm
|
||||
|
||||
.macro senduart,rd,rx
|
||||
str \rd, [\rx, #0x0C]
|
||||
teq \rx, #0
|
||||
strne \rd, [\rx, #0x0C]
|
||||
.endm
|
||||
|
||||
.macro waituart,rd,rx
|
||||
@ wait for TX_READY
|
||||
teq \rx, #0
|
||||
bne 2f
|
||||
1: ldr \rd, [\rx, #0x08]
|
||||
tst \rd, #0x04
|
||||
beq 1b
|
||||
2:
|
||||
.endm
|
||||
|
||||
.macro busyuart,rd,rx
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* arch/arm/mach-msm/include/mach/dma.h
|
||||
/* linux/include/asm-arm/arch-msm/dma.h
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
*
|
||||
@ -18,17 +18,21 @@
|
||||
#include <linux/list.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
struct msm_dmov_errdata {
|
||||
uint32_t flush[6];
|
||||
};
|
||||
|
||||
struct msm_dmov_cmd {
|
||||
struct list_head list;
|
||||
unsigned int cmdptr;
|
||||
void (*complete_func)(struct msm_dmov_cmd *cmd, unsigned int result);
|
||||
/* void (*user_result_func)(struct msm_dmov_cmd *cmd); */
|
||||
void (*complete_func)(struct msm_dmov_cmd *cmd,
|
||||
unsigned int result,
|
||||
struct msm_dmov_errdata *err);
|
||||
};
|
||||
|
||||
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd);
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
|
||||
/* int msm_dmov_exec_cmd_etc(unsigned id, unsigned int cmdptr, int timeout, int interruptible); */
|
||||
|
||||
|
||||
|
||||
@ -122,6 +126,16 @@ typedef struct {
|
||||
unsigned _reserved;
|
||||
} dmov_sg;
|
||||
|
||||
/* Box mode */
|
||||
typedef struct {
|
||||
uint32_t cmd;
|
||||
uint32_t src_row_addr;
|
||||
uint32_t dst_row_addr;
|
||||
uint32_t src_dst_len;
|
||||
uint32_t num_rows;
|
||||
uint32_t row_offset;
|
||||
} dmov_box;
|
||||
|
||||
/* bits for the cmd field of the above structures */
|
||||
|
||||
#define CMD_LC (1 << 31) /* last command */
|
||||
|
@ -37,11 +37,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define MSM_VIC_BASE 0xE0000000
|
||||
#ifdef __ASSEMBLY__
|
||||
#define IOMEM(x) x
|
||||
#else
|
||||
#define IOMEM(x) ((void __force __iomem *)(x))
|
||||
#endif
|
||||
|
||||
#define MSM_VIC_BASE IOMEM(0xE0000000)
|
||||
#define MSM_VIC_PHYS 0xC0000000
|
||||
#define MSM_VIC_SIZE SZ_4K
|
||||
|
||||
#define MSM_CSR_BASE 0xE0001000
|
||||
#define MSM_CSR_BASE IOMEM(0xE0001000)
|
||||
#define MSM_CSR_PHYS 0xC0100000
|
||||
#define MSM_CSR_SIZE SZ_4K
|
||||
|
||||
@ -49,56 +55,67 @@
|
||||
#define MSM_GPT_BASE MSM_CSR_BASE
|
||||
#define MSM_GPT_SIZE SZ_4K
|
||||
|
||||
#define MSM_DMOV_BASE 0xE0002000
|
||||
#define MSM_DMOV_BASE IOMEM(0xE0002000)
|
||||
#define MSM_DMOV_PHYS 0xA9700000
|
||||
#define MSM_DMOV_SIZE SZ_4K
|
||||
|
||||
#define MSM_UART1_BASE 0xE0003000
|
||||
#define MSM_UART1_PHYS 0xA9A00000
|
||||
#define MSM_UART1_SIZE SZ_4K
|
||||
|
||||
#define MSM_UART2_BASE 0xE0004000
|
||||
#define MSM_UART2_PHYS 0xA9B00000
|
||||
#define MSM_UART2_SIZE SZ_4K
|
||||
|
||||
#define MSM_UART3_BASE 0xE0005000
|
||||
#define MSM_UART3_PHYS 0xA9C00000
|
||||
#define MSM_UART3_SIZE SZ_4K
|
||||
|
||||
#define MSM_I2C_BASE 0xE0006000
|
||||
#define MSM_I2C_PHYS 0xA9900000
|
||||
#define MSM_I2C_SIZE SZ_4K
|
||||
|
||||
#define MSM_GPIO1_BASE 0xE0007000
|
||||
#define MSM_GPIO1_BASE IOMEM(0xE0003000)
|
||||
#define MSM_GPIO1_PHYS 0xA9200000
|
||||
#define MSM_GPIO1_SIZE SZ_4K
|
||||
|
||||
#define MSM_GPIO2_BASE 0xE0008000
|
||||
#define MSM_GPIO2_BASE IOMEM(0xE0004000)
|
||||
#define MSM_GPIO2_PHYS 0xA9300000
|
||||
#define MSM_GPIO2_SIZE SZ_4K
|
||||
|
||||
#define MSM_HSUSB_BASE 0xE0009000
|
||||
#define MSM_HSUSB_PHYS 0xA0800000
|
||||
#define MSM_HSUSB_SIZE SZ_4K
|
||||
|
||||
#define MSM_CLK_CTL_BASE 0xE000A000
|
||||
#define MSM_CLK_CTL_BASE IOMEM(0xE0005000)
|
||||
#define MSM_CLK_CTL_PHYS 0xA8600000
|
||||
#define MSM_CLK_CTL_SIZE SZ_4K
|
||||
|
||||
#define MSM_PMDH_BASE 0xE000B000
|
||||
#define MSM_PMDH_PHYS 0xAA600000
|
||||
#define MSM_PMDH_SIZE SZ_4K
|
||||
|
||||
#define MSM_EMDH_BASE 0xE000C000
|
||||
#define MSM_EMDH_PHYS 0xAA700000
|
||||
#define MSM_EMDH_SIZE SZ_4K
|
||||
|
||||
#define MSM_MDP_BASE 0xE0010000
|
||||
#define MSM_MDP_PHYS 0xAA200000
|
||||
#define MSM_MDP_SIZE 0x000F0000
|
||||
|
||||
#define MSM_SHARED_RAM_BASE 0xE0100000
|
||||
#define MSM_SHARED_RAM_BASE IOMEM(0xE0100000)
|
||||
#define MSM_SHARED_RAM_PHYS 0x01F00000
|
||||
#define MSM_SHARED_RAM_SIZE SZ_1M
|
||||
|
||||
#define MSM_UART1_PHYS 0xA9A00000
|
||||
#define MSM_UART1_SIZE SZ_4K
|
||||
|
||||
#define MSM_UART2_PHYS 0xA9B00000
|
||||
#define MSM_UART2_SIZE SZ_4K
|
||||
|
||||
#define MSM_UART3_PHYS 0xA9C00000
|
||||
#define MSM_UART3_SIZE SZ_4K
|
||||
|
||||
#define MSM_SDC1_PHYS 0xA0400000
|
||||
#define MSM_SDC1_SIZE SZ_4K
|
||||
|
||||
#define MSM_SDC2_PHYS 0xA0500000
|
||||
#define MSM_SDC2_SIZE SZ_4K
|
||||
|
||||
#define MSM_SDC3_PHYS 0xA0600000
|
||||
#define MSM_SDC3_SIZE SZ_4K
|
||||
|
||||
#define MSM_SDC4_PHYS 0xA0700000
|
||||
#define MSM_SDC4_SIZE SZ_4K
|
||||
|
||||
#define MSM_I2C_PHYS 0xA9900000
|
||||
#define MSM_I2C_SIZE SZ_4K
|
||||
|
||||
#define MSM_HSUSB_PHYS 0xA0800000
|
||||
#define MSM_HSUSB_SIZE SZ_4K
|
||||
|
||||
#define MSM_PMDH_PHYS 0xAA600000
|
||||
#define MSM_PMDH_SIZE SZ_4K
|
||||
|
||||
#define MSM_EMDH_PHYS 0xAA700000
|
||||
#define MSM_EMDH_SIZE SZ_4K
|
||||
|
||||
#define MSM_MDP_PHYS 0xAA200000
|
||||
#define MSM_MDP_SIZE 0x000F0000
|
||||
|
||||
#define MSM_MDC_PHYS 0xAA500000
|
||||
#define MSM_MDC_SIZE SZ_1M
|
||||
|
||||
#define MSM_AD5_PHYS 0xAC000000
|
||||
#define MSM_AD5_SIZE (SZ_1M*13)
|
||||
|
||||
|
||||
#endif
|
||||
|
29
arch/arm/mach-msm/include/mach/vreg.h
Normal file
29
arch/arm/mach-msm/include/mach/vreg.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* linux/include/asm-arm/arch-msm/vreg.h
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_MSM_VREG_H
|
||||
#define __ARCH_ARM_MACH_MSM_VREG_H
|
||||
|
||||
struct vreg;
|
||||
|
||||
struct vreg *vreg_get(struct device *dev, const char *id);
|
||||
void vreg_put(struct vreg *vreg);
|
||||
|
||||
int vreg_enable(struct vreg *vreg);
|
||||
void vreg_disable(struct vreg *vreg);
|
||||
int vreg_set_level(struct vreg *vreg, unsigned mv);
|
||||
|
||||
#endif
|
@ -28,7 +28,7 @@
|
||||
#include <mach/board.h>
|
||||
|
||||
#define MSM_DEVICE(name) { \
|
||||
.virtual = MSM_##name##_BASE, \
|
||||
.virtual = (unsigned long) MSM_##name##_BASE, \
|
||||
.pfn = __phys_to_pfn(MSM_##name##_PHYS), \
|
||||
.length = MSM_##name##_SIZE, \
|
||||
.type = MT_DEVICE_NONSHARED, \
|
||||
@ -39,19 +39,11 @@ static struct map_desc msm_io_desc[] __initdata = {
|
||||
MSM_DEVICE(CSR),
|
||||
MSM_DEVICE(GPT),
|
||||
MSM_DEVICE(DMOV),
|
||||
MSM_DEVICE(UART1),
|
||||
MSM_DEVICE(UART2),
|
||||
MSM_DEVICE(UART3),
|
||||
MSM_DEVICE(I2C),
|
||||
MSM_DEVICE(GPIO1),
|
||||
MSM_DEVICE(GPIO2),
|
||||
MSM_DEVICE(HSUSB),
|
||||
MSM_DEVICE(CLK_CTL),
|
||||
MSM_DEVICE(PMDH),
|
||||
MSM_DEVICE(EMDH),
|
||||
MSM_DEVICE(MDP),
|
||||
{
|
||||
.virtual = MSM_SHARED_RAM_BASE,
|
||||
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
|
||||
.pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
|
||||
.length = MSM_SHARED_RAM_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
|
@ -66,20 +66,20 @@
|
||||
|
||||
static void msm_irq_ack(unsigned int irq)
|
||||
{
|
||||
unsigned reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
irq = 1 << (irq & 31);
|
||||
writel(irq, reg);
|
||||
}
|
||||
|
||||
static void msm_irq_mask(unsigned int irq)
|
||||
{
|
||||
unsigned reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
writel(1 << (irq & 31), reg);
|
||||
}
|
||||
|
||||
static void msm_irq_unmask(unsigned int irq)
|
||||
{
|
||||
unsigned reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
|
||||
writel(1 << (irq & 31), reg);
|
||||
}
|
||||
|
||||
@ -90,8 +90,8 @@ static int msm_irq_set_wake(unsigned int irq, unsigned int on)
|
||||
|
||||
static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
|
||||
{
|
||||
unsigned treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
|
||||
int b = 1 << (irq & 31);
|
||||
|
||||
if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
|
||||
|
110
arch/arm/mach-msm/proc_comm.c
Normal file
110
arch/arm/mach-msm/proc_comm.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* arch/arm/mach-msm/proc_comm.c
|
||||
*
|
||||
* Copyright (C) 2007-2008 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/system.h>
|
||||
|
||||
#include "proc_comm.h"
|
||||
|
||||
#define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4)
|
||||
|
||||
static inline void notify_other_proc_comm(void)
|
||||
{
|
||||
writel(1, MSM_A2M_INT(6));
|
||||
}
|
||||
|
||||
#define APP_COMMAND 0x00
|
||||
#define APP_STATUS 0x04
|
||||
#define APP_DATA1 0x08
|
||||
#define APP_DATA2 0x0C
|
||||
|
||||
#define MDM_COMMAND 0x10
|
||||
#define MDM_STATUS 0x14
|
||||
#define MDM_DATA1 0x18
|
||||
#define MDM_DATA2 0x1C
|
||||
|
||||
static DEFINE_SPINLOCK(proc_comm_lock);
|
||||
|
||||
/* The higher level SMD support will install this to
|
||||
* provide a way to check for and handle modem restart.
|
||||
*/
|
||||
int (*msm_check_for_modem_crash)(void);
|
||||
|
||||
/* Poll for a state change, checking for possible
|
||||
* modem crashes along the way (so we don't wait
|
||||
* forever while the ARM9 is blowing up).
|
||||
*
|
||||
* Return an error in the event of a modem crash and
|
||||
* restart so the msm_proc_comm() routine can restart
|
||||
* the operation from the beginning.
|
||||
*/
|
||||
static int proc_comm_wait_for(void __iomem *addr, unsigned value)
|
||||
{
|
||||
for (;;) {
|
||||
if (readl(addr) == value)
|
||||
return 0;
|
||||
|
||||
if (msm_check_for_modem_crash)
|
||||
if (msm_check_for_modem_crash())
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
|
||||
{
|
||||
void __iomem *base = MSM_SHARED_RAM_BASE;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&proc_comm_lock, flags);
|
||||
|
||||
for (;;) {
|
||||
if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
|
||||
continue;
|
||||
|
||||
writel(cmd, base + APP_COMMAND);
|
||||
writel(data1 ? *data1 : 0, base + APP_DATA1);
|
||||
writel(data2 ? *data2 : 0, base + APP_DATA2);
|
||||
|
||||
notify_other_proc_comm();
|
||||
|
||||
if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
|
||||
continue;
|
||||
|
||||
if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) {
|
||||
if (data1)
|
||||
*data1 = readl(base + APP_DATA1);
|
||||
if (data2)
|
||||
*data2 = readl(base + APP_DATA2);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
writel(PCOM_CMD_IDLE, base + APP_COMMAND);
|
||||
|
||||
spin_unlock_irqrestore(&proc_comm_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
165
arch/arm/mach-msm/proc_comm.h
Normal file
165
arch/arm/mach-msm/proc_comm.h
Normal file
@ -0,0 +1,165 @@
|
||||
/* arch/arm/mach-msm/proc_comm.h
|
||||
*
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ARCH_ARM_MACH_MSM_PROC_COMM_H_
|
||||
#define _ARCH_ARM_MACH_MSM_PROC_COMM_H_
|
||||
|
||||
enum {
|
||||
PCOM_CMD_IDLE = 0x0,
|
||||
PCOM_CMD_DONE,
|
||||
PCOM_RESET_APPS,
|
||||
PCOM_RESET_CHIP,
|
||||
PCOM_CONFIG_NAND_MPU,
|
||||
PCOM_CONFIG_USB_CLKS,
|
||||
PCOM_GET_POWER_ON_STATUS,
|
||||
PCOM_GET_WAKE_UP_STATUS,
|
||||
PCOM_GET_BATT_LEVEL,
|
||||
PCOM_CHG_IS_CHARGING,
|
||||
PCOM_POWER_DOWN,
|
||||
PCOM_USB_PIN_CONFIG,
|
||||
PCOM_USB_PIN_SEL,
|
||||
PCOM_SET_RTC_ALARM,
|
||||
PCOM_NV_READ,
|
||||
PCOM_NV_WRITE,
|
||||
PCOM_GET_UUID_HIGH,
|
||||
PCOM_GET_UUID_LOW,
|
||||
PCOM_GET_HW_ENTROPY,
|
||||
PCOM_RPC_GPIO_TLMM_CONFIG_REMOTE,
|
||||
PCOM_CLKCTL_RPC_ENABLE,
|
||||
PCOM_CLKCTL_RPC_DISABLE,
|
||||
PCOM_CLKCTL_RPC_RESET,
|
||||
PCOM_CLKCTL_RPC_SET_FLAGS,
|
||||
PCOM_CLKCTL_RPC_SET_RATE,
|
||||
PCOM_CLKCTL_RPC_MIN_RATE,
|
||||
PCOM_CLKCTL_RPC_MAX_RATE,
|
||||
PCOM_CLKCTL_RPC_RATE,
|
||||
PCOM_CLKCTL_RPC_PLL_REQUEST,
|
||||
PCOM_CLKCTL_RPC_ENABLED,
|
||||
PCOM_VREG_SWITCH,
|
||||
PCOM_VREG_SET_LEVEL,
|
||||
PCOM_GPIO_TLMM_CONFIG_GROUP,
|
||||
PCOM_GPIO_TLMM_UNCONFIG_GROUP,
|
||||
PCOM_NV_WRITE_BYTES_4_7,
|
||||
PCOM_CONFIG_DISP,
|
||||
PCOM_GET_FTM_BOOT_COUNT,
|
||||
PCOM_RPC_GPIO_TLMM_CONFIG_EX,
|
||||
PCOM_PM_MPP_CONFIG,
|
||||
PCOM_GPIO_IN,
|
||||
PCOM_GPIO_OUT,
|
||||
PCOM_RESET_MODEM,
|
||||
PCOM_RESET_CHIP_IMM,
|
||||
PCOM_PM_VID_EN,
|
||||
PCOM_VREG_PULLDOWN,
|
||||
PCOM_NUM_CMDS,
|
||||
};
|
||||
|
||||
enum {
|
||||
PCOM_INVALID_STATUS = 0x0,
|
||||
PCOM_READY,
|
||||
PCOM_CMD_RUNNING,
|
||||
PCOM_CMD_SUCCESS,
|
||||
PCOM_CMD_FAIL,
|
||||
};
|
||||
|
||||
/* List of VREGs that support the Pull Down Resistor setting. */
|
||||
enum {
|
||||
PM_VREG_PDOWN_MSMA_ID,
|
||||
PM_VREG_PDOWN_MSMP_ID,
|
||||
PM_VREG_PDOWN_MSME1_ID, /* Not supported in Panoramix */
|
||||
PM_VREG_PDOWN_MSMC1_ID, /* Not supported in PM6620 */
|
||||
PM_VREG_PDOWN_MSMC2_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_GP3_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_MSME2_ID, /* Supported in PM7500 and Panoramix only */
|
||||
PM_VREG_PDOWN_GP4_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_GP1_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_TCXO_ID,
|
||||
PM_VREG_PDOWN_PA_ID,
|
||||
PM_VREG_PDOWN_RFTX_ID,
|
||||
PM_VREG_PDOWN_RFRX1_ID,
|
||||
PM_VREG_PDOWN_RFRX2_ID,
|
||||
PM_VREG_PDOWN_SYNT_ID,
|
||||
PM_VREG_PDOWN_WLAN_ID,
|
||||
PM_VREG_PDOWN_USB_ID,
|
||||
PM_VREG_PDOWN_MMC_ID,
|
||||
PM_VREG_PDOWN_RUIM_ID,
|
||||
PM_VREG_PDOWN_MSMC0_ID, /* Supported in PM6610 only */
|
||||
PM_VREG_PDOWN_GP2_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_GP5_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_GP6_ID, /* Supported in PM7500 only */
|
||||
PM_VREG_PDOWN_RF_ID,
|
||||
PM_VREG_PDOWN_RF_VCO_ID,
|
||||
PM_VREG_PDOWN_MPLL_ID,
|
||||
PM_VREG_PDOWN_S2_ID,
|
||||
PM_VREG_PDOWN_S3_ID,
|
||||
PM_VREG_PDOWN_RFUBM_ID,
|
||||
|
||||
/* new for HAN */
|
||||
PM_VREG_PDOWN_RF1_ID,
|
||||
PM_VREG_PDOWN_RF2_ID,
|
||||
PM_VREG_PDOWN_RFA_ID,
|
||||
PM_VREG_PDOWN_CDC2_ID,
|
||||
PM_VREG_PDOWN_RFTX2_ID,
|
||||
PM_VREG_PDOWN_USIM_ID,
|
||||
PM_VREG_PDOWN_USB2P6_ID,
|
||||
PM_VREG_PDOWN_USB3P3_ID,
|
||||
PM_VREG_PDOWN_INVALID_ID,
|
||||
|
||||
/* backward compatible enums only */
|
||||
PM_VREG_PDOWN_CAM_ID = PM_VREG_PDOWN_GP1_ID,
|
||||
PM_VREG_PDOWN_MDDI_ID = PM_VREG_PDOWN_GP2_ID,
|
||||
PM_VREG_PDOWN_RUIM2_ID = PM_VREG_PDOWN_GP3_ID,
|
||||
PM_VREG_PDOWN_AUX_ID = PM_VREG_PDOWN_GP4_ID,
|
||||
PM_VREG_PDOWN_AUX2_ID = PM_VREG_PDOWN_GP5_ID,
|
||||
PM_VREG_PDOWN_BT_ID = PM_VREG_PDOWN_GP6_ID,
|
||||
|
||||
PM_VREG_PDOWN_MSME_ID = PM_VREG_PDOWN_MSME1_ID,
|
||||
PM_VREG_PDOWN_MSMC_ID = PM_VREG_PDOWN_MSMC1_ID,
|
||||
PM_VREG_PDOWN_RFA1_ID = PM_VREG_PDOWN_RFRX2_ID,
|
||||
PM_VREG_PDOWN_RFA2_ID = PM_VREG_PDOWN_RFTX2_ID,
|
||||
PM_VREG_PDOWN_XO_ID = PM_VREG_PDOWN_TCXO_ID
|
||||
};
|
||||
|
||||
/* gpio info for PCOM_RPC_GPIO_TLMM_CONFIG_EX */
|
||||
|
||||
#define GPIO_ENABLE 0
|
||||
#define GPIO_DISABLE 1
|
||||
|
||||
#define GPIO_INPUT 0
|
||||
#define GPIO_OUTPUT 1
|
||||
|
||||
#define GPIO_NO_PULL 0
|
||||
#define GPIO_PULL_DOWN 1
|
||||
#define GPIO_KEEPER 2
|
||||
#define GPIO_PULL_UP 3
|
||||
|
||||
#define GPIO_2MA 0
|
||||
#define GPIO_4MA 1
|
||||
#define GPIO_6MA 2
|
||||
#define GPIO_8MA 3
|
||||
#define GPIO_10MA 4
|
||||
#define GPIO_12MA 5
|
||||
#define GPIO_14MA 6
|
||||
#define GPIO_16MA 7
|
||||
|
||||
#define PCOM_GPIO_CFG(gpio, func, dir, pull, drvstr) \
|
||||
((((gpio) & 0x3FF) << 4) | \
|
||||
((func) & 0xf) | \
|
||||
(((dir) & 0x1) << 14) | \
|
||||
(((pull) & 0x3) << 15) | \
|
||||
(((drvstr) & 0xF) << 17))
|
||||
|
||||
int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2);
|
||||
|
||||
#endif
|
@ -45,7 +45,7 @@ struct msm_clock {
|
||||
struct clock_event_device clockevent;
|
||||
struct clocksource clocksource;
|
||||
struct irqaction irq;
|
||||
uint32_t regbase;
|
||||
void __iomem *regbase;
|
||||
uint32_t freq;
|
||||
uint32_t shift;
|
||||
};
|
||||
|
143
arch/arm/mach-msm/vreg.c
Normal file
143
arch/arm/mach-msm/vreg.c
Normal file
@ -0,0 +1,143 @@
|
||||
/* arch/arm/mach-msm/vreg.c
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <mach/vreg.h>
|
||||
|
||||
#include "proc_comm.h"
|
||||
|
||||
struct vreg {
|
||||
const char *name;
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
#define VREG(_name, _id) { .name = _name, .id = _id, }
|
||||
|
||||
static struct vreg vregs[] = {
|
||||
VREG("msma", 0),
|
||||
VREG("msmp", 1),
|
||||
VREG("msme1", 2),
|
||||
VREG("msmc1", 3),
|
||||
VREG("msmc2", 4),
|
||||
VREG("gp3", 5),
|
||||
VREG("msme2", 6),
|
||||
VREG("gp4", 7),
|
||||
VREG("gp1", 8),
|
||||
VREG("tcxo", 9),
|
||||
VREG("pa", 10),
|
||||
VREG("rftx", 11),
|
||||
VREG("rfrx1", 12),
|
||||
VREG("rfrx2", 13),
|
||||
VREG("synt", 14),
|
||||
VREG("wlan", 15),
|
||||
VREG("usb", 16),
|
||||
VREG("boost", 17),
|
||||
VREG("mmc", 18),
|
||||
VREG("ruim", 19),
|
||||
VREG("msmc0", 20),
|
||||
VREG("gp2", 21),
|
||||
VREG("gp5", 22),
|
||||
VREG("gp6", 23),
|
||||
VREG("rf", 24),
|
||||
VREG("rf_vco", 26),
|
||||
VREG("mpll", 27),
|
||||
VREG("s2", 28),
|
||||
VREG("s3", 29),
|
||||
VREG("rfubm", 30),
|
||||
VREG("ncp", 31),
|
||||
};
|
||||
|
||||
struct vreg *vreg_get(struct device *dev, const char *id)
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < ARRAY_SIZE(vregs); n++) {
|
||||
if (!strcmp(vregs[n].name, id))
|
||||
return vregs + n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vreg_put(struct vreg *vreg)
|
||||
{
|
||||
}
|
||||
|
||||
int vreg_enable(struct vreg *vreg)
|
||||
{
|
||||
unsigned id = vreg->id;
|
||||
unsigned enable = 1;
|
||||
return msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
|
||||
}
|
||||
|
||||
void vreg_disable(struct vreg *vreg)
|
||||
{
|
||||
unsigned id = vreg->id;
|
||||
unsigned enable = 0;
|
||||
msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
|
||||
}
|
||||
|
||||
int vreg_set_level(struct vreg *vreg, unsigned mv)
|
||||
{
|
||||
unsigned id = vreg->id;
|
||||
return msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static int vreg_debug_set(void *data, u64 val)
|
||||
{
|
||||
struct vreg *vreg = data;
|
||||
switch (val) {
|
||||
case 0:
|
||||
vreg_disable(vreg);
|
||||
break;
|
||||
case 1:
|
||||
vreg_enable(vreg);
|
||||
break;
|
||||
default:
|
||||
vreg_set_level(vreg, val);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vreg_debug_get(void *data, u64 *val)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
|
||||
|
||||
static int __init vreg_debug_init(void)
|
||||
{
|
||||
struct dentry *dent;
|
||||
int n;
|
||||
|
||||
dent = debugfs_create_dir("vreg", 0);
|
||||
if (IS_ERR(dent))
|
||||
return 0;
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(vregs); n++)
|
||||
(void) debugfs_create_file(vregs[n].name, 0644,
|
||||
dent, vregs + n, &vreg_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(vreg_debug_init);
|
||||
#endif
|
@ -13,6 +13,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <mach/mv78xx0.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
@ -28,10 +29,14 @@ static struct mv643xx_eth_platform_data db78x00_ge01_data = {
|
||||
|
||||
static struct mv643xx_eth_platform_data db78x00_ge10_data = {
|
||||
.phy_addr = MV643XX_ETH_PHY_NONE,
|
||||
.speed = SPEED_1000,
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct mv643xx_eth_platform_data db78x00_ge11_data = {
|
||||
.phy_addr = MV643XX_ETH_PHY_NONE,
|
||||
.speed = SPEED_1000,
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct mv_sata_platform_data db78x00_sata_data = {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/mv643xx_i2c.h>
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/spi/orion_spi.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/timex.h>
|
||||
@ -197,6 +198,40 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet switch
|
||||
****************************************************************************/
|
||||
static struct resource orion5x_switch_resources[] = {
|
||||
{
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device orion5x_switch_device = {
|
||||
.name = "dsa",
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
.resource = orion5x_switch_resources,
|
||||
};
|
||||
|
||||
void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
|
||||
{
|
||||
if (irq != NO_IRQ) {
|
||||
orion5x_switch_resources[0].start = irq;
|
||||
orion5x_switch_resources[0].end = irq;
|
||||
orion5x_switch_device.num_resources = 1;
|
||||
}
|
||||
|
||||
d->mii_bus = &orion5x_eth_shared.dev;
|
||||
d->netdev = &orion5x_eth.dev;
|
||||
orion5x_switch_device.dev.platform_data = d;
|
||||
|
||||
platform_device_register(&orion5x_switch_device);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* I2C
|
||||
****************************************************************************/
|
||||
@ -275,7 +310,8 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
|
||||
* SPI
|
||||
****************************************************************************/
|
||||
static struct orion_spi_info orion5x_spi_plat_data = {
|
||||
.tclk = 0,
|
||||
.tclk = 0,
|
||||
.enable_clock_fix = 1,
|
||||
};
|
||||
|
||||
static struct resource orion5x_spi_resources[] = {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef __ARCH_ORION5X_COMMON_H
|
||||
#define __ARCH_ORION5X_COMMON_H
|
||||
|
||||
struct dsa_platform_data;
|
||||
struct mv643xx_eth_platform_data;
|
||||
struct mv_sata_platform_data;
|
||||
|
||||
@ -29,6 +30,7 @@ void orion5x_setup_pcie_wa_win(u32 base, u32 size);
|
||||
void orion5x_ehci0_init(void);
|
||||
void orion5x_ehci1_init(void);
|
||||
void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
|
||||
void orion5x_eth_switch_init(struct dsa_platform_data *d, int irq);
|
||||
void orion5x_i2c_init(void);
|
||||
void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
|
||||
void orion5x_spi_init(void);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/leds.h>
|
||||
@ -93,6 +94,15 @@ static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = {
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct dsa_platform_data rd88f5181l_fxo_switch_data = {
|
||||
.port_names[0] = "lan2",
|
||||
.port_names[1] = "lan1",
|
||||
.port_names[2] = "wan",
|
||||
.port_names[3] = "cpu",
|
||||
.port_names[5] = "lan4",
|
||||
.port_names[7] = "lan3",
|
||||
};
|
||||
|
||||
static void __init rd88f5181l_fxo_init(void)
|
||||
{
|
||||
/*
|
||||
@ -107,6 +117,7 @@ static void __init rd88f5181l_fxo_init(void)
|
||||
*/
|
||||
orion5x_ehci0_init();
|
||||
orion5x_eth_init(&rd88f5181l_fxo_eth_data);
|
||||
orion5x_eth_switch_init(&rd88f5181l_fxo_switch_data, NO_IRQ);
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/leds.h>
|
||||
@ -94,6 +95,15 @@ static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = {
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct dsa_platform_data rd88f5181l_ge_switch_data = {
|
||||
.port_names[0] = "lan2",
|
||||
.port_names[1] = "lan1",
|
||||
.port_names[2] = "wan",
|
||||
.port_names[3] = "cpu",
|
||||
.port_names[5] = "lan4",
|
||||
.port_names[7] = "lan3",
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = {
|
||||
I2C_BOARD_INFO("ds1338", 0x68),
|
||||
};
|
||||
@ -112,6 +122,7 @@ static void __init rd88f5181l_ge_init(void)
|
||||
*/
|
||||
orion5x_ehci0_init();
|
||||
orion5x_eth_init(&rd88f5181l_ge_eth_data);
|
||||
orion5x_eth_switch_init(&rd88f5181l_ge_switch_data, gpio_to_irq(8));
|
||||
orion5x_i2c_init();
|
||||
orion5x_uart0_init();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/spi/orion_spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/leds.h>
|
||||
@ -34,6 +35,15 @@ static struct mv643xx_eth_platform_data rd88f6183ap_ge_eth_data = {
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct dsa_platform_data rd88f6183ap_ge_switch_data = {
|
||||
.port_names[0] = "lan1",
|
||||
.port_names[1] = "lan2",
|
||||
.port_names[2] = "lan3",
|
||||
.port_names[3] = "lan4",
|
||||
.port_names[4] = "wan",
|
||||
.port_names[5] = "cpu",
|
||||
};
|
||||
|
||||
static struct mtd_partition rd88f6183ap_ge_partitions[] = {
|
||||
{
|
||||
.name = "kernel",
|
||||
@ -79,6 +89,7 @@ static void __init rd88f6183ap_ge_init(void)
|
||||
*/
|
||||
orion5x_ehci0_init();
|
||||
orion5x_eth_init(&rd88f6183ap_ge_eth_data);
|
||||
orion5x_eth_switch_init(&rd88f6183ap_ge_switch_data, gpio_to_irq(3));
|
||||
spi_register_board_info(rd88f6183ap_ge_spi_slave_info,
|
||||
ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info));
|
||||
orion5x_spi_init();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <net/dsa.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/arch.h>
|
||||
@ -105,6 +106,15 @@ static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = {
|
||||
.duplex = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
static struct dsa_platform_data wrt350n_v2_switch_data = {
|
||||
.port_names[0] = "lan2",
|
||||
.port_names[1] = "lan1",
|
||||
.port_names[2] = "wan",
|
||||
.port_names[3] = "cpu",
|
||||
.port_names[5] = "lan3",
|
||||
.port_names[7] = "lan4",
|
||||
};
|
||||
|
||||
static void __init wrt350n_v2_init(void)
|
||||
{
|
||||
/*
|
||||
@ -119,6 +129,7 @@ static void __init wrt350n_v2_init(void)
|
||||
*/
|
||||
orion5x_ehci0_init();
|
||||
orion5x_eth_init(&wrt350n_v2_eth_data);
|
||||
orion5x_eth_switch_init(&wrt350n_v2_switch_data, NO_IRQ);
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE,
|
||||
|
@ -71,6 +71,14 @@ config PXA_SHARPSL
|
||||
SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
|
||||
handheld computer.
|
||||
|
||||
config CORGI_SSP_DEPRECATED
|
||||
bool
|
||||
select PXA_SSP
|
||||
help
|
||||
This option will include corgi_ssp.c and corgi_lcd.c
|
||||
that corgi_ts.c and other legacy drivers (corgi_bl.c
|
||||
and sharpsl_pm.c) may depend on.
|
||||
|
||||
config MACH_POODLE
|
||||
bool "Enable Sharp SL-5600 (Poodle) Support"
|
||||
depends on PXA_SHARPSL
|
||||
@ -257,7 +265,6 @@ config MACH_ARMCORE
|
||||
bool "CompuLab CM-X255/CM-X270 modules"
|
||||
select PXA27x
|
||||
select IWMMXT
|
||||
select ZONE_DMA if PCI
|
||||
select PXA25x
|
||||
select PXA_SSP
|
||||
|
||||
|
@ -37,6 +37,7 @@ obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o
|
||||
obj-$(CONFIG_MACH_COLIBRI) += colibri.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
|
||||
obj-$(CONFIG_MACH_POODLE) += poodle.o
|
||||
obj-$(CONFIG_MACH_PCM027) += pcm027.o
|
||||
obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o
|
||||
|
289
arch/arm/mach-pxa/corgi_lcd.c
Normal file
289
arch/arm/mach-pxa/corgi_lcd.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-pxa/corgi_lcd.c
|
||||
*
|
||||
* Corgi/Spitz LCD Specific Code
|
||||
*
|
||||
* Copyright (C) 2005 Richard Purdie
|
||||
*
|
||||
* Connectivity:
|
||||
* Corgi - LCD to ATI Imageon w100 (Wallaby)
|
||||
* Spitz - LCD to PXA 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/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <mach/corgi.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/pxa-regs.h>
|
||||
#include <mach/sharpsl.h>
|
||||
#include <mach/spitz.h>
|
||||
#include <asm/hardware/scoop.h>
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
#include "generic.h"
|
||||
|
||||
/* Register Addresses */
|
||||
#define RESCTL_ADRS 0x00
|
||||
#define PHACTRL_ADRS 0x01
|
||||
#define DUTYCTRL_ADRS 0x02
|
||||
#define POWERREG0_ADRS 0x03
|
||||
#define POWERREG1_ADRS 0x04
|
||||
#define GPOR3_ADRS 0x05
|
||||
#define PICTRL_ADRS 0x06
|
||||
#define POLCTRL_ADRS 0x07
|
||||
|
||||
/* Register Bit Definitions */
|
||||
#define RESCTL_QVGA 0x01
|
||||
#define RESCTL_VGA 0x00
|
||||
|
||||
#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
|
||||
#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
|
||||
#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
|
||||
|
||||
#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
|
||||
#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
|
||||
#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
|
||||
|
||||
#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
|
||||
#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
|
||||
#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
|
||||
#define POWER0_COM_ON 0x08 /* COM Power Supply ON */
|
||||
#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
|
||||
|
||||
#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
|
||||
#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */
|
||||
#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
|
||||
|
||||
#define PICTRL_INIT_STATE 0x01
|
||||
#define PICTRL_INIOFF 0x02
|
||||
#define PICTRL_POWER_DOWN 0x04
|
||||
#define PICTRL_COM_SIGNAL_OFF 0x08
|
||||
#define PICTRL_DAC_SIGNAL_OFF 0x10
|
||||
|
||||
#define POLCTRL_SYNC_POL_FALL 0x01
|
||||
#define POLCTRL_EN_POL_FALL 0x02
|
||||
#define POLCTRL_DATA_POL_FALL 0x04
|
||||
#define POLCTRL_SYNC_ACT_H 0x08
|
||||
#define POLCTRL_EN_ACT_L 0x10
|
||||
|
||||
#define POLCTRL_SYNC_POL_RISE 0x00
|
||||
#define POLCTRL_EN_POL_RISE 0x00
|
||||
#define POLCTRL_DATA_POL_RISE 0x00
|
||||
#define POLCTRL_SYNC_ACT_L 0x00
|
||||
#define POLCTRL_EN_ACT_H 0x00
|
||||
|
||||
#define PHACTRL_PHASE_MANUAL 0x01
|
||||
#define DEFAULT_PHAD_QVGA (9)
|
||||
#define DEFAULT_COMADJ (125)
|
||||
|
||||
/*
|
||||
* This is only a psuedo I2C interface. We can't use the standard kernel
|
||||
* routines as the interface is write only. We just assume the data is acked...
|
||||
*/
|
||||
static void lcdtg_ssp_i2c_send(u8 data)
|
||||
{
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, data);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void lcdtg_i2c_send_bit(u8 data)
|
||||
{
|
||||
lcdtg_ssp_i2c_send(data);
|
||||
lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
|
||||
lcdtg_ssp_i2c_send(data);
|
||||
}
|
||||
|
||||
static void lcdtg_i2c_send_start(u8 base)
|
||||
{
|
||||
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
|
||||
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
|
||||
lcdtg_ssp_i2c_send(base);
|
||||
}
|
||||
|
||||
static void lcdtg_i2c_send_stop(u8 base)
|
||||
{
|
||||
lcdtg_ssp_i2c_send(base);
|
||||
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
|
||||
lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
|
||||
}
|
||||
|
||||
static void lcdtg_i2c_send_byte(u8 base, u8 data)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (data & 0x80)
|
||||
lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
|
||||
else
|
||||
lcdtg_i2c_send_bit(base);
|
||||
data <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcdtg_i2c_wait_ack(u8 base)
|
||||
{
|
||||
lcdtg_i2c_send_bit(base);
|
||||
}
|
||||
|
||||
static void lcdtg_set_common_voltage(u8 base_data, u8 data)
|
||||
{
|
||||
/* Set Common Voltage to M62332FP via I2C */
|
||||
lcdtg_i2c_send_start(base_data);
|
||||
lcdtg_i2c_send_byte(base_data, 0x9c);
|
||||
lcdtg_i2c_wait_ack(base_data);
|
||||
lcdtg_i2c_send_byte(base_data, 0x00);
|
||||
lcdtg_i2c_wait_ack(base_data);
|
||||
lcdtg_i2c_send_byte(base_data, data);
|
||||
lcdtg_i2c_wait_ack(base_data);
|
||||
lcdtg_i2c_send_stop(base_data);
|
||||
}
|
||||
|
||||
/* Set Phase Adjust */
|
||||
static void lcdtg_set_phadadj(int mode)
|
||||
{
|
||||
int adj;
|
||||
switch(mode) {
|
||||
case 480:
|
||||
case 640:
|
||||
/* Setting for VGA */
|
||||
adj = sharpsl_param.phadadj;
|
||||
if (adj < 0) {
|
||||
adj = PHACTRL_PHASE_MANUAL;
|
||||
} else {
|
||||
adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
|
||||
}
|
||||
break;
|
||||
case 240:
|
||||
case 320:
|
||||
default:
|
||||
/* Setting for QVGA */
|
||||
adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
|
||||
break;
|
||||
}
|
||||
|
||||
corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj);
|
||||
}
|
||||
|
||||
static int lcd_inited;
|
||||
|
||||
void corgi_lcdtg_hw_init(int mode)
|
||||
{
|
||||
if (!lcd_inited) {
|
||||
int comadj;
|
||||
|
||||
/* Initialize Internal Logic & Port */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE
|
||||
| PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF);
|
||||
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF
|
||||
| POWER0_COM_OFF | POWER0_VCC5_OFF);
|
||||
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
|
||||
|
||||
/* VDD(+8V), SVSS(-4V) ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
|
||||
mdelay(3);
|
||||
|
||||
/* DAC ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
|
||||
| POWER0_COM_OFF | POWER0_VCC5_OFF);
|
||||
|
||||
/* INIB = H, INI = L */
|
||||
/* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
|
||||
|
||||
/* Set Common Voltage */
|
||||
comadj = sharpsl_param.comadj;
|
||||
if (comadj < 0)
|
||||
comadj = DEFAULT_COMADJ;
|
||||
lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
|
||||
|
||||
/* VCC5 ON, DAC ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
|
||||
POWER0_COM_OFF | POWER0_VCC5_ON);
|
||||
|
||||
/* GVSS(-8V) ON, VDD ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
|
||||
mdelay(2);
|
||||
|
||||
/* COM SIGNAL ON (PICTL[3] = L) */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE);
|
||||
|
||||
/* COM ON, DAC ON, VCC5_ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
|
||||
| POWER0_COM_ON | POWER0_VCC5_ON);
|
||||
|
||||
/* VW ON, GVSS ON, VDD ON */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
|
||||
|
||||
/* Signals output enable */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
|
||||
|
||||
/* Set Phase Adjust */
|
||||
lcdtg_set_phadadj(mode);
|
||||
|
||||
/* Initialize for Input Signals from ATI */
|
||||
corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
|
||||
| POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H);
|
||||
udelay(1000);
|
||||
|
||||
lcd_inited=1;
|
||||
} else {
|
||||
lcdtg_set_phadadj(mode);
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case 480:
|
||||
case 640:
|
||||
/* Set Lcd Resolution (VGA) */
|
||||
corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA);
|
||||
break;
|
||||
case 240:
|
||||
case 320:
|
||||
default:
|
||||
/* Set Lcd Resolution (QVGA) */
|
||||
corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void corgi_lcdtg_suspend(void)
|
||||
{
|
||||
/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
|
||||
mdelay(34);
|
||||
|
||||
/* (1)VW OFF */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
|
||||
|
||||
/* (2)COM OFF */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
|
||||
|
||||
/* (3)Set Common Voltage Bias 0V */
|
||||
lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
|
||||
|
||||
/* (4)GVSS OFF */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
|
||||
|
||||
/* (5)VCC5 OFF */
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
|
||||
|
||||
/* (6)Set PDWN, INIOFF, DACOFF */
|
||||
corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
|
||||
PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
|
||||
|
||||
/* (7)DAC OFF */
|
||||
corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
|
||||
|
||||
/* (8)VDD OFF */
|
||||
corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
|
||||
|
||||
lcd_inited = 0;
|
||||
}
|
||||
|
276
arch/arm/mach-pxa/corgi_ssp.c
Normal file
276
arch/arm/mach-pxa/corgi_ssp.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* SSP control code for Sharp Corgi devices
|
||||
*
|
||||
* Copyright (c) 2004-2005 Richard Purdie
|
||||
*
|
||||
* 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/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <mach/ssp.h>
|
||||
#include <mach/pxa-regs.h>
|
||||
#include <mach/pxa2xx-gpio.h>
|
||||
#include <mach/regs-ssp.h>
|
||||
#include "sharpsl.h"
|
||||
|
||||
static DEFINE_SPINLOCK(corgi_ssp_lock);
|
||||
static struct ssp_dev corgi_ssp_dev;
|
||||
static struct ssp_state corgi_ssp_state;
|
||||
static struct corgissp_machinfo *ssp_machinfo;
|
||||
|
||||
/*
|
||||
* There are three devices connected to the SSP interface:
|
||||
* 1. A touchscreen controller (TI ADS7846 compatible)
|
||||
* 2. An LCD controller (with some Backlight functionality)
|
||||
* 3. A battery monitoring IC (Maxim MAX1111)
|
||||
*
|
||||
* Each device uses a different speed/mode of communication.
|
||||
*
|
||||
* The touchscreen is very sensitive and the most frequently used
|
||||
* so the port is left configured for this.
|
||||
*
|
||||
* Devices are selected using Chip Selects on GPIOs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ADS7846 Routines
|
||||
*/
|
||||
unsigned long corgi_ssp_ads7846_putget(ulong data)
|
||||
{
|
||||
unsigned long flag;
|
||||
u32 ret = 0;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
ssp_read_word(&corgi_ssp_dev, &ret);
|
||||
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: These functions should always be called in interrupt context
|
||||
* and use the _lock and _unlock functions. They are very time sensitive.
|
||||
*/
|
||||
void corgi_ssp_ads7846_lock(void)
|
||||
{
|
||||
spin_lock(&corgi_ssp_lock);
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
}
|
||||
|
||||
void corgi_ssp_ads7846_unlock(void)
|
||||
{
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
|
||||
spin_unlock(&corgi_ssp_lock);
|
||||
}
|
||||
|
||||
void corgi_ssp_ads7846_put(ulong data)
|
||||
{
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
}
|
||||
|
||||
unsigned long corgi_ssp_ads7846_get(void)
|
||||
{
|
||||
u32 ret = 0;
|
||||
ssp_read_word(&corgi_ssp_dev, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_lock);
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_put);
|
||||
EXPORT_SYMBOL(corgi_ssp_ads7846_get);
|
||||
|
||||
|
||||
/*
|
||||
* LCD/Backlight Routines
|
||||
*/
|
||||
unsigned long corgi_ssp_dac_put(ulong data)
|
||||
{
|
||||
unsigned long flag, sscr1 = SSCR1_SPH;
|
||||
u32 tmp;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
|
||||
if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi())
|
||||
sscr1 = 0;
|
||||
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
|
||||
if (ssp_machinfo->cs_lcdcon >= 0)
|
||||
GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
/* Read null data back from device to prevent SSP overflow */
|
||||
ssp_read_word(&corgi_ssp_dev, &tmp);
|
||||
if (ssp_machinfo->cs_lcdcon >= 0)
|
||||
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
|
||||
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
|
||||
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void corgi_ssp_lcdtg_send(u8 adrs, u8 data)
|
||||
{
|
||||
corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));
|
||||
}
|
||||
|
||||
void corgi_ssp_blduty_set(int duty)
|
||||
{
|
||||
corgi_ssp_lcdtg_send(0x02,duty);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
|
||||
EXPORT_SYMBOL(corgi_ssp_blduty_set);
|
||||
|
||||
/*
|
||||
* Max1111 Routines
|
||||
*/
|
||||
int corgi_ssp_max1111_get(ulong data)
|
||||
{
|
||||
unsigned long flag;
|
||||
long voltage = 0, voltage1 = 0, voltage2 = 0;
|
||||
|
||||
spin_lock_irqsave(&corgi_ssp_lock, flag);
|
||||
if (ssp_machinfo->cs_max1111 >= 0)
|
||||
GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* TB1/RB1 */
|
||||
ssp_write_word(&corgi_ssp_dev,data);
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */
|
||||
|
||||
/* TB12/RB2 */
|
||||
ssp_write_word(&corgi_ssp_dev,0);
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1);
|
||||
|
||||
/* TB13/RB3*/
|
||||
ssp_write_word(&corgi_ssp_dev,0);
|
||||
ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2);
|
||||
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
if (ssp_machinfo->cs_max1111 >= 0)
|
||||
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
|
||||
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
|
||||
|
||||
if (voltage1 & 0xc0 || voltage2 & 0x3f)
|
||||
voltage = -1;
|
||||
else
|
||||
voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
|
||||
|
||||
return voltage;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(corgi_ssp_max1111_get);
|
||||
|
||||
/*
|
||||
* Support Routines
|
||||
*/
|
||||
|
||||
void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo)
|
||||
{
|
||||
ssp_machinfo = machinfo;
|
||||
}
|
||||
|
||||
static int __init corgi_ssp_probe(struct platform_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Chip Select - Disable All */
|
||||
if (ssp_machinfo->cs_lcdcon >= 0)
|
||||
pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH);
|
||||
if (ssp_machinfo->cs_max1111 >= 0)
|
||||
pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
|
||||
|
||||
ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
|
||||
|
||||
if (ret)
|
||||
printk(KERN_ERR "Unable to register SSP handler!\n");
|
||||
else {
|
||||
ssp_disable(&corgi_ssp_dev);
|
||||
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int corgi_ssp_remove(struct platform_device *dev)
|
||||
{
|
||||
ssp_exit(&corgi_ssp_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgi_ssp_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
ssp_flush(&corgi_ssp_dev);
|
||||
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgi_ssp_resume(struct platform_device *dev)
|
||||
{
|
||||
if (ssp_machinfo->cs_lcdcon >= 0)
|
||||
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
|
||||
if (ssp_machinfo->cs_max1111 >= 0)
|
||||
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
|
||||
if (ssp_machinfo->cs_ads7846 >= 0)
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
|
||||
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver corgissp_driver = {
|
||||
.probe = corgi_ssp_probe,
|
||||
.remove = corgi_ssp_remove,
|
||||
.suspend = corgi_ssp_suspend,
|
||||
.resume = corgi_ssp_resume,
|
||||
.driver = {
|
||||
.name = "corgi-ssp",
|
||||
},
|
||||
};
|
||||
|
||||
int __init corgi_ssp_init(void)
|
||||
{
|
||||
return platform_driver_register(&corgissp_driver);
|
||||
}
|
||||
|
||||
arch_initcall(corgi_ssp_init);
|
@ -113,6 +113,7 @@
|
||||
* Shared data structures
|
||||
*/
|
||||
extern struct platform_device corgiscoop_device;
|
||||
extern struct platform_device corgissp_device;
|
||||
|
||||
#endif /* __ASM_ARCH_CORGI_H */
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_IRQS_H
|
||||
#define __ASM_MACH_IRQS_H
|
||||
|
||||
#ifdef CONFIG_PXA_HAVE_ISA_IRQS
|
||||
#define PXA_ISA_IRQ(x) (x)
|
||||
@ -264,3 +265,5 @@
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_PCI_HOST_ITE8152 */
|
||||
|
||||
#endif /* __ASM_MACH_IRQS_H */
|
||||
|
@ -142,7 +142,7 @@
|
||||
|
||||
#define SPITZ_SCP2_GPIO_BASE (NR_BUILTIN_GPIO + 12)
|
||||
#define SPITZ_GPIO_IR_ON (SPITZ_SCP2_GPIO_BASE + 0)
|
||||
#define SPITZ_GPIO_AKIN_PULLUP (SPITZ_SCP2_GPIO_BASE + 1
|
||||
#define SPITZ_GPIO_AKIN_PULLUP (SPITZ_SCP2_GPIO_BASE + 1)
|
||||
#define SPITZ_GPIO_RESERVED_1 (SPITZ_SCP2_GPIO_BASE + 2)
|
||||
#define SPITZ_GPIO_RESERVED_2 (SPITZ_SCP2_GPIO_BASE + 3)
|
||||
#define SPITZ_GPIO_RESERVED_3 (SPITZ_SCP2_GPIO_BASE + 4)
|
||||
@ -187,4 +187,5 @@
|
||||
*/
|
||||
extern struct platform_device spitzscoop_device;
|
||||
extern struct platform_device spitzscoop2_device;
|
||||
extern struct platform_device spitzssp_device;
|
||||
extern struct sharpsl_charger_machinfo spitz_pm_machinfo;
|
||||
|
@ -193,4 +193,7 @@
|
||||
#define TOSA_KEY_MAIL KEY_MAIL
|
||||
#endif
|
||||
|
||||
struct spi_device;
|
||||
extern int tosa_bl_enable(struct spi_device *spi, int enable);
|
||||
|
||||
#endif /* _ASM_ARCH_TOSA_H_ */
|
||||
|
@ -60,7 +60,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
|
||||
do_div(c, 1000000000);
|
||||
period_cycles = c;
|
||||
|
||||
if (period_cycles < 0)
|
||||
if (period_cycles < 1)
|
||||
period_cycles = 1;
|
||||
prescale = (period_cycles - 1) / 1024;
|
||||
pv = period_cycles / (prescale + 1) - 1;
|
||||
|
@ -116,20 +116,33 @@ struct battery_thresh spitz_battery_levels_noac[] = {
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
/* MAX1111 Commands */
|
||||
#define MAXCTRL_PD0 1u << 0
|
||||
#define MAXCTRL_PD1 1u << 1
|
||||
#define MAXCTRL_SGL 1u << 2
|
||||
#define MAXCTRL_UNI 1u << 3
|
||||
#define MAXCTRL_SEL_SH 4
|
||||
#define MAXCTRL_STR 1u << 7
|
||||
|
||||
/*
|
||||
* Read MAX1111 ADC
|
||||
*/
|
||||
extern int max1111_read_channel(int);
|
||||
|
||||
int sharpsl_pm_pxa_read_max1111(int channel)
|
||||
{
|
||||
if (machine_is_tosa()) // Ugly, better move this function into another module
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_CORGI_SSP_DEPRECATED
|
||||
return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
|
||||
| MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
|
||||
#else
|
||||
extern int max1111_read_channel(int);
|
||||
|
||||
/* max1111 accepts channels from 0-3, however,
|
||||
* it is encoded from 0-7 here in the code.
|
||||
*/
|
||||
return max1111_read_channel(channel >> 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sharpsl_pm_pxa_init(void)
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach-types.h>
|
||||
@ -42,6 +43,7 @@
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/udc.h>
|
||||
#include <mach/tosa_bt.h>
|
||||
#include <mach/pxa2xx_spi.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <mach/tosa.h>
|
||||
@ -612,7 +614,7 @@ static int tosa_tc6393xb_enable(struct platform_device *dev)
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
|
||||
if (rc)
|
||||
goto err_req_suspend;
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "tc6393xb l3v");
|
||||
if (rc)
|
||||
goto err_req_l3v;
|
||||
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
|
||||
@ -772,6 +774,20 @@ static struct platform_device tosa_bt_device = {
|
||||
.dev.platform_data = &tosa_bt_data,
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_master pxa_ssp_master_info = {
|
||||
.num_chipselect = 1,
|
||||
};
|
||||
|
||||
static struct spi_board_info spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "tosa-lcd",
|
||||
// .platform_data
|
||||
.max_speed_hz = 28750,
|
||||
.bus_num = 2,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&tosascoop_device,
|
||||
@ -826,6 +842,9 @@ static void __init tosa_init(void)
|
||||
pxa_set_i2c_info(NULL);
|
||||
platform_scoop_config = &tosa_pcmcia_config;
|
||||
|
||||
pxa2xx_set_spi_info(2, &pxa_ssp_master_info);
|
||||
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
||||
|
||||
clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL);
|
||||
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
|
@ -399,7 +399,7 @@ static void trizeps4_irda_transceiver_mode(struct device *dev, int mode)
|
||||
/* Switch mode */
|
||||
if (mode & IR_SIRMODE)
|
||||
trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; /* Slow mode */
|
||||
else if (mode & IR_FIRMODE) {
|
||||
else if (mode & IR_FIRMODE)
|
||||
trizeps_conxs_ircr |= ConXS_IRCR_MODE; /* Fast mode */
|
||||
|
||||
/* Switch power */
|
||||
|
@ -1033,8 +1033,7 @@ void __init s3c2443_init_clocks(int xtal)
|
||||
|
||||
fclk = pll / s3c2443_fclk_div(clkdiv0);
|
||||
hclk = s3c2443_prediv_getrate(&clk_prediv);
|
||||
hclk = hclk / s3c2443_get_hdiv(clkdiv0);
|
||||
hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
|
||||
hclk /= s3c2443_get_hdiv(clkdiv0);
|
||||
pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
|
||||
|
||||
s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
|
||||
|
@ -400,9 +400,9 @@ 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_MSM7X00A || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
|
||||
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_MSM7X00A
|
||||
default y if ARCH_MSM
|
||||
select CPU_32v6
|
||||
select CPU_ABRT_EV6
|
||||
select CPU_PABRT_NOIFAR
|
||||
|
@ -29,7 +29,7 @@ ENTRY(v4_flush_user_cache_all)
|
||||
* Clean and invalidate the entire cache.
|
||||
*/
|
||||
ENTRY(v4_flush_kern_cache_all)
|
||||
#ifdef CPU_CP15
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 @ flush ID cache
|
||||
mov pc, lr
|
||||
@ -48,7 +48,7 @@ ENTRY(v4_flush_kern_cache_all)
|
||||
* - flags - vma_area_struct flags describing address space
|
||||
*/
|
||||
ENTRY(v4_flush_user_cache_range)
|
||||
#ifdef CPU_CP15
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
mov ip, #0
|
||||
mcreq p15, 0, ip, c7, c7, 0 @ flush ID cache
|
||||
mov pc, lr
|
||||
@ -116,7 +116,7 @@ ENTRY(v4_dma_inv_range)
|
||||
* - end - virtual end address
|
||||
*/
|
||||
ENTRY(v4_dma_flush_range)
|
||||
#ifdef CPU_CP15
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 @ flush ID cache
|
||||
#endif
|
||||
|
@ -180,8 +180,8 @@ __v7_setup:
|
||||
mov r10, #0x1f @ domains 0, 1 = manager
|
||||
mcr p15, 0, r10, c3, c0, 0 @ load domain access register
|
||||
#endif
|
||||
ldr r5, =0x40e040e0
|
||||
ldr r6, =0xff0aa1a8
|
||||
ldr r5, =0xff0aa1a8
|
||||
ldr r6, =0x40e040e0
|
||||
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
|
||||
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
|
||||
adr r5, v7_crval
|
||||
|
@ -315,7 +315,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
|
||||
if (parent == s3c24xx_pwmclk_tclk(id))
|
||||
bits = S3C2410_TCFG1_MUX_TCLK << shift;
|
||||
else if (parent == s3c24xx_pwmclk_tdiv(id))
|
||||
bits = clk_pwm_tdiv_bits(to_tdiv(clk)) << shift;
|
||||
bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -56,7 +56,7 @@ static struct clk *clk_scaler[2];
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_TIMER(_tmr_no, _irq) \
|
||||
#define DEFINE_S3C_TIMER(_tmr_no, _irq) \
|
||||
.name = "s3c24xx-pwm", \
|
||||
.id = _tmr_no, \
|
||||
.num_resources = TIMER_RESOURCE_SIZE, \
|
||||
@ -67,11 +67,11 @@ static struct clk *clk_scaler[2];
|
||||
*/
|
||||
|
||||
struct platform_device s3c_device_timer[] = {
|
||||
[0] = { DEFINE_TIMER(0, IRQ_TIMER0) },
|
||||
[1] = { DEFINE_TIMER(1, IRQ_TIMER1) },
|
||||
[2] = { DEFINE_TIMER(2, IRQ_TIMER2) },
|
||||
[3] = { DEFINE_TIMER(3, IRQ_TIMER3) },
|
||||
[4] = { DEFINE_TIMER(4, IRQ_TIMER4) },
|
||||
[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
|
||||
[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
|
||||
[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
|
||||
[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
|
||||
[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
|
||||
};
|
||||
|
||||
static inline int pwm_is_tdiv(struct pwm_device *pwm)
|
||||
|
@ -121,11 +121,19 @@ config BOARD_ATSTK1000
|
||||
config BOARD_ATNGW100
|
||||
bool "ATNGW100 Network Gateway"
|
||||
select CPU_AT32AP7000
|
||||
|
||||
config BOARD_FAVR_32
|
||||
bool "Favr-32 LCD-board"
|
||||
select CPU_AT32AP7000
|
||||
|
||||
config BOARD_MIMC200
|
||||
bool "MIMC200 CPU board"
|
||||
select CPU_AT32AP7000
|
||||
endchoice
|
||||
|
||||
if BOARD_ATSTK1000
|
||||
source "arch/avr32/boards/atstk1000/Kconfig"
|
||||
endif
|
||||
source "arch/avr32/boards/atngw100/Kconfig"
|
||||
source "arch/avr32/boards/favr-32/Kconfig"
|
||||
|
||||
choice
|
||||
prompt "Boot loader type"
|
||||
|
@ -33,6 +33,8 @@ head-y += arch/avr32/kernel/head.o
|
||||
core-y += $(machdirs)
|
||||
core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
|
||||
core-$(CONFIG_BOARD_ATNGW100) += arch/avr32/boards/atngw100/
|
||||
core-$(CONFIG_BOARD_FAVR_32) += arch/avr32/boards/favr-32/
|
||||
core-$(CONFIG_BOARD_MIMC200) += arch/avr32/boards/mimc200/
|
||||
core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
|
||||
core-y += arch/avr32/kernel/
|
||||
core-y += arch/avr32/mm/
|
||||
|
35
arch/avr32/boards/atngw100/Kconfig
Normal file
35
arch/avr32/boards/atngw100/Kconfig
Normal file
@ -0,0 +1,35 @@
|
||||
# NGW100 customization
|
||||
|
||||
if BOARD_ATNGW100
|
||||
|
||||
config BOARD_ATNGW100_EVKLCD10X
|
||||
bool "Add support for EVKLCD10X addon board"
|
||||
help
|
||||
This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA)
|
||||
addon board for the NGW100. By enabling this the LCD controller and
|
||||
AC97 controller is added as platform devices.
|
||||
|
||||
This choice disables the detect pin and the write-protect pin for the
|
||||
MCI platform device, since it conflicts with the LCD platform device.
|
||||
The MCI pins can be reenabled by editing the "add device function" but
|
||||
this may break the setup for other displays that use these pins.
|
||||
|
||||
Choose 'Y' here if you have a EVKLCD100/101 connected to the NGW100.
|
||||
|
||||
choice
|
||||
prompt "LCD panel resolution on EVKLCD10X"
|
||||
depends on BOARD_ATNGW100_EVKLCD10X
|
||||
default BOARD_ATNGW100_EVKLCD10X_VGA
|
||||
|
||||
config BOARD_ATNGW100_EVKLCD10X_QVGA
|
||||
bool "QVGA (320x240)"
|
||||
|
||||
config BOARD_ATNGW100_EVKLCD10X_VGA
|
||||
bool "VGA (640x480)"
|
||||
|
||||
config BOARD_ATNGW100_EVKLCD10X_POW_QVGA
|
||||
bool "Powertip QVGA (320x240)"
|
||||
|
||||
endchoice
|
||||
|
||||
endif # BOARD_ATNGW100
|
@ -1 +1,2 @@
|
||||
obj-y += setup.o flash.o
|
||||
obj-y += setup.o flash.o
|
||||
obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o
|
||||
|
155
arch/avr32/boards/atngw100/evklcd10x.c
Normal file
155
arch/avr32/boards/atngw100/evklcd10x.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Board-specific setup code for the ATEVKLCD10X addon board to the ATNGW100
|
||||
* Network Gateway
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Corporation
|
||||
*
|
||||
* 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/linkage.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <mach/at32ap700x.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
static struct ac97c_platform_data __initdata ac97c0_data = {
|
||||
.dma_rx_periph_id = 3,
|
||||
.dma_tx_periph_id = 4,
|
||||
.dma_controller_id = 0,
|
||||
.reset_pin = GPIO_PIN_PB(19),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BOARD_ATNGW100_EVKLCD10X_VGA
|
||||
static struct fb_videomode __initdata tcg057vglad_modes[] = {
|
||||
{
|
||||
.name = "640x480 @ 60",
|
||||
.refresh = 60,
|
||||
.xres = 640, .yres = 480,
|
||||
.pixclock = KHZ2PICOS(25180),
|
||||
|
||||
.left_margin = 64, .right_margin = 31,
|
||||
.upper_margin = 34, .lower_margin = 2,
|
||||
.hsync_len = 96, .vsync_len = 4,
|
||||
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
|
||||
.manufacturer = "KYO",
|
||||
.monitor = "TCG057VGLAD",
|
||||
.modedb = tcg057vglad_modes,
|
||||
.modedb_len = ARRAY_SIZE(tcg057vglad_modes),
|
||||
.hfmin = 19948,
|
||||
.hfmax = 31478,
|
||||
.vfmin = 50,
|
||||
.vfmax = 67,
|
||||
.dclkmax = 28330000,
|
||||
};
|
||||
|
||||
static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
|
||||
.default_bpp = 16,
|
||||
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
|
||||
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
|
||||
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
|
||||
| ATMEL_LCDC_MEMOR_BIG),
|
||||
.default_monspecs = &atevklcd10x_default_monspecs,
|
||||
.guard_time = 2,
|
||||
};
|
||||
#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_QVGA
|
||||
static struct fb_videomode __initdata tcg057qvlad_modes[] = {
|
||||
{
|
||||
.name = "320x240 @ 60",
|
||||
.refresh = 60,
|
||||
.xres = 320, .yres = 240,
|
||||
.pixclock = KHZ2PICOS(6300),
|
||||
|
||||
.left_margin = 52, .right_margin = 28,
|
||||
.upper_margin = 7, .lower_margin = 2,
|
||||
.hsync_len = 96, .vsync_len = 4,
|
||||
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
|
||||
.manufacturer = "KYO",
|
||||
.monitor = "TCG057QVLAD",
|
||||
.modedb = tcg057qvlad_modes,
|
||||
.modedb_len = ARRAY_SIZE(tcg057qvlad_modes),
|
||||
.hfmin = 19948,
|
||||
.hfmax = 31478,
|
||||
.vfmin = 50,
|
||||
.vfmax = 67,
|
||||
.dclkmax = 7000000,
|
||||
};
|
||||
|
||||
static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
|
||||
.default_bpp = 16,
|
||||
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
|
||||
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
|
||||
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
|
||||
| ATMEL_LCDC_MEMOR_BIG),
|
||||
.default_monspecs = &atevklcd10x_default_monspecs,
|
||||
.guard_time = 2,
|
||||
};
|
||||
#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_POW_QVGA
|
||||
static struct fb_videomode __initdata ph320240t_modes[] = {
|
||||
{
|
||||
.name = "320x240 @ 60",
|
||||
.refresh = 60,
|
||||
.xres = 320, .yres = 240,
|
||||
.pixclock = KHZ2PICOS(6300),
|
||||
|
||||
.left_margin = 38, .right_margin = 20,
|
||||
.upper_margin = 15, .lower_margin = 5,
|
||||
.hsync_len = 30, .vsync_len = 3,
|
||||
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
|
||||
.manufacturer = "POW",
|
||||
.monitor = "PH320240T",
|
||||
.modedb = ph320240t_modes,
|
||||
.modedb_len = ARRAY_SIZE(ph320240t_modes),
|
||||
.hfmin = 14400,
|
||||
.hfmax = 21600,
|
||||
.vfmin = 50,
|
||||
.vfmax = 90,
|
||||
.dclkmax = 6400000,
|
||||
};
|
||||
|
||||
static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
|
||||
.default_bpp = 16,
|
||||
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
|
||||
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
|
||||
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
|
||||
| ATMEL_LCDC_MEMOR_BIG),
|
||||
.default_monspecs = &atevklcd10x_default_monspecs,
|
||||
.guard_time = 2,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init atevklcd10x_init(void)
|
||||
{
|
||||
at32_add_device_ac97c(0, &ac97c0_data);
|
||||
|
||||
at32_add_device_lcdc(0, &atevklcd10x_lcdc_data,
|
||||
fbmem_start, fbmem_size, 1);
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(atevklcd10x_init);
|
@ -56,8 +56,13 @@ static struct spi_board_info spi0_board_info[] __initdata = {
|
||||
static struct mci_platform_data __initdata mci0_data = {
|
||||
.slot[0] = {
|
||||
.bus_width = 4,
|
||||
#ifndef CONFIG_BOARD_ATNGW100_EVKLCD10X
|
||||
.detect_pin = GPIO_PIN_PC(25),
|
||||
.wp_pin = GPIO_PIN_PE(0),
|
||||
#else
|
||||
.detect_pin = GPIO_PIN_NONE,
|
||||
.wp_pin = GPIO_PIN_NONE,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
@ -172,8 +177,6 @@ static int __init atngw100_init(void)
|
||||
* reserve any pins for it.
|
||||
*/
|
||||
|
||||
at32_add_system_devices();
|
||||
|
||||
at32_add_device_usart(0);
|
||||
|
||||
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
||||
|
@ -305,8 +305,6 @@ static int __init atstk1002_init(void)
|
||||
at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
|
||||
|
||||
at32_add_system_devices();
|
||||
|
||||
#ifdef CONFIG_BOARD_ATSTK1006
|
||||
smc_set_timing(&nand_config, &nand_timing);
|
||||
smc_set_configuration(3, &nand_config);
|
||||
|
@ -149,8 +149,6 @@ static int __init atstk1003_init(void)
|
||||
at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
|
||||
|
||||
at32_add_system_devices();
|
||||
|
||||
#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||
at32_add_device_usart(1);
|
||||
#else
|
||||
|
@ -132,8 +132,6 @@ void __init setup_board(void)
|
||||
|
||||
static int __init atstk1004_init(void)
|
||||
{
|
||||
at32_add_system_devices();
|
||||
|
||||
#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||
at32_add_device_usart(1);
|
||||
#else
|
||||
|
22
arch/avr32/boards/favr-32/Kconfig
Normal file
22
arch/avr32/boards/favr-32/Kconfig
Normal file
@ -0,0 +1,22 @@
|
||||
# Favr-32 customization
|
||||
|
||||
if BOARD_FAVR_32
|
||||
|
||||
config BOARD_FAVR32_ABDAC_RATE
|
||||
int "DAC target rate"
|
||||
default 44100
|
||||
range 32000 50000
|
||||
help
|
||||
Specify the target rate the internal DAC should try to match. This
|
||||
will use PLL1 to generate a frequency as close as possible to this
|
||||
rate.
|
||||
|
||||
Must be within the range 32000 to 50000, which should be suitable to
|
||||
generate most other frequencies in power of 2 steps.
|
||||
|
||||
Ex:
|
||||
48000 will also suit 24000 and 12000
|
||||
44100 will also suit 22050 and 11025
|
||||
32000 will also suit 16000 and 8000
|
||||
|
||||
endif # BOARD_FAVR_32
|
1
arch/avr32/boards/favr-32/Makefile
Normal file
1
arch/avr32/boards/favr-32/Makefile
Normal file
@ -0,0 +1 @@
|
||||
obj-y += setup.o flash.o
|
98
arch/avr32/boards/favr-32/flash.c
Normal file
98
arch/avr32/boards/favr-32/flash.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Favr-32 board-specific flash initialization
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Corporation
|
||||
*
|
||||
* 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/platform_device.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
#include <asm/arch/smc.h>
|
||||
|
||||
static struct smc_timing flash_timing __initdata = {
|
||||
.ncs_read_setup = 0,
|
||||
.nrd_setup = 40,
|
||||
.ncs_write_setup = 0,
|
||||
.nwe_setup = 10,
|
||||
|
||||
.ncs_read_pulse = 80,
|
||||
.nrd_pulse = 40,
|
||||
.ncs_write_pulse = 65,
|
||||
.nwe_pulse = 55,
|
||||
|
||||
.read_cycle = 120,
|
||||
.write_cycle = 120,
|
||||
};
|
||||
|
||||
static struct smc_config flash_config __initdata = {
|
||||
.bus_width = 2,
|
||||
.nrd_controlled = 1,
|
||||
.nwe_controlled = 1,
|
||||
.byte_write = 1,
|
||||
};
|
||||
|
||||
static struct mtd_partition flash_parts[] = {
|
||||
{
|
||||
.name = "u-boot",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x00020000, /* 128 KiB */
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
},
|
||||
{
|
||||
.name = "root",
|
||||
.offset = 0x00020000,
|
||||
.size = 0x007d0000,
|
||||
},
|
||||
{
|
||||
.name = "env",
|
||||
.offset = 0x007f0000,
|
||||
.size = 0x00010000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct physmap_flash_data flash_data = {
|
||||
.width = 2,
|
||||
.nr_parts = ARRAY_SIZE(flash_parts),
|
||||
.parts = flash_parts,
|
||||
};
|
||||
|
||||
static struct resource flash_resource = {
|
||||
.start = 0x00000000,
|
||||
.end = 0x007fffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device flash_device = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.resource = &flash_resource,
|
||||
.num_resources = 1,
|
||||
.dev = {
|
||||
.platform_data = &flash_data,
|
||||
},
|
||||
};
|
||||
|
||||
/* This needs to be called after the SMC has been initialized */
|
||||
static int __init favr32_flash_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
smc_set_timing(&flash_config, &flash_timing);
|
||||
ret = smc_set_configuration(0, &flash_config);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Favr-32: failed to set NOR flash timing\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_device_register(&flash_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(favr32_flash_init);
|
352
arch/avr32/boards/favr-32/setup.c
Normal file
352
arch/avr32/boards/favr-32/setup.c
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Favr-32 board-specific setup code.
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Corporation
|
||||
*
|
||||
* 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/clk.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/atmel-pwm-bl.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <asm/arch/at32ap700x.h>
|
||||
#include <asm/arch/init.h>
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/portmux.h>
|
||||
|
||||
/* Oscillator frequencies. These are board-specific */
|
||||
unsigned long at32_board_osc_rates[3] = {
|
||||
[0] = 32768, /* 32.768 kHz on RTC osc */
|
||||
[1] = 20000000, /* 20 MHz on osc0 */
|
||||
[2] = 12000000, /* 12 MHz on osc1 */
|
||||
};
|
||||
|
||||
/* Initialized by bootloader-specific startup code. */
|
||||
struct tag *bootloader_tags __initdata;
|
||||
|
||||
struct eth_addr {
|
||||
u8 addr[6];
|
||||
};
|
||||
static struct eth_addr __initdata hw_addr[1];
|
||||
static struct eth_platform_data __initdata eth_data[1] = {
|
||||
{
|
||||
.phy_mask = ~(1U << 1),
|
||||
},
|
||||
};
|
||||
|
||||
static int ads7843_get_pendown_state(void)
|
||||
{
|
||||
return !gpio_get_value(GPIO_PIN_PB(3));
|
||||
}
|
||||
|
||||
static struct ads7846_platform_data ads7843_data = {
|
||||
.model = 7843,
|
||||
.get_pendown_state = ads7843_get_pendown_state,
|
||||
.pressure_max = 255,
|
||||
/*
|
||||
* Values below are for debounce filtering, these can be experimented
|
||||
* with further.
|
||||
*/
|
||||
.debounce_max = 20,
|
||||
.debounce_rep = 4,
|
||||
.debounce_tol = 5,
|
||||
};
|
||||
|
||||
static struct spi_board_info __initdata spi1_board_info[] = {
|
||||
{
|
||||
/* ADS7843 touch controller */
|
||||
.modalias = "ads7846",
|
||||
.max_speed_hz = 2000000,
|
||||
.chip_select = 0,
|
||||
.bus_num = 1,
|
||||
.platform_data = &ads7843_data,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_videomode __initdata lb104v03_modes[] = {
|
||||
{
|
||||
.name = "640x480 @ 50",
|
||||
.refresh = 50,
|
||||
.xres = 640, .yres = 480,
|
||||
.pixclock = KHZ2PICOS(25100),
|
||||
|
||||
.left_margin = 90, .right_margin = 70,
|
||||
.upper_margin = 30, .lower_margin = 15,
|
||||
.hsync_len = 12, .vsync_len = 2,
|
||||
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_monspecs __initdata favr32_default_monspecs = {
|
||||
.manufacturer = "LG",
|
||||
.monitor = "LB104V03",
|
||||
.modedb = lb104v03_modes,
|
||||
.modedb_len = ARRAY_SIZE(lb104v03_modes),
|
||||
.hfmin = 27273,
|
||||
.hfmax = 31111,
|
||||
.vfmin = 45,
|
||||
.vfmax = 60,
|
||||
.dclkmax = 28000000,
|
||||
};
|
||||
|
||||
struct atmel_lcdfb_info __initdata favr32_lcdc_data = {
|
||||
.default_bpp = 16,
|
||||
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
|
||||
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
|
||||
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
|
||||
| ATMEL_LCDC_MEMOR_BIG),
|
||||
.default_monspecs = &favr32_default_monspecs,
|
||||
.guard_time = 2,
|
||||
};
|
||||
|
||||
static struct gpio_led favr32_leds[] = {
|
||||
{
|
||||
.name = "green",
|
||||
.gpio = GPIO_PIN_PE(19),
|
||||
.default_trigger = "heartbeat",
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "red",
|
||||
.gpio = GPIO_PIN_PE(20),
|
||||
.active_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data favr32_led_data = {
|
||||
.num_leds = ARRAY_SIZE(favr32_leds),
|
||||
.leds = favr32_leds,
|
||||
};
|
||||
|
||||
static struct platform_device favr32_led_dev = {
|
||||
.name = "leds-gpio",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &favr32_led_data,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The next two functions should go away as the boot loader is
|
||||
* supposed to initialize the macb address registers with a valid
|
||||
* ethernet address. But we need to keep it around for a while until
|
||||
* we can be reasonably sure the boot loader does this.
|
||||
*
|
||||
* The phy_id is ignored as the driver will probe for it.
|
||||
*/
|
||||
static int __init parse_tag_ethernet(struct tag *tag)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = tag->u.ethernet.mac_index;
|
||||
if (i < ARRAY_SIZE(hw_addr))
|
||||
memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
|
||||
sizeof(hw_addr[i].addr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
|
||||
|
||||
static void __init set_hw_addr(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
const u8 *addr;
|
||||
void __iomem *regs;
|
||||
struct clk *pclk;
|
||||
|
||||
if (!res)
|
||||
return;
|
||||
if (pdev->id >= ARRAY_SIZE(hw_addr))
|
||||
return;
|
||||
|
||||
addr = hw_addr[pdev->id].addr;
|
||||
if (!is_valid_ether_addr(addr))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Since this is board-specific code, we'll cheat and use the
|
||||
* physical address directly as we happen to know that it's
|
||||
* the same as the virtual address.
|
||||
*/
|
||||
regs = (void __iomem __force *)res->start;
|
||||
pclk = clk_get(&pdev->dev, "pclk");
|
||||
if (!pclk)
|
||||
return;
|
||||
|
||||
clk_enable(pclk);
|
||||
__raw_writel((addr[3] << 24) | (addr[2] << 16)
|
||||
| (addr[1] << 8) | addr[0], regs + 0x98);
|
||||
__raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
|
||||
clk_disable(pclk);
|
||||
clk_put(pclk);
|
||||
}
|
||||
|
||||
void __init favr32_setup_leds(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(favr32_leds); i++)
|
||||
at32_select_gpio(favr32_leds[i].gpio, AT32_GPIOF_OUTPUT);
|
||||
|
||||
platform_device_register(&favr32_led_dev);
|
||||
}
|
||||
|
||||
static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = {
|
||||
.pwm_channel = 2,
|
||||
.pwm_frequency = 200000,
|
||||
.pwm_compare_max = 345,
|
||||
.pwm_duty_max = 345,
|
||||
.pwm_duty_min = 90,
|
||||
.pwm_active_low = 1,
|
||||
.gpio_on = GPIO_PIN_PA(28),
|
||||
.on_active_low = 0,
|
||||
};
|
||||
|
||||
static struct platform_device atmel_pwm_bl_dev = {
|
||||
.name = "atmel-pwm-bl",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &atmel_pwm_bl_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init favr32_setup_atmel_pwm_bl(void)
|
||||
{
|
||||
platform_device_register(&atmel_pwm_bl_dev);
|
||||
at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0);
|
||||
}
|
||||
|
||||
void __init setup_board(void)
|
||||
{
|
||||
at32_map_usart(3, 0); /* USART 3 => /dev/ttyS0 */
|
||||
at32_setup_serial_console(0);
|
||||
}
|
||||
|
||||
static int __init set_abdac_rate(struct platform_device *pdev)
|
||||
{
|
||||
int retval;
|
||||
struct clk *osc1;
|
||||
struct clk *pll1;
|
||||
struct clk *abdac;
|
||||
|
||||
if (pdev == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
osc1 = clk_get(NULL, "osc1");
|
||||
if (IS_ERR(osc1)) {
|
||||
retval = PTR_ERR(osc1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pll1 = clk_get(NULL, "pll1");
|
||||
if (IS_ERR(pll1)) {
|
||||
retval = PTR_ERR(pll1);
|
||||
goto out_osc1;
|
||||
}
|
||||
|
||||
abdac = clk_get(&pdev->dev, "sample_clk");
|
||||
if (IS_ERR(abdac)) {
|
||||
retval = PTR_ERR(abdac);
|
||||
goto out_pll1;
|
||||
}
|
||||
|
||||
retval = clk_set_parent(pll1, osc1);
|
||||
if (retval != 0)
|
||||
goto out_abdac;
|
||||
|
||||
/*
|
||||
* Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in
|
||||
* power of 2, to a value above 80 MHz. Power of 2 so it is possible
|
||||
* for the generic clock to divide it down again and 80 MHz is the
|
||||
* lowest frequency for the PLL.
|
||||
*/
|
||||
retval = clk_round_rate(pll1,
|
||||
CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
|
||||
if (retval < 0)
|
||||
goto out_abdac;
|
||||
|
||||
retval = clk_set_rate(pll1, retval);
|
||||
if (retval != 0)
|
||||
goto out_abdac;
|
||||
|
||||
retval = clk_set_parent(abdac, pll1);
|
||||
if (retval != 0)
|
||||
goto out_abdac;
|
||||
|
||||
out_abdac:
|
||||
clk_put(abdac);
|
||||
out_pll1:
|
||||
clk_put(pll1);
|
||||
out_osc1:
|
||||
clk_put(osc1);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __init favr32_init(void)
|
||||
{
|
||||
/*
|
||||
* Favr-32 uses 32-bit SDRAM interface. Reserve the SDRAM-specific
|
||||
* pins so that nobody messes with them.
|
||||
*/
|
||||
at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
|
||||
at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
|
||||
|
||||
at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */
|
||||
|
||||
at32_add_system_devices();
|
||||
|
||||
at32_add_device_usart(0);
|
||||
|
||||
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
||||
|
||||
spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3));
|
||||
|
||||
set_abdac_rate(at32_add_device_abdac(0));
|
||||
|
||||
at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
|
||||
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
||||
at32_add_device_mci(0, NULL);
|
||||
at32_add_device_usba(0, NULL);
|
||||
at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0);
|
||||
|
||||
favr32_setup_leds();
|
||||
|
||||
favr32_setup_atmel_pwm_bl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(favr32_init);
|
1
arch/avr32/boards/mimc200/Makefile
Normal file
1
arch/avr32/boards/mimc200/Makefile
Normal file
@ -0,0 +1 @@
|
||||
obj-y += setup.o flash.o fram.o
|
143
arch/avr32/boards/mimc200/flash.c
Normal file
143
arch/avr32/boards/mimc200/flash.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* MIMC200 board-specific flash initialization
|
||||
*
|
||||
* Copyright (C) 2008 Mercury IMC Ltd
|
||||
*
|
||||
* 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/platform_device.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
#include <mach/smc.h>
|
||||
|
||||
static struct smc_timing flash_timing __initdata = {
|
||||
.ncs_read_setup = 0,
|
||||
.nrd_setup = 15,
|
||||
.ncs_write_setup = 0,
|
||||
.nwe_setup = 0,
|
||||
|
||||
.ncs_read_pulse = 115,
|
||||
.nrd_pulse = 110,
|
||||
.ncs_write_pulse = 60,
|
||||
.nwe_pulse = 60,
|
||||
|
||||
.read_cycle = 115,
|
||||
.write_cycle = 100,
|
||||
};
|
||||
|
||||
static struct smc_config flash_config __initdata = {
|
||||
.bus_width = 2,
|
||||
.nrd_controlled = 1,
|
||||
.nwe_controlled = 1,
|
||||
.byte_write = 1,
|
||||
};
|
||||
|
||||
/* system flash definition */
|
||||
|
||||
static struct mtd_partition flash_parts_system[] = {
|
||||
{
|
||||
.name = "u-boot",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x00020000, /* 128 KiB */
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
},
|
||||
{
|
||||
.name = "root",
|
||||
.offset = 0x00020000,
|
||||
.size = 0x007c0000,
|
||||
},
|
||||
{
|
||||
.name = "splash",
|
||||
.offset = 0x007e0000,
|
||||
.size = 0x00010000, /* 64KiB */
|
||||
},
|
||||
{
|
||||
.name = "env",
|
||||
.offset = 0x007f0000,
|
||||
.size = 0x00010000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct physmap_flash_data flash_system = {
|
||||
.width = 2,
|
||||
.nr_parts = ARRAY_SIZE(flash_parts_system),
|
||||
.parts = flash_parts_system,
|
||||
};
|
||||
|
||||
static struct resource flash_resource_system = {
|
||||
.start = 0x00000000,
|
||||
.end = 0x007fffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device flash_device_system = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.resource = &flash_resource_system,
|
||||
.num_resources = 1,
|
||||
.dev = {
|
||||
.platform_data = &flash_system,
|
||||
},
|
||||
};
|
||||
|
||||
/* data flash definition */
|
||||
|
||||
static struct mtd_partition flash_parts_data[] = {
|
||||
{
|
||||
.name = "data",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x00800000,
|
||||
},
|
||||
};
|
||||
|
||||
static struct physmap_flash_data flash_data = {
|
||||
.width = 2,
|
||||
.nr_parts = ARRAY_SIZE(flash_parts_data),
|
||||
.parts = flash_parts_data,
|
||||
};
|
||||
|
||||
static struct resource flash_resource_data = {
|
||||
.start = 0x08000000,
|
||||
.end = 0x087fffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device flash_device_data = {
|
||||
.name = "physmap-flash",
|
||||
.id = 1,
|
||||
.resource = &flash_resource_data,
|
||||
.num_resources = 1,
|
||||
.dev = {
|
||||
.platform_data = &flash_data,
|
||||
},
|
||||
};
|
||||
|
||||
/* This needs to be called after the SMC has been initialized */
|
||||
static int __init mimc200_flash_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
smc_set_timing(&flash_config, &flash_timing);
|
||||
ret = smc_set_configuration(0, &flash_config);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "mimc200: failed to set 'System' NOR flash timing\n");
|
||||
return ret;
|
||||
}
|
||||
ret = smc_set_configuration(1, &flash_config);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "mimc200: failed to set 'Data' NOR flash timing\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_device_register(&flash_device_system);
|
||||
platform_device_register(&flash_device_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(mimc200_flash_init);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user