* Re: [PATCH V6 09/10] USB/ppc4xx:Synopsys DWC OTG driver enable gadget support
From: Greg KH @ 2010-12-10 22:13 UTC (permalink / raw)
To: Tirumala Marri
Cc: Mark Miesfeld, linux-usb, linuxppc-dev, Fushen Chen,
Sergei Shtylyov
In-Reply-To: <AANLkTimp8iF2PxApA2kXF64TM47_EeGM9BZrfi1uEVJj@mail.gmail.com>
On Thu, Dec 09, 2010 at 08:52:45AM -0800, Tirumala Marri wrote:
> On Thu, Dec 9, 2010 at 5:24 AM, Sergei Shtylyov <sshtylyov@mvista.com> wrote:
> > Hello.
> >
> > On 09-12-2010 3:32, tmarri@apm.com wrote:
> >
> >> From: Tirumala Marri<tmarri@apm.com>
> >
> >> Enable gadget support
> >
> >> Signed-off-by: Tirumala R Marri<tmarri@apm.com>
> >> Signed-off-by: Fushen Chen<fchen@apm.com>
> >> Signed-off-by: Mark Miesfeld<mmiesfeld@apm.com>
> >
> > [...]
> >
> >> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> >> index 747b0d3..b2bcc4e 100644
> >> --- a/drivers/usb/gadget/Kconfig
> >> +++ b/drivers/usb/gadget/Kconfig
> >> @@ -365,6 +365,28 @@ config USB_GADGET_MUSB_HDRC
> >
> > [...]
> >>
> >> +config USB_OTG
> >> + boolean "OTG Support"
> >
> > This symbol is already defined in drivers/usb/core/Kconfig.
> >
> > WBR, Sergei
> >
> Sure I will fix that.
Other than this minor thing, the patches look good. I'll go apply
patches 1-8 for now, care to resend 9 and 10 with this change made?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH V6 01/10] USB/ppc4xx: Add Synopsys DWC OTG Register definitions
From: Greg KH @ 2010-12-10 22:33 UTC (permalink / raw)
To: tmarri; +Cc: Mark Miesfeld, linux-usb, linuxppc-dev, Fushen Chen
In-Reply-To: <1291854722-24744-1-git-send-email-tmarri@apm.com>
On Wed, Dec 08, 2010 at 04:32:02PM -0800, tmarri@apm.com wrote:
> From: Tirumala Marri <tmarri@apm.com>
>
> Add Synopsys Design Ware core register definitions.
>
> Signed-off-by: Tirumala R Marri<tmarri@apm.com>
Minor nit for future patches, you need a space after your name and
before the '<' character.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH V6 00/10] Add-Synopsys-DesignWare-HS-USB-OTG-driver
From: Greg KH @ 2010-12-10 22:44 UTC (permalink / raw)
To: tmarri; +Cc: linux-usb, linuxppc-dev
In-Reply-To: <1291854539-23879-1-git-send-email-tmarri@apm.com>
On Wed, Dec 08, 2010 at 04:28:59PM -0800, tmarri@apm.com wrote:
> From: Tirumala Marri <tmarri@apm.com>
>
> v6:
> 1. Replaced register definitions and bit fields with macros.
> 2. Replace printks with dev_dbg or dev_err functions.
> 3. Cleanup some assignments.
> 4. Remove chip specific selections in Kconfig file.
There are still a lot of checkpatch errors and warnings in these
patches. Patch 1-8 has:
total: 64 errors, 126 warnings, 13905 lines checked
Care to fix all of these up in your next submission? I can't take these
as-is, sorry.
And, if you haven't run checkpatch.pl before, odds are you haven't run
'sparse'. Please run that as well and resolve the issues it finds.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH -mm 0/4] RapidIO: Misc updates
From: Andrew Morton @ 2010-12-10 23:19 UTC (permalink / raw)
To: Alexandre Bounine; +Cc: linux-kernel, Thomas Moll, linuxppc-dev
In-Reply-To: <1292013498-31406-1-git-send-email-alexandre.bounine@idt.com>
On Fri, 10 Dec 2010 15:38:14 -0500
Alexandre Bounine <alexandre.bounine@idt.com> wrote:
> The following four patches are follow-up to two RapidIO patches
> that are in the -mm tree now.
>
> Alexandre Bounine (4):
> RapidIO: Add definitions of Component Tag fields
> RapidIO: Add device object linking into discovery
> RapidIO: Use Component Tag for unified switch identification
> RapidIO: Add new sysfs attributes
>
I held
rapidio-use-common-destid-storage-for-endpoints-and-switches.patch and
rapidio-integrate-rio_switch-into-rio_dev.patch back from 2.6.37 due to
ongoing discussion. What is the situation now?
^ permalink raw reply
* Re: [PATCH -mm 4/4] RapidIO: Add new sysfs attributes
From: Andrew Morton @ 2010-12-10 23:22 UTC (permalink / raw)
To: Alexandre Bounine; +Cc: linux-kernel, Thomas Moll, linuxppc-dev
In-Reply-To: <1292013498-31406-5-git-send-email-alexandre.bounine@idt.com>
On Fri, 10 Dec 2010 15:38:18 -0500
Alexandre Bounine <alexandre.bounine@idt.com> wrote:
> Add new sysfs attributes.
One would like to see documentation updates along with sysfs API
updates. But one fears that this entire interface wasn't documented
anyway :(
Please at least fully describe the proposed interface in the changelog
so others can review the proposal.
The proposed new sysfs files appear to break the
one-value-per-sysfs-file rule.
^ permalink raw reply
* [PATCH 7/7 v3] ppc: add dynamic dma window support
From: Nishanth Aravamudan @ 2010-12-11 0:07 UTC (permalink / raw)
To: sonnyrao, miltonm, Benjamin Herrenschmidt, Paul Mackerras,
Grant Likely, Anton Blanchard, linuxppc-dev
In-Reply-To: <20101209190920.GB25003@us.ibm.com>
On 09.12.2010 [11:09:20 -0800], Nishanth Aravamudan wrote:
> On 26.10.2010 [20:35:17 -0700], Nishanth Aravamudan wrote:
> > If firmware allows us to map all of a partition's memory for DMA on a
> > particular bridge, create a 1:1 mapping of that memory. Add hooks for
> > dealing with hotplug events. Dyanmic DMA windows can use larger than the
> > default page size, and we use the largest one possible.
> >
> > Not-yet-signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> >
> > ---
> >
> > I've tested this briefly on a machine with suitable firmware/hardware.
> > Things seem to work well, but I want to do more exhaustive I/O testing
> > before asking for upstream merging. I would really appreciate any
> > feedback on the updated approach.
> >
> > Specific questions:
> >
> > Ben, did I hook into the dma_set_mask() platform callback as you
> > expected? Anything I can do better or which perhaps might lead to
> > gotchas later?
> >
> > I've added a disable_ddw option, but perhaps it would be better to
> > just disable the feature if iommu=force?
>
> So for the final version, I probably should document this option in
> kernel-parameters.txt w/ the patch, right?
Here's an updated version. Ben, think you can pick this up to your tree?
Thanks,
Nish
ppc: add dynamic dma window support
If firmware allows us to map all of a partition's memory for DMA on a
particular bridge, create a 1:1 mapping of that memory. Add hooks for
dealing with hotplug events. Dyanmic DMA windows can use larger than the
default page size, and we use the largest one possible.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
---
I've tested this fairly heavily on a machine with suitable
firmware/hardware, including dlpar operations.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index cdd2a6e..e9ac890 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -618,6 +618,10 @@ and is between 256 and 4096 characters. It is defined in the file
disable= [IPV6]
See Documentation/networking/ipv6.txt.
+ disable_ddw [PPC]
+ Disable Dynamic DMA Window support. Use this if
+ to workaround buggy firmware.
+
disable_ipv6= [IPV6]
See Documentation/networking/ipv6.txt.
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 45c6865..4ba2338 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/crash_dump.h>
+#include <linux/memory.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -45,6 +46,7 @@
#include <asm/tce.h>
#include <asm/ppc-pci.h>
#include <asm/udbg.h>
+#include <asm/mmzone.h>
#include "plpar_wrappers.h"
@@ -270,6 +272,137 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
return tce_ret;
}
+/* this is compatable with cells for the device tree property */
+struct dynamic_dma_window_prop {
+ __be32 liobn; /* tce table number */
+ __be64 dma_base; /* address hi,lo */
+ __be32 tce_shift; /* ilog2(tce_page_size) */
+ __be32 window_shift; /* ilog2(tce_window_size) */
+};
+
+struct direct_window {
+ struct device_node *device;
+ const struct dynamic_dma_window_prop *prop;
+ struct list_head list;
+};
+static LIST_HEAD(direct_window_list);
+/* prevents races between memory on/offline and window creation */
+static DEFINE_SPINLOCK(direct_window_list_lock);
+/* protects initializing window twice for same device */
+static DEFINE_MUTEX(direct_window_init_mutex);
+#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+
+static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
+ unsigned long num_pfn, const void *arg)
+{
+ const struct dynamic_dma_window_prop *maprange = arg;
+ int rc;
+ u64 tce_size, num_tce, dma_offset, next;
+ u32 tce_shift;
+ long limit;
+
+ tce_shift = be32_to_cpu(maprange->tce_shift);
+ tce_size = 1ULL << tce_shift;
+ next = start_pfn << PAGE_SHIFT;
+ num_tce = num_pfn << PAGE_SHIFT;
+
+ /* round back to the beginning of the tce page size */
+ num_tce += next & (tce_size - 1);
+ next &= ~(tce_size - 1);
+
+ /* covert to number of tces */
+ num_tce |= tce_size - 1;
+ num_tce >>= tce_shift;
+
+ do {
+ /*
+ * Set up the page with TCE data, looping through and setting
+ * the values.
+ */
+ limit = min_t(long, num_tce, 512);
+ dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+ rc = plpar_tce_stuff((u64)be32_to_cpu(maprange->liobn),
+ (u64)dma_offset,
+ 0, limit);
+ num_tce -= limit;
+ } while (num_tce > 0 && !rc);
+
+ return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+ unsigned long num_pfn, const void *arg)
+{
+ const struct dynamic_dma_window_prop *maprange = arg;
+ u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
+ u32 tce_shift;
+ u64 rc = 0;
+ long l, limit;
+
+ local_irq_disable(); /* to protect tcep and the page behind it */
+ tcep = __get_cpu_var(tce_page);
+
+ if (!tcep) {
+ tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+ if (!tcep) {
+ local_irq_enable();
+ return -ENOMEM;
+ }
+ __get_cpu_var(tce_page) = tcep;
+ }
+
+ proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
+
+ liobn = (u64)be32_to_cpu(maprange->liobn);
+ tce_shift = be32_to_cpu(maprange->tce_shift);
+ tce_size = 1ULL << tce_shift;
+ next = start_pfn << PAGE_SHIFT;
+ num_tce = num_pfn << PAGE_SHIFT;
+
+ /* round back to the beginning of the tce page size */
+ num_tce += next & (tce_size - 1);
+ next &= ~(tce_size - 1);
+
+ /* covert to number of tces */
+ num_tce |= tce_size - 1;
+ num_tce >>= tce_shift;
+
+ /* We can map max one pageful of TCEs at a time */
+ do {
+ /*
+ * Set up the page with TCE data, looping through and setting
+ * the values.
+ */
+ limit = min_t(long, num_tce, 4096/TCE_ENTRY_SIZE);
+ dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+ for (l = 0; l < limit; l++) {
+ tcep[l] = proto_tce | next;
+ next += tce_size;
+ }
+
+ rc = plpar_tce_put_indirect(liobn,
+ (u64)dma_offset,
+ (u64)virt_to_abs(tcep),
+ limit);
+
+ num_tce -= limit;
+ } while (num_tce > 0 && !rc);
+
+ /* error cleanup: caller will clear whole range */
+
+ local_irq_enable();
+ return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP_walk(unsigned long start_pfn,
+ unsigned long num_pfn, void *arg)
+{
+ return tce_setrange_multi_pSeriesLP(start_pfn, num_pfn, arg);
+}
+
+
#ifdef CONFIG_PCI
static void iommu_table_setparms(struct pci_controller *phb,
struct device_node *dn,
@@ -449,8 +582,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
if (!ppci->iommu_table) {
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
ppci->phb->node);
- iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
- bus->number);
+ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
pr_debug(" created table: %p\n", ppci->iommu_table);
}
@@ -496,6 +628,328 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
pci_name(dev));
}
+static int __read_mostly disable_ddw;
+
+static int __init disable_ddw_setup(char *str)
+{
+ disable_ddw = 1;
+ printk(KERN_INFO "ppc iommu: disabling ddw.\n");
+
+ return 0;
+}
+
+early_param("disable_ddw", disable_ddw_setup);
+
+static void remove_ddw(struct device_node *np)
+{
+ struct dynamic_dma_window_prop *dwp;
+ struct property *win64;
+ const u32 *ddr_avail;
+ u64 liobn;
+ int len, ret;
+
+ ddr_avail = of_get_property(np, "ibm,ddw-applicable", &len);
+ win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
+ if (!win64 || !ddr_avail || len < 3 * sizeof(u32))
+ return;
+
+ dwp = win64->value;
+ liobn = (u64)be32_to_cpu(dwp->liobn);
+
+ /* clear the whole window, note the arg is in kernel pages */
+ ret = tce_clearrange_multi_pSeriesLP(0,
+ 1ULL << (be32_to_cpu(dwp->window_shift) - PAGE_SHIFT), dwp);
+ if (ret)
+ pr_warning("%s failed to clear tces in window.\n",
+ np->full_name);
+ else
+ pr_warning("%s successfully cleared tces in window.\n",
+ np->full_name);
+
+ ret = rtas_call(ddr_avail[2], 1, 1, NULL, liobn);
+ if (ret)
+ pr_warning("%s: failed to remove direct window: rtas returned "
+ "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+ np->full_name, ret, ddr_avail[2], liobn);
+ else
+ pr_warning("%s: successfully removed direct window: rtas returned "
+ "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+ np->full_name, ret, ddr_avail[2], liobn);
+}
+
+
+static int dupe_ddw_if_already_created(struct pci_dev *dev, struct device_node *pdn)
+{
+ struct device_node *dn;
+ struct pci_dn *pcidn;
+ struct direct_window *window;
+ const struct dynamic_dma_window_prop *direct64;
+ u64 dma_addr;
+
+ dn = pci_device_to_OF_node(dev);
+ pcidn = PCI_DN(dn);
+ spin_lock(&direct_window_list_lock);
+ /* check if we already created a window and dupe that config if so */
+ list_for_each_entry(window, &direct_window_list, list) {
+ if (window->device == pdn) {
+ direct64 = window->prop;
+ dma_addr = direct64->dma_base;
+ break;
+ }
+ }
+ spin_unlock(&direct_window_list_lock);
+
+ return dma_addr;
+}
+
+static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn)
+{
+ struct device_node *dn;
+ struct pci_dn *pcidn;
+ int len;
+ struct direct_window *window;
+ const struct dynamic_dma_window_prop *direct64;
+ u64 dma_addr;
+
+ dn = pci_device_to_OF_node(dev);
+ pcidn = PCI_DN(dn);
+ direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
+ if (direct64) {
+ window = kzalloc(sizeof(*window), GFP_KERNEL);
+ if (!window) {
+ remove_ddw(pdn);
+ } else {
+ window->device = pdn;
+ window->prop = direct64;
+ spin_lock(&direct_window_list_lock);
+ list_add(&window->list, &direct_window_list);
+ spin_unlock(&direct_window_list_lock);
+ dma_addr = direct64->dma_base;
+ }
+ }
+
+ return dma_addr;
+}
+
+static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail, u32 *query)
+{
+ struct device_node *dn;
+ struct pci_dn *pcidn;
+ u32 cfg_addr;
+ u64 buid;
+ int ret;
+
+ /*
+ * Get the config address and phb build of the PE window.
+ * Rely on eeh to retrieve this for us.
+ * Retrieve them from the pci device, not the node with the
+ * dma-window property
+ */
+ dn = pci_device_to_OF_node(dev);
+ pcidn = PCI_DN(dn);
+ cfg_addr = pcidn->eeh_config_addr;
+ if (pcidn->eeh_pe_config_addr)
+ cfg_addr = pcidn->eeh_pe_config_addr;
+ buid = pcidn->phb->buid;
+ ret = rtas_call(ddr_avail[0], 3, 5, query,
+ cfg_addr, BUID_HI(buid), BUID_LO(buid));
+ dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
+ " returned %d\n", ddr_avail[0], cfg_addr, BUID_HI(buid),
+ BUID_LO(buid), ret);
+ return ret;
+}
+
+static int create_ddw(struct pci_dev *dev, const u32 *ddr_avail, u32 *create, int page_shift, int window_shift)
+{
+ struct device_node *dn;
+ struct pci_dn *pcidn;
+ u32 cfg_addr;
+ u64 buid;
+ int ret;
+
+ /*
+ * Get the config address and phb build of the PE window.
+ * Rely on eeh to retrieve this for us.
+ * Retrieve them from the pci device, not the node with the
+ * dma-window property
+ */
+ dn = pci_device_to_OF_node(dev);
+ pcidn = PCI_DN(dn);
+ cfg_addr = pcidn->eeh_config_addr;
+ if (pcidn->eeh_pe_config_addr)
+ cfg_addr = pcidn->eeh_pe_config_addr;
+ buid = pcidn->phb->buid;
+
+ do {
+ /* extra outputs are LIOBN and dma-addr (hi, lo) */
+ ret = rtas_call(ddr_avail[1], 5, 4, &create[0], cfg_addr,
+ BUID_HI(buid), BUID_LO(buid), page_shift, window_shift);
+ } while(rtas_busy_delay(ret));
+ dev_info(&dev->dev,
+ "ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d "
+ "(liobn = 0x%x starting addr = %x %x)\n", ddr_avail[1],
+ cfg_addr, BUID_HI(buid), BUID_LO(buid), page_shift,
+ window_shift, ret, create[0], create[1], create[2]);
+
+ return ret;
+}
+
+/*
+ * If the PE supports dynamic dma windows, and there is space for a table
+ * that can map all pages in a linear offset, then setup such a table,
+ * and record the dma-offset in the struct device.
+ *
+ * dev: the pci device we are checking
+ * pdn: the parent pe node with the ibm,dma_window property
+ * Future: also check if we can remap the base window for our base page size
+ *
+ * returns the dma offset for use by dma_set_mask
+ */
+static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+{
+ int len, ret;
+ u32 query[4], create[3];
+ int page_shift;
+ u64 dma_addr, max_addr;
+ struct device_node *dn;
+ const u32 *uninitialized_var(ddr_avail);
+ struct direct_window *window;
+ struct property *uninitialized_var(win64);
+ struct dynamic_dma_window_prop *ddwprop;
+
+ mutex_lock(&direct_window_init_mutex);
+
+ dma_addr = dupe_ddw_if_already_created(dev, pdn);
+ if (dma_addr != 0)
+ goto out_unlock;
+
+ dma_addr = dupe_ddw_if_kexec(dev, pdn);
+ if (dma_addr != 0)
+ goto out_unlock;
+
+ /*
+ * the ibm,ddw-applicable property holds the tokens for:
+ * ibm,query-pe-dma-window
+ * ibm,create-pe-dma-window
+ * ibm,remove-pe-dma-window
+ * for the given node in that order.
+ * the property is actually in the parent, not the PE
+ */
+ ddr_avail = of_get_property(pdn, "ibm,ddw-applicable", &len);
+ if (!ddr_avail || len < 3 * sizeof(u32))
+ goto out_unlock;
+
+ /*
+ * Query if there is a second window of size to map the
+ * whole partition. Query returns number of windows, largest
+ * block assigned to PE (partition endpoint), and two bitmasks
+ * of page sizes: supported and supported for migrate-dma.
+ */
+ dn = pci_device_to_OF_node(dev);
+ ret = query_ddw(dev, ddr_avail, &query[0]);
+ if (ret != 0)
+ goto out_unlock;
+
+ if (!query[0]) {
+ /*
+ * no additional windows are available for this device.
+ * We might be able to reallocate the existing window,
+ * trading in for a larger page size.
+ */
+ dev_dbg(&dev->dev, "no free dynamic windows");
+ goto out_unlock;
+ }
+ if (query[2] & 4) {
+ page_shift = 24; /* 16MB */
+ } else if (query[2] & 2) {
+ page_shift = 16; /* 64kB */
+ } else if (query[2] & 1) {
+ page_shift = 12; /* 4kB */
+ } else {
+ dev_dbg(&dev->dev, "no supported direct page size in mask %x",
+ query[2]);
+ goto out_unlock;
+ }
+ /* verify the window * number of ptes will map the partition */
+ /* check largest block * page size > max memory hotplug addr */
+ max_addr = memory_hotplug_max();
+ if (query[1] < (max_addr >> page_shift)) {
+ dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
+ "%llu-sized pages\n", max_addr, query[1],
+ 1ULL << page_shift);
+ goto out_unlock;
+ }
+ len = order_base_2(max_addr);
+ win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
+ if (!win64) {
+ dev_info(&dev->dev,
+ "couldn't allocate property for 64bit dma window\n");
+ goto out_unlock;
+ }
+ win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
+ win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
+ if (!win64->name || !win64->value) {
+ dev_info(&dev->dev,
+ "couldn't allocate property name and value\n");
+ goto out_free_prop;
+ }
+
+ ret = create_ddw(dev, ddr_avail, &create[0], page_shift, len);
+ if (ret != 0)
+ goto out_free_prop;
+
+ *ddwprop = (struct dynamic_dma_window_prop) {
+ .liobn = cpu_to_be32(create[0]),
+ .dma_base = cpu_to_be64(((u64)create[1] << 32) + (u64)create[2]),
+ .tce_shift = cpu_to_be32(page_shift),
+ .window_shift = cpu_to_be32(len)
+ };
+
+ dev_dbg(&dev->dev, "created tce table LIOBN 0x%x for %s\n",
+ create[0], dn->full_name);
+
+ window = kzalloc(sizeof(*window), GFP_KERNEL);
+ if (!window)
+ goto out_clear_window;
+
+ ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
+ win64->value, tce_setrange_multi_pSeriesLP_walk);
+ if (ret) {
+ dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
+ dn->full_name, ret);
+ goto out_clear_window;
+ }
+
+ ret = prom_add_property(pdn, win64);
+ if (ret) {
+ dev_err(&dev->dev, "unable to add dma window property for %s: %d",
+ pdn->full_name, ret);
+ goto out_clear_window;
+ }
+
+ window->device = pdn;
+ window->prop = ddwprop;
+ spin_lock(&direct_window_list_lock);
+ list_add(&window->list, &direct_window_list);
+ spin_unlock(&direct_window_list_lock);
+
+ dma_addr = of_read_number(&create[1], 2);
+ set_dma_offset(&dev->dev, dma_addr);
+ goto out_unlock;
+
+out_clear_window:
+ remove_ddw(pdn);
+
+out_free_prop:
+ kfree(win64->name);
+ kfree(win64->value);
+ kfree(win64);
+
+out_unlock:
+ mutex_unlock(&direct_window_init_mutex);
+ return dma_addr;
+}
+
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{
struct device_node *pdn, *dn;
@@ -542,23 +996,129 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
set_iommu_table_base(&dev->dev, pci->iommu_table);
}
+
+static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
+{
+ bool ddw_enabled = false;
+ struct device_node *pdn, *dn;
+ struct pci_dev *pdev;
+ const void *dma_window = NULL;
+ u64 dma_offset;
+
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+
+ /* only attempt to use a new window if 64-bit DMA is requested */
+ if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
+ pdev = to_pci_dev(dev);
+
+ dn = pci_device_to_OF_node(pdev);
+ dev_dbg(dev, "node is %s\n", dn->full_name);
+
+ /*
+ * the device tree might contain the dma-window properties
+ * per-device and not neccesarily for the bus. So we need to
+ * search upwards in the tree until we either hit a dma-window
+ * property, OR find a parent with a table already allocated.
+ */
+ for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+ pdn = pdn->parent) {
+ dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+ if (dma_window)
+ break;
+ }
+ if (pdn && PCI_DN(pdn)) {
+ dma_offset = enable_ddw(pdev, pdn);
+ if (dma_offset != 0) {
+ dev_info(dev, "Using 64-bit direct DMA at offset %llx\n", dma_offset);
+ set_dma_offset(dev, dma_offset);
+ set_dma_ops(dev, &dma_direct_ops);
+ ddw_enabled = true;
+ }
+ }
+ }
+
+ /* fall-through to iommu ops */
+ if (!ddw_enabled) {
+ dev_info(dev, "Using 32-bit DMA via iommu\n");
+ set_dma_ops(dev, &dma_iommu_ops);
+ }
+
+ *dev->dma_mask = dma_mask;
+ return 0;
+}
+
#else /* CONFIG_PCI */
#define pci_dma_bus_setup_pSeries NULL
#define pci_dma_dev_setup_pSeries NULL
#define pci_dma_bus_setup_pSeriesLP NULL
#define pci_dma_dev_setup_pSeriesLP NULL
+#define dma_set_mask_pSeriesLP NULL
#endif /* !CONFIG_PCI */
+static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct direct_window *window;
+ struct memory_notify *arg = data;
+ int ret = 0;
+
+ switch (action) {
+ case MEM_GOING_ONLINE:
+ spin_lock(&direct_window_list_lock);
+ list_for_each_entry(window, &direct_window_list, list) {
+ ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
+ arg->nr_pages, window->prop);
+ /* XXX log error */
+ }
+ spin_unlock(&direct_window_list_lock);
+ break;
+ case MEM_CANCEL_ONLINE:
+ case MEM_OFFLINE:
+ spin_lock(&direct_window_list_lock);
+ list_for_each_entry(window, &direct_window_list, list) {
+ ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
+ arg->nr_pages, window->prop);
+ /* XXX log error */
+ }
+ spin_unlock(&direct_window_list_lock);
+ break;
+ default:
+ break;
+ }
+ if (ret && action != MEM_CANCEL_ONLINE)
+ return NOTIFY_BAD;
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block iommu_mem_nb = {
+ .notifier_call = iommu_mem_notifier,
+};
+
static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
{
int err = NOTIFY_OK;
struct device_node *np = node;
struct pci_dn *pci = PCI_DN(np);
+ struct direct_window *window;
switch (action) {
case PSERIES_RECONFIG_REMOVE:
if (pci && pci->iommu_table)
iommu_free_table(pci->iommu_table, np->full_name);
+
+ spin_lock(&direct_window_list_lock);
+ list_for_each_entry(window, &direct_window_list, list) {
+ if (window->device == np) {
+ list_del(&window->list);
+ kfree(window);
+ break;
+ }
+ }
+ spin_unlock(&direct_window_list_lock);
+
+ remove_ddw(np);
break;
default:
err = NOTIFY_DONE;
@@ -588,6 +1148,7 @@ void iommu_init_early_pSeries(void)
ppc_md.tce_get = tce_get_pSeriesLP;
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
+ ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
} else {
ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries;
@@ -598,6 +1159,7 @@ void iommu_init_early_pSeries(void)
pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+ register_memory_notifier(&iommu_mem_nb);
set_pci_dma_ops(&dma_iommu_ops);
}
--
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center
^ permalink raw reply related
* [PATCH 1/2] powerpc, mpc5200: update defconfig to fit with 2.6.37-rc4
From: Heiko Schocher @ 2010-12-11 6:13 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Heiko Schocher
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: linuxppc-dev@lists.ozlabs.org
---
- based against 2.6.37-rc4
- I did the following steps to generate this patch:
make mpc5200_defconfig
make savedefconfig
cp ./defconfig arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/mpc5200_defconfig | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 7376e27..6f75623 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,5 +1,6 @@
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -20,7 +21,6 @@ CONFIG_PPC_BESTCOMM=y
CONFIG_SIMPLE_GPIO=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
-CONFIG_SPARSE_IRQ=y
CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -52,7 +52,6 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_EEPROM_AT24=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -114,7 +113,6 @@ CONFIG_RTC_DRV_DS1307=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
@@ -132,5 +130,4 @@ CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_CRYPTO_ANSI_CPRNG is not set
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/2] powerpc, mpc5200: update mpc5200_defconfig to fit for charon board.
From: Heiko Schocher @ 2010-12-11 6:13 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Heiko Schocher
In-Reply-To: <1292047981-1435-1-git-send-email-hs@denx.de>
add to mpc5200_defconfig:
CONFIG_SENSORS_LM80=m
CONFIG_RTC_DRV_DS1374=m
as this is used by the charon board.
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: linuxppc-dev@lists.ozlabs.org
---
- based against 2.6.37-rc4
arch/powerpc/configs/mpc5200_defconfig | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 6f75623..70e5d8e 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -78,6 +78,7 @@ CONFIG_SPI_GPIO=m
CONFIG_SPI_MPC52xx=m
CONFIG_SPI_MPC52xx_PSC=m
CONFIG_SPI_SPIDEV=m
+CONFIG_SENSORS_LM80=m
CONFIG_WATCHDOG=y
CONFIG_DRM=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
@@ -110,6 +111,7 @@ CONFIG_USB_STORAGE=y
CONFIG_NEW_LEDS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
--
1.7.2.3
^ permalink raw reply related
* [PATCH v2 1/2] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2010-12-11 6:31 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, Heiko Schocher
In-Reply-To: <1291451028-22532-1-git-send-email-hs@denx.de>
- add binding to OF, compatible name "smi,sm501"
- add read/write functions for using this driver
also on powerpc plattforms
- add commandline options:
sm501.fb_mode:
Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
sm501.bpp:
Specify bit-per-pixel if not specified mode
- Add support for encoding display mode information
in the device tree using verbatim EDID block.
If the "edid" entry in the "smi,sm501" node is present,
the driver will build mode database using EDID data
and allow setting the display modes from this database.
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
---
- changes since v1:
add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
Paul Mundt.
Documentation/kernel-parameters.txt | 7 +
Documentation/powerpc/dts-bindings/sm501.txt | 30 +++
drivers/mfd/sm501.c | 141 ++++++++------
drivers/video/sm501fb.c | 264 +++++++++++++++++---------
include/linux/sm501.h | 8 +
5 files changed, 299 insertions(+), 151 deletions(-)
create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index cdd2a6e..6341541 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2301,6 +2301,13 @@ and is between 256 and 4096 characters. It is defined in the file
merging on their own.
For more information see Documentation/vm/slub.txt.
+ sm501.bpp= SM501 Display driver:
+ Specify bit-per-pixel if not specified mode
+
+ sm501fb.mode= SM501 Display driver:
+ Specify resolution as
+ "<xres>x<yres>[-<bpp>][@<refresh>]"
+
smart2= [HW]
Format: <io1>[,<io2>[,...,<io8>]]
diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 0000000..9905dd9
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,30 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+ - First entry: System Configuration register
+ - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+ <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+ Data from the detailed timing descriptor will be used to
+ program the display controller.
+
+Example for MPC5200:
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ interrupts = <1 1 3>;
+ mode = "640x480-32@60";
+ edid = [edid-data];
+ };
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index bc9275c..d1f952c 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -133,10 +133,10 @@ static unsigned long decode_div(unsigned long pll2, unsigned long val,
static void sm501_dump_clk(struct sm501_devdata *sm)
{
- unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
- unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
- unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
- unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
+ unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+ unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+ unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
unsigned long sdclk0, sdclk1;
unsigned long pll2 = 0;
@@ -193,29 +193,29 @@ static void sm501_dump_regs(struct sm501_devdata *sm)
void __iomem *regs = sm->regs;
dev_info(sm->dev, "System Control %08x\n",
- readl(regs + SM501_SYSTEM_CONTROL));
+ smc501_readl(regs + SM501_SYSTEM_CONTROL));
dev_info(sm->dev, "Misc Control %08x\n",
- readl(regs + SM501_MISC_CONTROL));
+ smc501_readl(regs + SM501_MISC_CONTROL));
dev_info(sm->dev, "GPIO Control Low %08x\n",
- readl(regs + SM501_GPIO31_0_CONTROL));
+ smc501_readl(regs + SM501_GPIO31_0_CONTROL));
dev_info(sm->dev, "GPIO Control Hi %08x\n",
- readl(regs + SM501_GPIO63_32_CONTROL));
+ smc501_readl(regs + SM501_GPIO63_32_CONTROL));
dev_info(sm->dev, "DRAM Control %08x\n",
- readl(regs + SM501_DRAM_CONTROL));
+ smc501_readl(regs + SM501_DRAM_CONTROL));
dev_info(sm->dev, "Arbitration Ctrl %08x\n",
- readl(regs + SM501_ARBTRTN_CONTROL));
+ smc501_readl(regs + SM501_ARBTRTN_CONTROL));
dev_info(sm->dev, "Misc Timing %08x\n",
- readl(regs + SM501_MISC_TIMING));
+ smc501_readl(regs + SM501_MISC_TIMING));
}
static void sm501_dump_gate(struct sm501_devdata *sm)
{
dev_info(sm->dev, "CurrentGate %08x\n",
- readl(sm->regs + SM501_CURRENT_GATE));
+ smc501_readl(sm->regs + SM501_CURRENT_GATE));
dev_info(sm->dev, "CurrentClock %08x\n",
- readl(sm->regs + SM501_CURRENT_CLOCK));
+ smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
dev_info(sm->dev, "PowerModeControl %08x\n",
- readl(sm->regs + SM501_POWER_MODE_CONTROL));
+ smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
}
#else
@@ -231,7 +231,7 @@ static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
static void sm501_sync_regs(struct sm501_devdata *sm)
{
- readl(sm->regs);
+ smc501_readl(sm->regs);
}
static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
@@ -261,11 +261,11 @@ int sm501_misc_control(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- misc = readl(sm->regs + SM501_MISC_CONTROL);
+ misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
to = (misc & ~clear) | set;
if (to != misc) {
- writel(to, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(to, sm->regs + SM501_MISC_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
@@ -294,11 +294,11 @@ unsigned long sm501_modify_reg(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- data = readl(sm->regs + reg);
+ data = smc501_readl(sm->regs + reg);
data |= set;
data &= ~clear;
- writel(data, sm->regs + reg);
+ smc501_writel(data, sm->regs + reg);
sm501_sync_regs(sm);
spin_unlock_irqrestore(&sm->reg_lock, save);
@@ -322,9 +322,9 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
mode &= 3; /* get current power mode */
@@ -356,14 +356,14 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -372,7 +372,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
goto already;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
@@ -519,9 +519,9 @@ unsigned long sm501_set_clock(struct device *dev,
unsigned long req_freq)
{
struct sm501_devdata *sm = dev_get_drvdata(dev);
- unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
- unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned char reg;
unsigned int pll_reg = 0;
unsigned long sm501_freq; /* the actual frequency achieved */
@@ -592,9 +592,9 @@ unsigned long sm501_set_clock(struct device *dev,
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
clock = clock & ~(0xFF << clksrc);
clock |= reg<<clksrc;
@@ -603,14 +603,14 @@ unsigned long sm501_set_clock(struct device *dev,
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -619,10 +619,11 @@ unsigned long sm501_set_clock(struct device *dev,
return -1;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
if (pll_reg)
- writel(pll_reg, sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
+ smc501_writel(pll_reg,
+ sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
sm501_sync_regs(sm);
@@ -905,7 +906,7 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
unsigned long result;
- result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+ result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
result >>= offset;
return result & 1UL;
@@ -918,13 +919,13 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
/* check and modify if this pin is not set as gpio. */
- if (readl(smchip->control) & bit) {
+ if (smc501_readl(smchip->control) & bit) {
dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
"changing mode of gpio, bit %08lx\n", bit);
- ctrl = readl(smchip->control);
+ ctrl = smc501_readl(smchip->control);
ctrl &= ~bit;
- writel(ctrl, smchip->control);
+ smc501_writel(ctrl, smchip->control);
sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
}
@@ -945,10 +946,10 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
if (value)
val |= bit;
- writel(val, regs);
+ smc501_writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -970,8 +971,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&smgpio->lock, save);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -997,18 +998,18 @@ static int sm501_gpio_output(struct gpio_chip *chip,
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW);
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW);
if (value)
val |= bit;
else
val &= ~bit;
- writel(val, regs);
+ smc501_writel(val, regs);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
- writel(val, regs + SM501_GPIO_DATA_LOW);
+ smc501_writel(val, regs + SM501_GPIO_DATA_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
spin_unlock_irqrestore(&smgpio->lock, save);
@@ -1234,7 +1235,7 @@ static ssize_t sm501_dbg_regs(struct device *dev,
for (reg = 0x00; reg < 0x70; reg += 4) {
ret = sprintf(ptr, "%08x = %08x\n",
- reg, readl(sm->regs + reg));
+ reg, smc501_readl(sm->regs + reg));
ptr += ret;
}
@@ -1258,10 +1259,10 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
{
unsigned long tmp;
- tmp = readl(sm->regs + reg);
+ tmp = smc501_readl(sm->regs + reg);
tmp &= ~r->mask;
tmp |= r->set;
- writel(tmp, sm->regs + reg);
+ smc501_writel(tmp, sm->regs + reg);
}
/* sm501_init_regs
@@ -1302,7 +1303,7 @@ static void sm501_init_regs(struct sm501_devdata *sm,
static int sm501_check_clocks(struct sm501_devdata *sm)
{
- unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long pwrmode = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
@@ -1337,7 +1338,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
INIT_LIST_HEAD(&sm->devices);
- devid = readl(sm->regs + SM501_DEVICEID);
+ devid = smc501_readl(sm->regs + SM501_DEVICEID);
if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
dev_err(sm->dev, "incorrect device id %08lx\n", devid);
@@ -1345,9 +1346,9 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
}
/* disable irqs */
- writel(0, sm->regs + SM501_IRQ_MASK);
+ smc501_writel(0, sm->regs + SM501_IRQ_MASK);
- dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+ dramctrl = smc501_readl(sm->regs + SM501_DRAM_CONTROL);
mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
@@ -1379,7 +1380,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
sm501_register_gpio(sm);
}
- if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+ if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
if (!sm501_gpio_isregistered(sm))
dev_err(sm->dev, "no gpio available for i2c gpio.\n");
else
@@ -1424,6 +1425,14 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+ if (sm->mem_res)
+ pr_debug("sm501 mem 0x%lx, 0x%lx\n",
+ sm->mem_res->start, sm->mem_res->end);
+ if (sm->io_res)
+ pr_debug("sm501 io 0x%lx, 0x%lx\n",
+ sm->io_res->start, sm->io_res->end);
+
if (sm->io_res == NULL || sm->mem_res == NULL) {
dev_err(&dev->dev, "failed to get IO resource\n");
ret = -ENOENT;
@@ -1492,7 +1501,7 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501_devdata *sm = platform_get_drvdata(pdev);
sm->in_suspend = 1;
- sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+ sm->pm_misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
sm501_dump_regs(sm);
@@ -1516,9 +1525,9 @@ static int sm501_plat_resume(struct platform_device *pdev)
/* check to see if we are in the same state as when suspended */
- if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+ if (smc501_readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
- writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
/* our suspend causes the controller state to change,
* either by something attempting setup, power loss,
@@ -1737,10 +1746,16 @@ static struct pci_driver sm501_pci_driver = {
MODULE_ALIAS("platform:sm501");
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+ { .compatible = "smi,sm501", },
+ { /* end */ }
+};
+
static struct platform_driver sm501_plat_driver = {
.driver = {
.name = "sm501",
.owner = THIS_MODULE,
+ .of_match_table = of_sm501_match_tbl,
},
.probe = sm501_plat_probe,
.remove = sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index b7dc180..fec8461 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -41,6 +41,26 @@
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
+#include "edid.h"
+
+static char *fb_mode = "640x480-16@60";
+static unsigned long default_bpp = 16;
+
+static struct fb_videomode __devinitdata sm501_default_mode = {
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 20833,
+ .left_margin = 142,
+ .right_margin = 13,
+ .upper_margin = 21,
+ .lower_margin = 1,
+ .hsync_len = 69,
+ .vsync_len = 3,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
#define NR_PALETTE 256
enum sm501_controller {
@@ -77,6 +97,7 @@ struct sm501fb_info {
void __iomem *regs2d; /* 2d remapped registers */
void __iomem *fbmem; /* remapped framebuffer */
size_t fbmem_len; /* length of remapped region */
+ u8 *edid_data;
};
/* per-framebuffer private data */
@@ -117,7 +138,7 @@ static inline int v_total(struct fb_var_screeninfo *var)
static inline void sm501fb_sync_regs(struct sm501fb_info *info)
{
- readl(info->regs);
+ smc501_readl(info->regs);
}
/* sm501_alloc_mem
@@ -262,7 +283,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
/* set gamma values */
for (offset = 0; offset < 256 * 4; offset += 4) {
- writel(value, fbi->regs + palette + offset);
+ smc501_writel(value, fbi->regs + palette + offset);
value += 0x010101; /* Advance RGB by 1,1,1.*/
}
}
@@ -476,7 +497,8 @@ static int sm501fb_set_par_common(struct fb_info *info,
/* set start of framebuffer to the screen */
- writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+ smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
+ fbi->regs + head_addr);
/* program CRT clock */
@@ -519,7 +541,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = info->fix.line_length;
reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
- writel(reg, fbi->regs + (par->head == HEAD_CRT ?
+ smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ?
SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET));
/* program horizontal total */
@@ -527,27 +549,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = (h_total(var) - 1) << 16;
reg |= (var->xres - 1);
- writel(reg, base + SM501_OFF_DC_H_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
/* program horizontal sync */
reg = var->hsync_len << 16;
reg |= var->xres + var->right_margin - 1;
- writel(reg, base + SM501_OFF_DC_H_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
/* program vertical total */
reg = (v_total(var) - 1) << 16;
reg |= (var->yres - 1);
- writel(reg, base + SM501_OFF_DC_V_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
/* program vertical sync */
reg = var->vsync_len << 16;
reg |= var->yres + var->lower_margin - 1;
- writel(reg, base + SM501_OFF_DC_V_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
}
/* sm501fb_pan_crt
@@ -566,15 +588,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
xoffs = var->xoffset * bytes_pixel;
- reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
reg |= ((xoffs & 15) / bytes_pixel) << 4;
- writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
reg = (par->screen.sm_addr + xoffs +
var->yoffset * info->fix.line_length);
- writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+ smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
sm501fb_sync_regs(fbi);
return 0;
@@ -593,10 +615,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
unsigned long reg;
reg = var->xoffset | (var->xres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
reg = var->yoffset | (var->yres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
sm501fb_sync_regs(fbi);
return 0;
@@ -622,7 +644,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
/* enable CRT DAC - note 0 is on!*/
sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
- control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
SM501_DC_CRT_CONTROL_GAMMA |
@@ -684,7 +706,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
out_update:
dev_dbg(fbi->dev, "new control is %08lx\n", control);
- writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -696,18 +718,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
- control = readl(ctrl_reg);
+ control = smc501_readl(ctrl_reg);
if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
/* enable panel power */
control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -719,7 +741,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -730,7 +752,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -742,7 +764,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -753,18 +775,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
control &= ~SM501_DC_PANEL_CONTROL_DATA;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control &= ~SM501_DC_PANEL_CONTROL_VDD;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -799,7 +821,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
/* update control register */
- control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
control &= (SM501_DC_PANEL_CONTROL_GAMMA |
SM501_DC_PANEL_CONTROL_VDD |
SM501_DC_PANEL_CONTROL_DATA |
@@ -833,16 +855,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
BUG();
}
- writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+ smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
/* panel plane top left and bottom right location */
- writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+ smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
reg = var->xres - 1;
reg |= (var->yres - 1) << 16;
- writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
/* program panel control register */
@@ -855,7 +877,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
control |= SM501_DC_PANEL_CONTROL_VSP;
- writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
sm501fb_sync_regs(fbi);
/* ensure the panel interface is not tristated at this point */
@@ -924,7 +946,7 @@ static int sm501fb_setcolreg(unsigned regno,
val |= (green >> 8) << 8;
val |= blue >> 8;
- writel(val, base + (regno * 4));
+ smc501_writel(val, base + (regno * 4));
}
break;
@@ -980,7 +1002,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
- ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
switch (blank_mode) {
case FB_BLANK_POWERDOWN:
@@ -1004,7 +1026,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
}
- writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -1041,12 +1063,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (cursor->image.depth > 1)
return -EINVAL;
- hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+ hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
if (cursor->enable)
- writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr | SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
else
- writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr & ~SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
/* set data */
if (cursor->set & FB_CUR_SETPOS) {
@@ -1060,7 +1084,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
//y += cursor->image.height;
- writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+ smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
}
if (cursor->set & FB_CUR_SETCMAP) {
@@ -1080,8 +1104,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
- writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
- writel(fg, base + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
}
if (cursor->set & FB_CUR_SETSIZE ||
@@ -1102,7 +1126,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
__func__, cursor->image.width, cursor->image.height);
for (op = 0; op < (64*64*2)/8; op+=4)
- writel(0x0, dst + op);
+ smc501_writel(0x0, dst + op);
for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < cursor->image.width; x++) {
@@ -1141,7 +1165,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
struct sm501fb_info *info = dev_get_drvdata(dev);
unsigned long ctrl;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
ctrl &= SM501_DC_CRT_CONTROL_SEL;
return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
@@ -1172,7 +1196,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
dev_info(dev, "setting crt source to head %d\n", head);
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
if (head == HEAD_CRT) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
@@ -1184,7 +1208,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
ctrl &= ~SM501_DC_CRT_CONTROL_TE;
}
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(info);
return len;
@@ -1205,7 +1229,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
unsigned int reg;
for (reg = start; reg < (len + start); reg += 4)
- ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+ ptr += sprintf(ptr, "%08x = %08x\n", reg,
+ smc501_readl(mem + reg));
return ptr - buf;
}
@@ -1257,7 +1282,7 @@ static int sm501fb_sync(struct fb_info *info)
/* wait for the 2d engine to be ready */
while ((count > 0) &&
- (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+ (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
count--;
@@ -1312,45 +1337,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* source and destination x y */
- writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
- writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+ smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do area move */
- writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
}
static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1372,47 +1398,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* colour */
- writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+ smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
/* x y */
- writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((rect->dx << 16) | rect->dy,
+ fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do rectangle fill */
- writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
}
@@ -1470,11 +1498,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
/* initialise the colour registers */
- writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+ smc501_writel(par->cursor.sm_addr,
+ par->cursor_regs + SM501_OFF_HWC_ADDR);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
sm501fb_sync_regs(info);
return 0;
@@ -1581,7 +1610,7 @@ static int sm501fb_start(struct sm501fb_info *info,
/* clear palette ram - undefined at power on */
for (k = 0; k < (256 * 3); k++)
- writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+ smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
/* enable display controller */
sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
@@ -1649,20 +1678,20 @@ static int sm501fb_init_fb(struct fb_info *fb,
switch (head) {
case HEAD_CRT:
pd = info->pdata->fb_crt;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
/* ensure we set the correct source register */
if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
}
break;
case HEAD_PANEL:
pd = info->pdata->fb_pnl;
- ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
break;
@@ -1680,7 +1709,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
enable = 0;
}
@@ -1698,6 +1727,9 @@ static int sm501fb_init_fb(struct fb_info *fb,
fb->fbops = &par->ops;
fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST |
FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+#if defined(CONFIG_PPC_MPC52xx)
+ FBINFO_FOREIGN_ENDIAN |
+#endif
FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
/* fixed data */
@@ -1717,9 +1749,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
fb->var.vmode = FB_VMODE_NONINTERLACED;
fb->var.bits_per_pixel = 16;
+ if (info->edid_data) {
+ /* Now build modedb from EDID */
+ fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
+ fb_videomode_to_modelist(fb->monspecs.modedb,
+ fb->monspecs.modedb_len,
+ &fb->modelist);
+ }
+
if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
/* TODO read the mode from the current display */
-
} else {
if (pd->def_mode) {
dev_info(info->dev, "using supplied mode\n");
@@ -1729,12 +1768,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
fb->var.xres_virtual = fb->var.xres;
fb->var.yres_virtual = fb->var.yres;
} else {
- ret = fb_find_mode(&fb->var, fb,
+ if (info->edid_data)
+ ret = fb_find_mode(&fb->var, fb, fb_mode,
+ fb->monspecs.modedb,
+ fb->monspecs.modedb_len,
+ &sm501_default_mode, default_bpp);
+ else
+ ret = fb_find_mode(&fb->var, fb,
NULL, NULL, 0, NULL, 8);
- if (ret == 0 || ret == 4) {
- dev_err(info->dev,
- "failed to get initial mode\n");
+ switch (ret) {
+ case 1:
+ dev_info(info->dev, "using mode specified in "
+ "@mode\n");
+ break;
+ case 2:
+ dev_info(info->dev, "using mode specified in "
+ "@mode with ignored refresh rate\n");
+ break;
+ case 3:
+ dev_info(info->dev, "using mode default "
+ "mode\n");
+ break;
+ case 4:
+ dev_info(info->dev, "using mode from list\n");
+ break;
+ default:
+ dev_info(info->dev, "ret = %d\n", ret);
+ dev_info(info->dev, "failed to find mode\n");
return -EINVAL;
}
}
@@ -1819,6 +1880,7 @@ static void sm501_free_init_fb(struct sm501fb_info *info,
{
struct fb_info *fbi = info->fb[head];
+ kfree(info->edid_data);
fb_dealloc_cmap(&fbi->cmap);
}
@@ -1875,8 +1937,29 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
}
if (info->pdata == NULL) {
- dev_info(dev, "using default configuration data\n");
+ int found = 0;
+#if defined(CONFIG_OF)
+ struct device_node *np = pdev->dev.parent->of_node;
+ const u8 *prop;
+ const char *cp;
+ int len;
+
info->pdata = &sm501fb_def_pdata;
+ if (np) {
+ /* Get EDID */
+ cp = of_get_property(np, "mode", &len);
+ if (cp)
+ strcpy(fb_mode, cp);
+ prop = of_get_property(np, "edid", &len);
+ if (prop && len == EDID_LENGTH) {
+ info->edid_data = kmemdup(prop, EDID_LENGTH,
+ GFP_KERNEL);
+ found = 1;
+ }
+ }
+#endif
+ if (!found)
+ dev_info(dev, "using default configuration data\n");
}
/* probe for the presence of each panel */
@@ -2085,7 +2168,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501fb_info *info = platform_get_drvdata(pdev);
/* store crt control to resume with */
- info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
sm501fb_suspend_fb(info, HEAD_CRT);
sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -2109,10 +2192,10 @@ static int sm501fb_resume(struct platform_device *pdev)
/* restore the items we want to be saved for crt control */
- crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
- writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_resume_fb(info, HEAD_CRT);
sm501fb_resume_fb(info, HEAD_PANEL);
@@ -2149,6 +2232,11 @@ static void __exit sm501fb_cleanup(void)
module_init(sm501fb_init);
module_exit(sm501fb_cleanup);
+module_param_named(mode, fb_mode, charp, 0);
+MODULE_PARM_DESC(mode,
+ "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+module_param_named(bpp, default_bpp, ulong, 0);
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
MODULE_DESCRIPTION("SM501 Framebuffer driver");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 214f932..090a07b 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -172,3 +172,11 @@ struct sm501_platdata {
struct sm501_platdata_gpio_i2c *gpio_i2c;
unsigned int gpio_i2c_nr;
};
+
+#if defined(CONFIG_PPC_MPC52xx)
+#define smc501_readl(addr) __do_readl_be((addr))
+#define smc501_writel(val, addr) __do_writel_be((val), (addr))
+#else
+#define smc501_readl(addr) readl(addr)
+#define smc501_writel(val, addr) writel(val, addr)
+#endif
--
1.7.2.3
^ permalink raw reply related
* [PATCH v3 2/2] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2010-12-11 6:31 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, Heiko Schocher
In-Reply-To: <1291451028-22532-2-git-send-email-hs@denx.de>
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
---
- based against 2.6.37-rc4
./scripts/checkpatch.pl 0003-powerpc-video-add-SM501-support-for-charon-board.patch
total: 0 errors, 0 warnings, 21 lines checked
0003-powerpc-video-add-SM501-support-for-charon-board.patch has no obvious style problems and is ready for submission.
- changes since v1:
- no board specific defconfig file for mpc52xx based boards as suggested
from Wolfram Sang
- changes since v2:
add Ben Dooks, Vincent Sanders and Samuel Ortiz and lkml to cc, as
suggested from Paul Mundt.
arch/powerpc/boot/dts/charon.dts | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 9776889..d9af022 100644
--- a/arch/powerpc/boot/dts/charon.dts
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -186,6 +186,7 @@
#address-cells = <2>;
#size-cells = <1>;
ranges = < 0 0 0xfc000000 0x02000000
+ 1 0 0xe0000000 0x04000000 // CS1 range, SM501
3 0 0xe8000000 0x00080000>;
flash@0,0 {
@@ -197,6 +198,14 @@
#address-cells = <1>;
};
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ mode = "640x480-32@60";
+ interrupts = <1 1 3>;
+ };
+
mram0@3,0 {
compatible = "mtd-ram";
reg = <3 0x00000 0x80000>;
--
1.7.2.3
^ permalink raw reply related
* Re: MPC831x (and others?) NAND erase performance improvements
From: Joakim Tjernlund @ 2010-12-11 9:14 UTC (permalink / raw)
To: Scott Wood; +Cc: Mark Mason, linuxppc-dev
In-Reply-To: <20101210115639.08d37db9@udp111988uds.am.freescale.net>
Scott Wood <scottwood@freescale.com> wrote on 2010/12/10 18:56:39:
>
> On Fri, 10 Dec 2010 13:39:01 +0100
> Joakim Tjernlund <joakim.tjernlund@transmode.se> wrote:
>
> > Scott Wood <scottwood@freescale.com> wrote on 2010/12/08 23:25:59:
> > >
> > > On Wed, 8 Dec 2010 17:02:45 -0500
> > > Mark Mason <mason@postdiluvian.org> wrote:
> > >
> > > > I don't think that using a software NAND controller instead of the LBC
> > > > FCM mode is all that bad. Again, I haven't actually done it, so check
> > > > the MTD docs, but I'm pretty sure the software is meant to do that, so
> > > > it doesn't even really constitute a "fix". Assuming that it is
> > > > supported then I doubt that configuring the NAND layer to use your
> > > > setup would be any harder than configuring the FCM.
> > >
> > > The MTD layer supports some really simple NAND controllers, but what do
> > > you mean by not having a controller at all? Hooking everything up to
> > > GPIO? Using UPM?
> > >
> > > There is already a UPM NAND driver, BTW.
> > >
> > > You would lose hardware ECC and the ability to be interrupt-driven (the
> > > latter should be possible with SW changes, using GPIO interrupts).
> >
> > hmm, you think it would be possible to use one of the IRQ pins instead?
>
> GPIO should be fine, software just needs to be changed to use the
> interrupt functionality.
>
> An external IRQ line would let you limit interrupts to rising edges
> rather than all edges, though you'd lose the ability to directly read
> the line status.
oh, one cannot read the IRQ line? didn't know that. Also I not sure
all Freescale CPUs can do rising edge.
^ permalink raw reply
* Re: [PATCH V6 00/10] Add-Synopsys-DesignWare-HS-USB-OTG-driver
From: Tirumala Marri @ 2010-12-11 17:53 UTC (permalink / raw)
To: Greg KH; +Cc: linux-usb, linuxppc-dev
In-Reply-To: <20101210224402.GA8943@kroah.com>
On Fri, Dec 10, 2010 at 2:44 PM, Greg KH <greg@kroah.com> wrote:
> On Wed, Dec 08, 2010 at 04:28:59PM -0800, tmarri@apm.com wrote:
>> From: Tirumala Marri <tmarri@apm.com>
>>
>> v6:
>> =A01. Replaced register definitions and bit fields with macros.
>> =A02. Replace printks with dev_dbg or dev_err functions.
>> =A03. Cleanup some assignments.
>> =A04. Remove chip specific selections in Kconfig file.
>
> There are still a lot of checkpatch errors and warnings in these
> patches. =A0Patch 1-8 has:
> =A0 =A0 =A0 =A0total: 64 errors, 126 warnings, 13905 lines checked
>
> Care to fix all of these up in your next submission? =A0I can't take thes=
e
> as-is, sorry.
>
> And, if you haven't run checkpatch.pl before, odds are you haven't run
> 'sparse'. =A0Please run that as well and resolve the issues it finds.
>
> thanks,
>
> greg k-h
>
I will fix the all these errors. Also will run use the sparse tool .
Regards,
Marri
^ permalink raw reply
* Re: [PATCH v2 1/2] video, sm501: add OF binding to support SM501
From: Randy Dunlap @ 2010-12-11 18:28 UTC (permalink / raw)
To: Heiko Schocher
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, linuxppc-dev
In-Reply-To: <1292049075-1809-1-git-send-email-hs@denx.de>
On Sat, 11 Dec 2010 07:31:15 +0100 Heiko Schocher wrote:
> - add commandline options:
> sm501.fb_mode:
sm501.mode:
> Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
> sm501.bpp:
> Specify bit-per-pixel if not specified mode
>
> ---
>
> Documentation/kernel-parameters.txt | 7 +
> Documentation/powerpc/dts-bindings/sm501.txt | 30 +++
> drivers/mfd/sm501.c | 141 ++++++++------
> drivers/video/sm501fb.c | 264 +++++++++++++++++---------
> include/linux/sm501.h | 8 +
> 5 files changed, 299 insertions(+), 151 deletions(-)
> create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index cdd2a6e..6341541 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2301,6 +2301,13 @@ and is between 256 and 4096 characters. It is defined in the file
> merging on their own.
> For more information see Documentation/vm/slub.txt.
>
> + sm501.bpp= SM501 Display driver:
> + Specify bit-per-pixel if not specified mode
Specifiy bits-per-pixel if not specified by 'mode'
> +
> + sm501fb.mode= SM501 Display driver:
> + Specify resolution as
> + "<xres>x<yres>[-<bpp>][@<refresh>]"
> +
> smart2= [HW]
> Format: <io1>[,<io2>[,...,<io8>]]
However, I think that these shouldn't be added to Documentation/kernel-parameters.txt
but should be added to the Documentation/fb/ sub-directory either by adding to
Documentation/fb/modedb.txt or by adding a new file Documentation/fb/sm501.txt.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* RE: [PATCH -mm 4/4] RapidIO: Add new sysfs attributes
From: Bounine, Alexandre @ 2010-12-11 18:49 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Thomas Moll, linuxppc-dev
In-Reply-To: <20101210152233.3786b432.akpm@linux-foundation.org>
Andrew Morton <akpm@linux-foundation.org> wrote:
>=20
> One would like to see documentation updates along with sysfs API
> updates. But one fears that this entire interface wasn't documented
> anyway :(
I think I have to find a time for that. I am adding it into my TODO
list.
=20
> Please at least fully describe the proposed interface in the changelog
> so others can review the proposal.
Will do.
=20
> The proposed new sysfs files appear to break the
> one-value-per-sysfs-file rule.
This is true for two of them. I was trying to find a better format for
them and at the end decided to break a rule and use port-device format
for this first version.
I may use just device name but "lnext" has to show multiple devices
anyway.
I decided the one-value-per-sysfs-file rule because it was broken once
already by the "routes" attribute (lprev and lnext have a similar
format).
^ permalink raw reply
* RE: [PATCH -mm 0/4] RapidIO: Misc updates
From: Bounine, Alexandre @ 2010-12-11 19:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Thomas Moll, linuxppc-dev
In-Reply-To: <20101210151924.333afed7.akpm@linux-foundation.org>
Andrew Morton <akpm@linux-foundation.org> wrote:
> I held
> rapidio-use-common-destid-storage-for-endpoints-and-switches.patch and
> rapidio-integrate-rio_switch-into-rio_dev.patch back from 2.6.37 due
to
> ongoing discussion. What is the situation now?
Sorry, it took me too long to do this follow-up.
Patches in this set are direct product of that discussion and address
the issue of unified switch identification brought by Micha Nelissen.
The implementation is different from what he would like to see but I
prefer to have minimal changes to the code combined with enough
flexibility to enable proprietary implementations if such are required.
Besides that discussion, I did not receive any complaints about the
changes that you are referencing above.
=20
^ permalink raw reply
* Re: [PATCH v2 1/2] video, sm501: add OF binding to support SM501
From: Randy Dunlap @ 2010-12-11 22:34 UTC (permalink / raw)
To: Heiko Schocher
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, linuxppc-dev
In-Reply-To: <1292049075-1809-1-git-send-email-hs@denx.de>
On Sat, 11 Dec 2010 07:31:15 +0100 Heiko Schocher wrote:
> - add commandline options:
> sm501.fb_mode:
sm501.mode:
> Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
> sm501.bpp:
> Specify bit-per-pixel if not specified mode
>
> ---
>
> Documentation/kernel-parameters.txt | 7 +
> Documentation/powerpc/dts-bindings/sm501.txt | 30 +++
> drivers/mfd/sm501.c | 141 ++++++++------
> drivers/video/sm501fb.c | 264 +++++++++++++++++---------
> include/linux/sm501.h | 8 +
> 5 files changed, 299 insertions(+), 151 deletions(-)
> create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index cdd2a6e..6341541 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2301,6 +2301,13 @@ and is between 256 and 4096 characters. It is defined in the file
> merging on their own.
> For more information see Documentation/vm/slub.txt.
>
> + sm501.bpp= SM501 Display driver:
> + Specify bit-per-pixel if not specified mode
Specifiy bits-per-pixel if not specified by 'mode'
> +
> + sm501fb.mode= SM501 Display driver:
Shouldn't that be sm501.mode ?
> + Specify resolution as
> + "<xres>x<yres>[-<bpp>][@<refresh>]"
> +
> smart2= [HW]
> Format: <io1>[,<io2>[,...,<io8>]]
However, I think that these shouldn't be added to Documentation/kernel-parameters.txt
but should be added to the Documentation/fb/ sub-directory either by adding to
Documentation/fb/modedb.txt or by adding a new file Documentation/fb/sm501.txt.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [PATCH 1/2] powerpc, mpc5200: update defconfig to fit with 2.6.37-rc4
From: Wolfram Sang @ 2010-12-12 8:47 UTC (permalink / raw)
To: Heiko Schocher; +Cc: linuxppc-dev
In-Reply-To: <1292047981-1435-1-git-send-email-hs@denx.de>
[-- Attachment #1: Type: text/plain, Size: 2115 bytes --]
On Sat, Dec 11, 2010 at 07:13:00AM +0100, Heiko Schocher wrote:
> Signed-off-by: Heiko Schocher <hs@denx.de>
I'd say the two patches can be merged. Dunno what Grant prefers whom you should
CC as he is the maintainer.
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: linuxppc-dev@lists.ozlabs.org
> ---
> - based against 2.6.37-rc4
> - I did the following steps to generate this patch:
>
> make mpc5200_defconfig
> make savedefconfig
> cp ./defconfig arch/powerpc/configs/mpc5200_defconfig
>
> arch/powerpc/configs/mpc5200_defconfig | 5 +----
> 1 files changed, 1 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
> index 7376e27..6f75623 100644
> --- a/arch/powerpc/configs/mpc5200_defconfig
> +++ b/arch/powerpc/configs/mpc5200_defconfig
> @@ -1,5 +1,6 @@
> CONFIG_EXPERIMENTAL=y
> CONFIG_SYSVIPC=y
> +CONFIG_SPARSE_IRQ=y
> CONFIG_LOG_BUF_SHIFT=14
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
> @@ -20,7 +21,6 @@ CONFIG_PPC_BESTCOMM=y
> CONFIG_SIMPLE_GPIO=y
> CONFIG_NO_HZ=y
> CONFIG_HIGH_RES_TIMERS=y
> -CONFIG_SPARSE_IRQ=y
> CONFIG_PM=y
> CONFIG_NET=y
> CONFIG_PACKET=y
> @@ -52,7 +52,6 @@ CONFIG_PROC_DEVICETREE=y
> CONFIG_BLK_DEV_LOOP=y
> CONFIG_BLK_DEV_RAM=y
> CONFIG_BLK_DEV_RAM_SIZE=32768
> -CONFIG_EEPROM_AT24=y
NACK.
> CONFIG_SCSI_TGT=y
> CONFIG_BLK_DEV_SD=y
> CONFIG_CHR_DEV_SG=y
> @@ -114,7 +113,6 @@ CONFIG_RTC_DRV_DS1307=y
> CONFIG_EXT2_FS=y
> CONFIG_EXT3_FS=y
> # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
> -CONFIG_INOTIFY=y
Are you sure?
> CONFIG_MSDOS_FS=y
> CONFIG_VFAT_FS=y
> CONFIG_PROC_KCORE=y
> @@ -132,5 +130,4 @@ CONFIG_PRINTK_TIME=y
> CONFIG_DEBUG_KERNEL=y
> CONFIG_DETECT_HUNG_TASK=y
> CONFIG_DEBUG_INFO=y
> -# CONFIG_RCU_CPU_STALL_DETECTOR is not set
> # CONFIG_CRYPTO_ANSI_CPRNG is not set
> --
> 1.7.2.3
>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH -mm 4/4] RapidIO: Add new sysfs attributes
From: Greg KH @ 2010-12-12 18:48 UTC (permalink / raw)
To: Alexandre Bounine; +Cc: linux-kernel, Thomas Moll, akpm, linuxppc-dev
In-Reply-To: <1292013498-31406-5-git-send-email-alexandre.bounine@idt.com>
On Fri, Dec 10, 2010 at 03:38:18PM -0500, Alexandre Bounine wrote:
> Add new sysfs attributes.
Like Andrew pointed out, all sysfs files are required to have entries in
Documentation/ABI. If the existing rapidio sysfs files are not
documented, please document them in there _before_ adding new ones.
thanks,
greg k-h
^ permalink raw reply
* Re: Getting the IRQ number (Was: Basic driver devel questions ?)
From: Michael Ellerman @ 2010-12-12 21:46 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
In-Reply-To: <201012101721.03689.dargaud@lpsc.in2p3.fr>
[-- Attachment #1: Type: text/plain, Size: 1356 bytes --]
On Fri, 2010-12-10 at 17:21 +0100, Guillaume Dargaud wrote:
> Hello all,
>
> > Also turn on CONFIG_DEBUG_DRIVER and see if that gives you anything
> > interesting.
>
> I see an unset CONFIG_DEBUG_KERNEL but no CONFIG_DEBUG_DRIVER in the .config of
> my current kernel.
Right you'd need to turn on CONFIG_DEBUG_KERNEL first, and then
CONFIG_DEBUG_DRIVER will appear.
> Does it need to be changed in the .config with a full kernel recompilation, or
> can I still benefit from it in my module only by doing a #define at the begining
> of my code ? Some #defines like DEBUG seem to work locally on things like
> dev_dbg but I doubt the CONFIG_* work the same...
No you'd need to rebuild your kernel. DEBUG is the only #define I can
think of that has an effect locally. Using different values for a
CONFIG_ in the kernel vs modules will not work.
> > Er. Not sure sorry. I can't see anything obviously wrong. Maybe post
> > your driver code again.
>
> Err... I ran it again this morning and it worked farther. I now get into the
> probe function and can now register my interrupt, yeah!, but I don't see the
> ISR being called. I'm currently checking if it can be a hardware problem
> before coming back here for more questions !
Great!
> BTW, is errno/strerror used within the kernel ?
Nope.
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* [PATCH] powerpc/pseries: Fix VPHN build errors on non-SMP systems
From: Jesse Larrew @ 2010-12-12 23:53 UTC (permalink / raw)
To: linuxppc-dev; +Cc: markn, tbreeds, lkessler, Jesse Larrew, mjwolf
From: Jesse Larrew <jlarrew@linux.vnet.ibm.com>
The VPHN feature is only meaningful on NUMA systems that implement
the SPLPAR option, so exclude the VPHN code on systems without
SPLPAR enabled.
This patch fixes a build problem on non-SMP systems introduced by the
following commits:
3b7a27db3b6b5501e3d1c1628e6d5a547ffe76c6
9eff1a38407c051273fe1a20f03f8155bd32de35
Signed-off-by: Jesse Larrew <jlarrew@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/topology.h | 20 +++++++++++---------
arch/powerpc/mm/numa.c | 3 +++
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index aed188b..a2832b8 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -93,9 +93,20 @@ extern void __init dump_numa_cpu_topology(void);
extern int sysfs_add_device_to_node(struct sys_device *dev, int nid);
extern void sysfs_remove_device_from_node(struct sys_device *dev, int nid);
+#ifdef CONFIG_SPLPAR
extern int start_topology_update(void);
extern int stop_topology_update(void);
#else
+static inline int start_topology_update(void)
+{
+ return 0;
+}
+static inline int stop_topology_update(void)
+{
+ return 0;
+}
+#endif /* CONFIG_SPLPAR */
+#else
static inline void dump_numa_cpu_topology(void) {}
@@ -108,15 +119,6 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
int nid)
{
}
-
-static inline int start_topology_update(void)
-{
- return 0;
-}
-static inline int stop_topology_update(void)
-{
- return 0;
-}
#endif /* CONFIG_NUMA */
#include <asm-generic/topology.h>
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 42aa7d1..0f50941 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -28,6 +28,7 @@
#include <asm/smp.h>
#include <asm/firmware.h>
#include <asm/paca.h>
+#include <asm/hvcall.h>
static int numa_enabled = 1;
@@ -1263,6 +1264,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
#endif /* CONFIG_MEMORY_HOTPLUG */
/* Vrtual Processor Home Node (VPHN) support */
+#ifdef CONFIG_SPLPAR
#define VPHN_NR_CHANGE_CTRS (8)
static u8 vphn_cpu_change_counts[NR_CPUS][VPHN_NR_CHANGE_CTRS];
static cpumask_t cpu_associativity_changes_mask;
@@ -1505,3 +1507,4 @@ int stop_topology_update(void)
vphn_enabled = 0;
return del_timer_sync(&topology_timer);
}
+#endif /* CONFIG_SPLPAR */
--
1.7.2.3
^ permalink raw reply related
* Re: [PATCH v2 1/2] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2010-12-13 7:01 UTC (permalink / raw)
To: Randy Dunlap
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, linuxppc-dev
In-Reply-To: <20101211143454.ccc5e296.rdunlap@xenotime.net>
Hello Randy,
Randy Dunlap wrote:
> On Sat, 11 Dec 2010 07:31:15 +0100 Heiko Schocher wrote:
>
>> - add commandline options:
>> sm501.fb_mode:
>
> sm501.mode:
Sorry, type, should be "sm501fb.mode", thanks!
>> Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
>> sm501.bpp:
Here too, "sm501fb.bpp"
>> Specify bit-per-pixel if not specified mode
>>
>> ---
>>
>> Documentation/kernel-parameters.txt | 7 +
>> Documentation/powerpc/dts-bindings/sm501.txt | 30 +++
>> drivers/mfd/sm501.c | 141 ++++++++------
>> drivers/video/sm501fb.c | 264 +++++++++++++++++---------
>> include/linux/sm501.h | 8 +
>> 5 files changed, 299 insertions(+), 151 deletions(-)
>> create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>>
>> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
>> index cdd2a6e..6341541 100644
>> --- a/Documentation/kernel-parameters.txt
>> +++ b/Documentation/kernel-parameters.txt
>> @@ -2301,6 +2301,13 @@ and is between 256 and 4096 characters. It is defined in the file
>> merging on their own.
>> For more information see Documentation/vm/slub.txt.
>>
>> + sm501.bpp= SM501 Display driver:
>> + Specify bit-per-pixel if not specified mode
>
> Specifiy bits-per-pixel if not specified by 'mode'
>
>> +
>> + sm501fb.mode= SM501 Display driver:
>
> Shouldn't that be sm501.mode ?
No, the name of the source file is sm501fb.c -> sm501fb is right here.
As the sm501 is a multifunction device, the "fb" is more precise here.
>> + Specify resolution as
>> + "<xres>x<yres>[-<bpp>][@<refresh>]"
>> +
>> smart2= [HW]
>> Format: <io1>[,<io2>[,...,<io8>]]
>
>
> However, I think that these shouldn't be added to Documentation/kernel-parameters.txt
> but should be added to the Documentation/fb/ sub-directory either by adding to
> Documentation/fb/modedb.txt or by adding a new file Documentation/fb/sm501.txt.
Ok, do this. Thanks for the review!
bye,
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply
* Re: [PATCH 1/2] powerpc, mpc5200: update defconfig to fit with 2.6.37-rc4
From: Heiko Schocher @ 2010-12-13 7:09 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev
In-Reply-To: <20101212084707.GA14580@pengutronix.de>
Hello Wolfram,
Wolfram Sang wrote:
> On Sat, Dec 11, 2010 at 07:13:00AM +0100, Heiko Schocher wrote:
>> Signed-off-by: Heiko Schocher <hs@denx.de>
>
> I'd say the two patches can be merged. Dunno what Grant prefers whom you should
> CC as he is the maintainer.
I prefer the split in two patches, so we can see, what is added
by the charon board, and what by "make mpc5200_defconfig" ...
>> cc: Wolfram Sang <w.sang@pengutronix.de>
>> cc: linuxppc-dev@lists.ozlabs.org
>> ---
>> - based against 2.6.37-rc4
>> - I did the following steps to generate this patch:
>>
>> make mpc5200_defconfig
>> make savedefconfig
>> cp ./defconfig arch/powerpc/configs/mpc5200_defconfig
>>
>> arch/powerpc/configs/mpc5200_defconfig | 5 +----
>> 1 files changed, 1 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
>> index 7376e27..6f75623 100644
>> --- a/arch/powerpc/configs/mpc5200_defconfig
>> +++ b/arch/powerpc/configs/mpc5200_defconfig
>> @@ -1,5 +1,6 @@
>> CONFIG_EXPERIMENTAL=y
>> CONFIG_SYSVIPC=y
>> +CONFIG_SPARSE_IRQ=y
>> CONFIG_LOG_BUF_SHIFT=14
>> CONFIG_BLK_DEV_INITRD=y
>> # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
>> @@ -20,7 +21,6 @@ CONFIG_PPC_BESTCOMM=y
>> CONFIG_SIMPLE_GPIO=y
>> CONFIG_NO_HZ=y
>> CONFIG_HIGH_RES_TIMERS=y
>> -CONFIG_SPARSE_IRQ=y
>> CONFIG_PM=y
>> CONFIG_NET=y
>> CONFIG_PACKET=y
>> @@ -52,7 +52,6 @@ CONFIG_PROC_DEVICETREE=y
>> CONFIG_BLK_DEV_LOOP=y
>> CONFIG_BLK_DEV_RAM=y
>> CONFIG_BLK_DEV_RAM_SIZE=32768
>> -CONFIG_EEPROM_AT24=y
>
> NACK.
... I did just the steps above mentioned, so this is
automagically done by "make mpc5200_defconfig" !
>> CONFIG_SCSI_TGT=y
>> CONFIG_BLK_DEV_SD=y
>> CONFIG_CHR_DEV_SG=y
>> @@ -114,7 +113,6 @@ CONFIG_RTC_DRV_DS1307=y
>> CONFIG_EXT2_FS=y
>> CONFIG_EXT3_FS=y
>> # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
>> -CONFIG_INOTIFY=y
>
> Are you sure?
See comment above, did just the "make mpc5200_defconfig"
step ...
>> CONFIG_MSDOS_FS=y
>> CONFIG_VFAT_FS=y
>> CONFIG_PROC_KCORE=y
>> @@ -132,5 +130,4 @@ CONFIG_PRINTK_TIME=y
>> CONFIG_DEBUG_KERNEL=y
>> CONFIG_DETECT_HUNG_TASK=y
>> CONFIG_DEBUG_INFO=y
>> -# CONFIG_RCU_CPU_STALL_DETECTOR is not set
>> # CONFIG_CRYPTO_ANSI_CPRNG is not set
>> --
>> 1.7.2.3
Thanks for the review!
bye,
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply
* RE: [PATCH v5] ppc44x:PHY fixup for USB on canyonlands board
From: Rupjyoti Sarmah @ 2010-12-13 7:17 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20101210133905.GE1903@zod.rchland.ibm.com>
>This can fail if you boot a new kernel on a board with an old FDT that
lacks the gpio node. Calling of_iomap with a NULL np seems like it would
work without crashing anything, so maybe that's not a huge issue.
>>+ vaddr = of_iomap(np, 0);
>>+ if (!vaddr) {
>>+ printk(KERN_CRIT "Could not get gpio node address\n");
>>+ ret = -ENODEV;
>>+ goto err_bcsr;
>>+ }
>A reference count is leaked for the node in this error case because
of_node_put isn't called for the gpio node. Also, iounmap is never called
on vaddr.
>>+ /* Disable USB, through the BCSR7 bits */
Thanks for your inputs. I will fix and resubmit.
Regards,
Rup
^ permalink raw reply
* Re: ppc_set_hwdebug vs ptrace_set_debugreg
From: K.Prasad @ 2010-12-13 8:26 UTC (permalink / raw)
To: Andreas Schwab
Cc: linuxppc-dev, Dave Kleikamp, Srikar Dronamraju, Paul Mackerras
In-Reply-To: <20101201043758.GA2219@in.ibm.com>
On Wed, Dec 01, 2010 at 10:07:58AM +0530, K.Prasad wrote:
> On Mon, Nov 29, 2010 at 11:15:51AM +0100, Andreas Schwab wrote:
> > "K.Prasad" <prasad@linux.vnet.ibm.com> writes:
> >
> > > Although ppc_set_hwdebug() can set DABR through set_dabr() in
> > > arch/powerpc/kernel/process.c, it is good to have it converted to use
> > > register_user_hw_breakpoint().
> >
> > What do you mean with "good to have"? It doesn't work without it unless
> > I disable PERF_EVENTS (which is the only way to disable
> > HAVE_HW_BREAKPOINT).
> >
> > Andreas.
> >
>
> Let me see if I can cook up a patch for this i.e. make set_dabr() invoke
> register_user_hw_breakpoint() when CONFIG_PPC_BOOK3S is defined; before I
> head out on my vacation (starting second week of this month).
>
> Thanks,
> K.Prasad
>
Hi,
Can you check if the following patch (compile tested only) works
for you?
Thanks,
K.Prasad
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/kernel/ptrace.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
Index: linux-2.6.set_hwdebug/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6.set_hwdebug.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6.set_hwdebug/arch/powerpc/kernel/ptrace.c
@@ -1316,6 +1316,11 @@ static int set_dac_range(struct task_str
static long ppc_set_hwdebug(struct task_struct *child,
struct ppc_hw_breakpoint *bp_info)
{
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ struct perf_event *bp;
+ struct perf_event_attr attr;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
if (bp_info->version != 1)
return -ENOTSUPP;
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -1362,10 +1367,29 @@ static long ppc_set_hwdebug(struct task_
if (child->thread.dabr)
return -ENOSPC;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ if (child->thread->ptrace_bps[0])
+ return -ENOSPC;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
if ((unsigned long)bp_info->addr >= TASK_SIZE)
return -EIO;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ /* Create a new breakpoint request if one doesn't exist already */
+ hw_breakpoint_init(&attr);
+ attr.bp_addr = bp_info->addr & ~HW_BREAKPOINT_ALIGN;
+ arch_bp_generic_fields(bp_info->addr &
+ (DABR_DATA_WRITE | DABR_DATA_READ),
+ &attr.bp_type);
+
+ bp = register_user_hw_breakpoint(&attr, ptrace_triggered, task);
+ if (IS_ERR(bp))
+ return PTR_ERR(bp);
+
+ child->thread.ptrace_bps[0] = bp;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
child->thread.dabr = (unsigned long)bp_info->addr;
return 1;
@@ -1395,6 +1419,16 @@ static long ppc_del_hwdebug(struct task_
return -EINVAL;
if (child->thread.dabr == 0)
return -ENOENT;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ /*
+ * There is no way by which address in ptrace_bps[0] and thread.dabr
+ * can be different. So we don't explicitly check if they're the same
+ */
+ if (child->thread.ptrace_bps[0]) {
+ unregister_hw_breakpoint(child->thread.ptrace_bps[0]);
+ child->thread.ptrace_bps[0] = NULL;
+ }
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
child->thread.dabr = 0;
^ permalink raw reply
* RE: MPC831x (and others?) NAND erase performance improvements
From: David Laight @ 2010-12-13 8:33 UTC (permalink / raw)
To: Joakim Tjernlund, Scott Wood; +Cc: Mark Mason, linuxppc-dev
In-Reply-To: <OF51D61C57.96435CC9-ONC12577F6.00326299-C12577F6.0032BA93@transmode.se>
=20
> > An external IRQ line would let you limit interrupts to rising edges
> > rather than all edges, though you'd lose the ability to=20
> > directly read the line status.
>=20
> oh, one cannot read the IRQ line? didn't know that. Also I not sure
> all Freescale CPUs can do rising edge.
I suspect that you may be able to leave the interupt masked, but still
read the 'interrupt pending' register. Which would have the same effect.
Our HW engineers tend to feed everything into an FPGA since it
gives than a lot more flexibility over pin connections.
In which case the invertor is trivial.
(and the fpga interface can read the status!)
David
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox