* [patch 4/6] PS3: Interrupt routine fixups.
From: Geoff Levand @ 2007-04-30 21:01 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20070430202420.872228544@am.sony.com>
Fixups for the ps3 interrupt routines to support all HV device
in a generic way.
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/interrupt.c | 234 +++++++++++++++++++++++----------
arch/powerpc/platforms/ps3/smp.c | 6
arch/powerpc/platforms/ps3/spu.c | 16 +-
drivers/ps3/vuart.c | 8 -
drivers/usb/host/ehci-ps3.c | 4
drivers/usb/host/ohci-ps3.c | 4
drivers/video/ps3fb.c | 12 -
include/asm-powerpc/ps3.h | 33 ++--
8 files changed, 211 insertions(+), 106 deletions(-)
--- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/interrupt.c
+++ ps3-linux-dev/arch/powerpc/platforms/ps3/interrupt.c
@@ -89,7 +89,18 @@ struct ps3_private {
static DEFINE_PER_CPU(struct ps3_private, ps3_private);
-int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
+/**
+ * ps3_virq_setup - virq related setup.
+ * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
+ * serviced on.
+ * @outlet: The HV outlet from the various create outlet routines.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls irq_create_mapping() to get a virq and sets the chip data to
+ * ps3_private data.
+ */
+
+int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
unsigned int *virq)
{
int result;
@@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding c
goto fail_create;
}
- /* Binds outlet to cpu + virq. */
-
- result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
-
- if (result) {
- pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
- __func__, __LINE__, ps3_result(result));
- result = -EPERM;
- goto fail_connect;
- }
-
pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
outlet, cpu, *virq);
@@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding c
return result;
fail_set:
- lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq);
-fail_connect:
irq_dispose_mapping(*virq);
fail_create:
return result;
}
-EXPORT_SYMBOL_GPL(ps3_alloc_irq);
-int ps3_free_irq(unsigned int virq)
+/**
+ * ps3_virq_destroy - virq related teardown.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears chip data and calls irq_dispose_mapping() for the virq.
+ */
+
+int ps3_virq_destroy(unsigned int virq)
{
- int result;
const struct ps3_private *pd = get_irq_chip_data(virq);
pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
pd->node, pd->cpu, virq);
- result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
-
- if (result)
- pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
- __func__, __LINE__, ps3_result(result));
-
set_irq_chip_data(virq, NULL);
irq_dispose_mapping(virq);
- return result;
+
+ pr_debug("%s:%d <-\n", __func__, __LINE__);
+ return 0;
}
-EXPORT_SYMBOL_GPL(ps3_free_irq);
/**
- * ps3_alloc_io_irq - Assign a virq to a system bus device.
+ * ps3_irq_plug_setup - Generic outlet and virq related setup.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @outlet: The HV outlet from the various create outlet routines.
* @virq: The assigned Linux virq.
*
- * An io irq represents a non-virtualized device interrupt. interrupt_id
- * coresponds to the interrupt number of the interrupt controller.
+ * Sets up virq and connects the irq plug.
*/
-int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
unsigned int *virq)
{
int result;
- unsigned long outlet;
+ struct ps3_private *pd;
- result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
+ result = ps3_virq_setup(cpu, outlet, virq);
if (result) {
- pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
- __func__, __LINE__, ps3_result(result));
- return result;
+ pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
+ goto fail_setup;
}
- result = ps3_alloc_irq(cpu, outlet, virq);
- BUG_ON(result);
+ pd = get_irq_chip_data(*virq);
+
+ /* Binds outlet to cpu + virq. */
+
+ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
+ if (result) {
+ pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ result = -EPERM;
+ goto fail_connect;
+ }
+
+ return result;
+
+fail_connect:
+ ps3_virq_destroy(*virq);
+fail_setup:
return result;
}
-EXPORT_SYMBOL_GPL(ps3_alloc_io_irq);
+EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
+
+/**
+ * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
+ * @virq: The assigned Linux virq.
+ *
+ * Disconnects the irq plug and tears down virq.
+ * Do not call for system bus event interrupts setup with
+ * ps3_sb_event_receive_port_setup().
+ */
-int ps3_free_io_irq(unsigned int virq)
+int ps3_irq_plug_destroy(unsigned int virq)
{
int result;
+ const struct ps3_private *pd = get_irq_chip_data(virq);
- result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+ pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
+ pd->node, pd->cpu, virq);
+
+ result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
if (result)
- pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
- __func__, __LINE__, ps3_result(result));
+ pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
- ps3_free_irq(virq);
+ ps3_virq_destroy(virq);
return result;
}
-EXPORT_SYMBOL_GPL(ps3_free_io_irq);
+EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
/**
- * ps3_alloc_event_irq - Allocate a virq for use with a system event.
+ * ps3_event_receive_port_setup - Setup an event receive port.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
* @virq: The assigned Linux virq.
*
* The virq can be used with lv1_connect_interrupt_event_receive_port() to
- * arrange to receive events, or with ps3_send_event_locally() to signal
- * events.
+ * arrange to receive interrupts from system-bus devices, or with
+ * ps3_send_event_locally() to signal events.
*/
-int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
+int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
{
int result;
unsigned long outlet;
@@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_bin
return result;
}
- result = ps3_alloc_irq(cpu, outlet, virq);
+ result = ps3_irq_plug_setup(cpu, outlet, virq);
BUG_ON(result);
return result;
}
+EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
+
+/**
+ * ps3_event_receive_port_destroy - Destroy an event receive port.
+ * @virq: The assigned Linux virq.
+ *
+ * Since ps3_event_receive_port_destroy destroys the receive port outlet,
+ * SB devices need to call disconnect_interrupt_event_receive_port() before
+ * this.
+ */
-int ps3_free_event_irq(unsigned int virq)
+int ps3_event_receive_port_destroy(unsigned int virq)
{
int result;
- pr_debug(" -> %s:%d\n", __func__, __LINE__);
+ pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
result = lv1_destruct_event_receive_port(virq_to_hw(virq));
@@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq
pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
__func__, __LINE__, ps3_result(result));
- ps3_free_irq(virq);
+ /* lv1_destruct_event_receive_port() destroys the IRQ plug,
+ * so don't call ps3_irq_plug_destroy() here.
+ */
+
+ result = ps3_virq_destroy(virq);
+ BUG_ON(result);
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
+EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
int ps3_send_event_locally(unsigned int virq)
{
@@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int
}
/**
- * ps3_connect_event_irq - Assign a virq to a system bus device.
+ * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
* @did: The HV device identifier read from the system repository.
@@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int
* coresponds to the software interrupt number.
*/
-int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
+int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
const struct ps3_device_id *did, unsigned int interrupt_id,
unsigned int *virq)
{
+ /* this should go in system-bus.c */
+
int result;
- result = ps3_alloc_event_irq(cpu, virq);
+ result = ps3_event_receive_port_setup(cpu, virq);
if (result)
return result;
@@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_b
pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
" failed: %s\n", __func__, __LINE__,
ps3_result(result));
- ps3_free_event_irq(*virq);
+ ps3_event_receive_port_destroy(*virq);
*virq = NO_IRQ;
return result;
}
@@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_b
return 0;
}
+EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
-int ps3_disconnect_event_irq(const struct ps3_device_id *did,
+int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
unsigned int interrupt_id, unsigned int virq)
{
+ /* this should go in system-bus.c */
+
int result;
pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
@@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struc
" failed: %s\n", __func__, __LINE__,
ps3_result(result));
- ps3_free_event_irq(virq);
+ result = ps3_event_receive_port_destroy(virq);
+ BUG_ON(result);
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
+EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
/**
- * ps3_alloc_vuart_irq - Configure the system virtual uart virq.
+ * ps3_io_irq_setup - Setup a system bus io irq.
+ * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
+ * serviced on.
+ * @interrupt_id: The device interrupt id read from the system repository.
+ * @virq: The assigned Linux virq.
+ *
+ * An io irq represents a non-virtualized device interrupt. interrupt_id
+ * coresponds to the interrupt number of the interrupt controller.
+ */
+
+int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+ unsigned int *virq)
+{
+ int result;
+ unsigned long outlet;
+
+ result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
+
+ if (result) {
+ pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ result = ps3_irq_plug_setup(cpu, outlet, virq);
+ BUG_ON(result);
+
+ return result;
+}
+EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
+
+int ps3_io_irq_destroy(unsigned int virq)
+{
+ int result;
+
+ result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+
+ if (result)
+ pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ result = ps3_irq_plug_destroy(virq);
+ BUG_ON(result);
+
+ return result;
+}
+EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
+
+/**
+ * ps3_vuart_irq_setup - Setup the system virtual uart virq.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
* @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
@@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struc
* freeing the interrupt will return a wrong state error.
*/
-int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
+int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
unsigned int *virq)
{
int result;
@@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_bin
return result;
}
- result = ps3_alloc_irq(cpu, outlet, virq);
+ result = ps3_irq_plug_setup(cpu, outlet, virq);
BUG_ON(result);
return result;
}
-int ps3_free_vuart_irq(unsigned int virq)
+int ps3_vuart_irq_destroy(unsigned int virq)
{
int result;
@@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq
return result;
}
- ps3_free_irq(virq);
+ result = ps3_irq_plug_destroy(virq);
+ BUG_ON(result);
return result;
}
/**
- * ps3_alloc_spe_irq - Configure an spe virq.
+ * ps3_spe_irq_setup - Setup an spe virq.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
* @spe_id: The spe_id returned from lv1_construct_logical_spe().
@@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq
*
*/
-int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
+int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
unsigned int class, unsigned int *virq)
{
int result;
@@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_bindi
return result;
}
- result = ps3_alloc_irq(cpu, outlet, virq);
+ result = ps3_irq_plug_setup(cpu, outlet, virq);
BUG_ON(result);
return result;
}
-int ps3_free_spe_irq(unsigned int virq)
+int ps3_spe_irq_destroy(unsigned int virq)
{
- ps3_free_irq(virq);
+ int result = ps3_irq_plug_destroy(virq);
+ BUG_ON(result);
return 0;
}
--- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/smp.c
+++ ps3-linux-dev/arch/powerpc/platforms/ps3/smp.c
@@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int
BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
for (i = 0; i < MSG_COUNT; i++) {
- result = ps3_alloc_event_irq(cpu, &virqs[i]);
+ result = ps3_event_receive_port_setup(cpu, &virqs[i]);
if (result)
continue;
@@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu)
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+
for (i = 0; i < MSG_COUNT; i++) {
- ps3_free_event_irq(virqs[i]);
free_irq(virqs[i], (void*)(long)i);
+ ps3_event_receive_port_destroy(virqs[i]);
virqs[i] = NO_IRQ;
}
+
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
}
--- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/spu.c
+++ ps3-linux-dev/arch/powerpc/platforms/ps3/spu.c
@@ -230,19 +230,19 @@ static int __init setup_interrupts(struc
{
int result;
- result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+ result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
0, &spu->irqs[0]);
if (result)
goto fail_alloc_0;
- result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+ result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
1, &spu->irqs[1]);
if (result)
goto fail_alloc_1;
- result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
+ result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
2, &spu->irqs[2]);
if (result)
@@ -251,9 +251,9 @@ static int __init setup_interrupts(struc
return result;
fail_alloc_2:
- ps3_free_spe_irq(spu->irqs[1]);
+ ps3_spe_irq_destroy(spu->irqs[1]);
fail_alloc_1:
- ps3_free_spe_irq(spu->irqs[0]);
+ ps3_spe_irq_destroy(spu->irqs[0]);
fail_alloc_0:
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
return result;
@@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *s
result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
BUG_ON(result);
- ps3_free_spe_irq(spu->irqs[2]);
- ps3_free_spe_irq(spu->irqs[1]);
- ps3_free_spe_irq(spu->irqs[0]);
+ ps3_spe_irq_destroy(spu->irqs[2]);
+ ps3_spe_irq_destroy(spu->irqs[1]);
+ ps3_spe_irq_destroy(spu->irqs[0]);
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
--- ps3-linux-dev.orig/drivers/ps3/vuart.c
+++ ps3-linux-dev/drivers/ps3/vuart.c
@@ -886,12 +886,12 @@ static int ps3_vuart_probe(struct device
if (++vuart_bus_priv.use_count == 1) {
- result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
+ result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
if (result) {
dev_dbg(&dev->core,
- "%s:%d: ps3_alloc_vuart_irq failed (%d)\n",
+ "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
__func__, __LINE__, result);
result = -EPERM;
goto fail_alloc_irq;
@@ -937,7 +937,7 @@ static int ps3_vuart_probe(struct device
fail_probe:
ps3_vuart_set_interrupt_mask(dev, 0);
fail_request_irq:
- ps3_free_vuart_irq(vuart_bus_priv.virq);
+ ps3_vuart_irq_destroy(vuart_bus_priv.virq);
vuart_bus_priv.virq = NO_IRQ;
fail_alloc_irq:
--vuart_bus_priv.use_count;
@@ -975,7 +975,7 @@ static int ps3_vuart_remove(struct devic
if (--vuart_bus_priv.use_count == 0) {
BUG();
free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
- ps3_free_vuart_irq(vuart_bus_priv.virq);
+ ps3_vuart_irq_destroy(vuart_bus_priv.virq);
vuart_bus_priv.virq = NO_IRQ;
}
--- ps3-linux-dev.orig/drivers/usb/host/ehci-ps3.c
+++ ps3-linux-dev/drivers/usb/host/ehci-ps3.c
@@ -97,7 +97,7 @@ static int ps3_ehci_sb_probe(struct ps3_
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
__LINE__, dev->m_region->lpar_addr);
- result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
+ result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
@@ -155,7 +155,7 @@ fail_add_hcd:
fail_ioremap:
usb_put_hcd(hcd);
fail_create_hcd:
- ps3_free_io_irq(virq);
+ ps3_io_irq_destroy(virq);
fail_irq:
ps3_free_mmio_region(dev->m_region);
fail_mmio:
--- ps3-linux-dev.orig/drivers/usb/host/ohci-ps3.c
+++ ps3-linux-dev/drivers/usb/host/ohci-ps3.c
@@ -99,7 +99,7 @@ static int ps3_ohci_sb_probe(struct ps3_
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
__LINE__, dev->m_region->lpar_addr);
- result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
+ result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
@@ -157,7 +157,7 @@ fail_add_hcd:
fail_ioremap:
usb_put_hcd(hcd);
fail_create_hcd:
- ps3_free_io_irq(virq);
+ ps3_io_irq_destroy(virq);
fail_irq:
ps3_free_mmio_region(dev->m_region);
fail_mmio:
--- ps3-linux-dev.orig/drivers/video/ps3fb.c
+++ ps3-linux-dev/drivers/video/ps3fb.c
@@ -885,8 +885,8 @@ static int ps3fb_vsync_settings(struct g
}
ps3fb.dev = dev;
- error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
- &ps3fb.irq_no);
+ error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+ &ps3fb.irq_no);
if (error) {
printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
error);
@@ -898,7 +898,7 @@ static int ps3fb_vsync_settings(struct g
if (error) {
printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
error);
- ps3_free_irq(ps3fb.irq_no);
+ ps3_irq_plug_destroy(ps3fb.irq_no);
return error;
}
@@ -1059,7 +1059,7 @@ err_framebuffer_release:
framebuffer_release(info);
err_free_irq:
free_irq(ps3fb.irq_no, ps3fb.dev);
- ps3_free_irq(ps3fb.irq_no);
+ ps3_irq_plug_destroy(ps3fb.irq_no);
err_iounmap_dinfo:
iounmap((u8 __iomem *)ps3fb.dinfo);
err_gpu_context_free:
@@ -1075,7 +1075,7 @@ static void ps3fb_shutdown(struct platfo
ps3fb_flip_ctl(0); /* flip off */
ps3fb.dinfo->irq.mask = 0;
free_irq(ps3fb.irq_no, ps3fb.dev);
- ps3_free_irq(ps3fb.irq_no);
+ ps3_irq_plug_destroy(ps3fb.irq_no);
iounmap((u8 __iomem *)ps3fb.dinfo);
}
@@ -1085,7 +1085,7 @@ void ps3fb_cleanup(void)
if (ps3fb.irq_no) {
free_irq(ps3fb.irq_no, ps3fb.dev);
- ps3_free_irq(ps3fb.irq_no);
+ ps3_irq_plug_destroy(ps3fb.irq_no);
}
iounmap((u8 __iomem *)ps3fb.dinfo);
--- ps3-linux-dev.orig/include/asm-powerpc/ps3.h
+++ ps3-linux-dev/include/asm-powerpc/ps3.h
@@ -167,26 +167,31 @@ enum ps3_cpu_binding {
PS3_BINDING_CPU_1 = 1,
};
-int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
+int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
unsigned int *virq);
-int ps3_free_io_irq(unsigned int virq);
-int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq);
-int ps3_free_event_irq(unsigned int virq);
+int ps3_virq_destroy(unsigned int virq);
+int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
+ unsigned int *virq);
+int ps3_irq_plug_destroy(unsigned int virq);
+int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_event_receive_port_destroy(unsigned int virq);
int ps3_send_event_locally(unsigned int virq);
-int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
- const struct ps3_device_id *did, unsigned int interrupt_id,
+
+int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
unsigned int *virq);
-int ps3_disconnect_event_irq(const struct ps3_device_id *did,
- unsigned int interrupt_id, unsigned int virq);
-int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
+int ps3_io_irq_destroy(unsigned int virq);
+int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
unsigned int *virq);
-int ps3_free_vuart_irq(unsigned int virq);
-int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
+int ps3_vuart_irq_destroy(unsigned int virq);
+int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
unsigned int class, unsigned int *virq);
-int ps3_free_spe_irq(unsigned int virq);
-int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
+int ps3_spe_irq_destroy(unsigned int virq);
+
+int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
+ const struct ps3_device_id *did, unsigned int interrupt_id,
unsigned int *virq);
-int ps3_free_irq(unsigned int virq);
+int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
+ unsigned int interrupt_id, unsigned int virq);
/* lv1 result codes */
--
^ permalink raw reply
* [patch 5/6] PS3: Fix system slowdown
From: Geoff Levand @ 2007-04-30 21:01 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20070430202420.872228544@am.sony.com>
From: Takao Shinohara <shin@sm.sony.co.jp>
The PS3 HV will deliver soft-disabled interrupts at the next HV call or
interrupt. Add an HV call to local_irq_restore() to force the timely
delivery of any pending interrupts.
This fixes the system slowdown bug reported here
http://bugzilla.kernel.org/show_bug.cgi?id=8260
From: Takao Shinohara <shin@sm.sony.co.jp>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
I made a request to change the behavior of the lv1 hypervisor to better
support the way we do soft-disable on Linux, but it is still not been
decided if and when that support will be done.
arch/powerpc/kernel/irq.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- ps3-linux-dev.orig/arch/powerpc/kernel/irq.c
+++ ps3-linux-dev/arch/powerpc/kernel/irq.c
@@ -67,6 +67,7 @@
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#include <asm/firmware.h>
+#include <asm/lv1call.h>
#endif
int __irq_offset_value;
@@ -162,6 +163,16 @@ void local_irq_restore(unsigned long en)
local_paca->hard_enabled = en;
if ((int)mfspr(SPRN_DEC) < 0)
mtspr(SPRN_DEC, 1);
+
+ /*
+ * Force the delivery of pending soft-disabled interrupts on PS3.
+ * Any HV call will have this side effect.
+ */
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+ u64 tmp;
+ lv1_get_version_info(&tmp);
+ }
+
hard_irq_enable();
}
#endif /* CONFIG_PPC64 */
--
^ permalink raw reply
* [patch 3/6] PS3: Remove duplicate variable assignement
From: Geoff Levand @ 2007-04-30 21:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20070430202420.872228544@am.sony.com>
A minor change to remove a duplicate variable assignement in ps3_mm_shutdown();
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/mm.c | 1 -
1 file changed, 1 deletion(-)
--- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/mm.c
+++ ps3-linux-dev/arch/powerpc/platforms/ps3/mm.c
@@ -826,5 +826,4 @@ void __init ps3_mm_init(void)
void ps3_mm_shutdown(void)
{
ps3_mm_region_destroy(&map.r1);
- map.total = map.rm.size;
}
--
^ permalink raw reply
* [patch 2/6] PS3: Add DABR support
From: Geoff Levand @ 2007-04-30 21:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <20070430202420.872228544@am.sony.com>
Add PS3 support for the PowerPC processor's Data Address Breakpoint Register
(DABR).
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/setup.c | 7 +++++++
1 files changed, 7 insertions(+)
--- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/setup.c
+++ ps3-linux-dev/arch/powerpc/platforms/ps3/setup.c
@@ -137,6 +137,12 @@ early_param("ps3fb", early_parse_ps3fb);
#define prealloc_ps3fb_videomemory() do { } while (0)
#endif
+static int ps3_set_dabr(u64 dabr)
+{
+ enum {DABR_USER = 1, DABR_KERNEL = 2,};
+
+ return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0;
+}
static void __init ps3_setup_arch(void)
{
@@ -234,6 +240,7 @@ define_machine(ps3) {
.get_boot_time = ps3_get_boot_time,
.set_rtc_time = ps3_set_rtc_time,
.get_rtc_time = ps3_get_rtc_time,
+ .set_dabr = ps3_set_dabr,
.calibrate_decr = ps3_calibrate_decr,
.progress = ps3_progress,
.restart = ps3_restart,
--
^ permalink raw reply
* [patch 1/6] PS3: Remove dev_dbg redefinition in ehci-ps3.c and ohci-ps3.c
From: Geoff Levand @ 2007-04-30 21:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20070430202420.872228544@am.sony.com>
Commit 404d5b185b4eb56d6fa2f7bd27833f8df1c38ce4 changed the definition
of dev_dbg in the !DEBUG case from being a #define to being a static
inline. There was code in usb/host/ehci-ps3.c and ohci-ps3.c to do
exactly that, which fails to compile now. This fixes it by removing
the redefinition, as the redefinition is now superfluous.
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
drivers/usb/host/ehci-ps3.c | 7 -------
drivers/usb/host/ohci-ps3.c | 8 --------
2 files changed, 15 deletions(-)
--- ps3-linux-dev.orig/drivers/usb/host/ehci-ps3.c
+++ ps3-linux-dev/drivers/usb/host/ehci-ps3.c
@@ -73,13 +73,6 @@ static const struct hc_driver ps3_ehci_h
#endif
};
-#if !defined(DEBUG)
-#undef dev_dbg
-static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
- const struct device *_dev, const char *fmt, ...) {return 0;}
-#endif
-
-
static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
{
int result;
--- ps3-linux-dev.orig/drivers/usb/host/ohci-ps3.c
+++ ps3-linux-dev/drivers/usb/host/ohci-ps3.c
@@ -75,14 +75,6 @@ static const struct hc_driver ps3_ohci_h
#endif
};
-/* redefine dev_dbg to do a syntax check */
-
-#if !defined(DEBUG)
-#undef dev_dbg
-static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
- const struct device *_dev, const char *fmt, ...) {return 0;}
-#endif
-
static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
{
int result;
--
^ permalink raw reply
* [patch 0/6] PS3: Patches for 2.6.22
From: Geoff Levand @ 2007-04-30 21:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Paul,
Here is a small set of six patches for 2.6.22. [patch 5/6] makes a
change to arch/powerpc/kernel/irq.c, so needs to be looked at
more closely.
[patch 6/6] PS3: Defconfig updates
[patch 5/6] PS3: Fix system slowdown
[patch 4/6] PS3: Interrupt routine fixups.
[patch 3/6] PS3: Remove duplicate variable assignement
[patch 2/6] PS3: Add DABR support
[patch 1/6] PS3: Remove dev_dbg redefinition in ehci-ps3.c and ohci-ps3.c
-Geoff
--
^ permalink raw reply
* Re: MPC5200 ethernet communication stops unexpected
From: Wolfgang Denk @ 2007-04-30 20:49 UTC (permalink / raw)
To: Eberhard Stoll; +Cc: linuxppc-embedded
In-Reply-To: <46322E3F.8050508@berghof.com>
In message <46322E3F.8050508@berghof.com> you wrote:
>
> It seems that this fault only occurs if the ping is done thru a telnet
> session. Logging into the controller on the serial console and doing the
> pings won't trigger the fault (at least not so fast). This might be a
According to our experience, it's actually not the "ping" which is
triggering the problem, but the telnet output you see (i. e. TCP/IP
traffic).
You will probaly see the same behaviour by running someting like
"telnet target_ip chargen >/dev/null" instead of the flood ping
(assuming you have enabled the chargen service on the target.
> If i do a 'ping -f 10.255.226.71 > /dev/null', which suppresses the
> output now run for hours ...
See above.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, CEO: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Bradley's Bromide: If computers get too powerful, we can organize
them into a committee - that will do them in.
^ permalink raw reply
* [PATCH] powerpc: fix spurious vectors on weird MPIC
From: Josh Boyer @ 2007-04-30 20:38 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
The weird TSI 10x MPIC needs an EOI after getting a spurious vector. This
patch uses the existing MPIC_SPV_EOI flag to fix this issue.
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
---
arch/powerpc/sysdev/mpic.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- linux-2.6.orig/arch/powerpc/sysdev/mpic.c
+++ linux-2.6/arch/powerpc/sysdev/mpic.c
@@ -1333,8 +1333,11 @@ unsigned int mpic_get_one_irq(struct mpi
#ifdef DEBUG_LOW
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
#endif
- if (unlikely(src == mpic->spurious_vec))
+ if (unlikely(src == mpic->spurious_vec)) {
+ if (mpic->flags & MPIC_SPV_EOI)
+ mpic_eoi(mpic);
return NO_IRQ;
+ }
return irq_linear_revmap(mpic->irqhost, src);
}
^ permalink raw reply
* Re: Revert "[POWERPC] <various>"
From: Simon Arlott @ 2007-04-30 19:56 UTC (permalink / raw)
To: Olaf Hering; +Cc: linuxppc-dev, Linux Kernel Mailing List
In-Reply-To: <20070430194911.GA1156@aepfle.de>
On 30/04/07 20:49, Olaf Hering wrote:
> On Mon, Apr 30, Simon Arlott wrote:
>
>> There are a few powerpc patches plus reverts in the recent push to
>> torvalds/linux-2.6 - shouldn't this be avoided whenever possible because it
>> could cause problems for people trying to use git bisect?
>
> The reverts do not cause compile failures (I hope).
> You may lose IDE if you happen to debug something on Pegasos.
> I'm sure the real bisect breakers are elsewhere.
The reverts themselves are not the real problem, a git bisect could occur
between the commit adding it and the one that reverts it. If that commit
introduced a bug then surely it would be better to avoid releasing it
elsewhere even if it will be reverted in the same batch.
Of course, this is probably difficult to do with git and impossible if
someone has cloned the bad commit already and tries to pull :/
Is it possible to mass copy all the good commits to create a clean branch?
--
Simon Arlott
^ permalink raw reply
* Re: patches for 2.6.22
From: Kim Phillips @ 2007-04-30 19:51 UTC (permalink / raw)
To: Paul Mackerras, Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <17969.56735.644629.328360@cargo.ozlabs.ibm.com>
On Fri, 27 Apr 2007 21:25:19 +1000
Paul Mackerras <paulus@samba.org> wrote:
> If anyone has patches that I haven't picked up yet which they think
> should go into 2.6.22, please send me either a pointer to the
these were missed:
[PATCH 1/4 v5] powerpc: document phy-connection-type property
Tue Apr 24 07:26:10 EST 2007
http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034669.html
[PATCH 2/4 v4] powerpc: replace undocumented interface properties in dts files
Tue Apr 24 07:26:14 EST 2007
http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034670.html
[PATCH 3/4] powerpc: Add 'mdio' to bus scan id list for platforms with QE UEC
Wed Apr 11 07:56:49 EST 2007
http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034163.html
[PATCH 4/4] powerpc: turn on corresponding PHY drivers in QE UEC platforms defconfigs
Wed Apr 11 07:56:53 EST 2007
http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034164.html
Kim
^ permalink raw reply
* Re: Revert "[POWERPC] <various>"
From: Olaf Hering @ 2007-04-30 19:49 UTC (permalink / raw)
To: Simon Arlott; +Cc: linuxppc-dev, Linux Kernel Mailing List
In-Reply-To: <46362B14.6090106@simon.arlott.org.uk>
On Mon, Apr 30, Simon Arlott wrote:
> There are a few powerpc patches plus reverts in the recent push to
> torvalds/linux-2.6 - shouldn't this be avoided whenever possible because it
> could cause problems for people trying to use git bisect?
The reverts do not cause compile failures (I hope).
You may lose IDE if you happen to debug something on Pegasos.
I'm sure the real bisect breakers are elsewhere.
^ permalink raw reply
* Re: Anyone using mpc832x_mds & freescale's GIT repo?
From: Kim Phillips @ 2007-04-30 18:52 UTC (permalink / raw)
To: Alex Zeffertt; +Cc: linuxppc-embedded
In-Reply-To: <4636081D.2000507@cambridgebroadband.com>
On Mon, 30 Apr 2007 16:15:41 +0100
Alex Zeffertt <ajz@cambridgebroadband.com> wrote:
> Hi list,
>
> I've got an MPC8323E-MDS-PB development board, which is
> running a year-old BSP from freescale. I wanted to track
> the most current developments so I cloned
>
> http://opensource.freescale.com/pub/scm/linux-2.6-83xx.git
>
that tree is obsolete; I'll label it so to avoid confusion.
> and rebuilt with ARCH=powerpc and using the mpc832x_mds_defconfig.
>
> I now don't get any serial console output after u-boot has
> started the kernel.
>
> My questions are:
>
> 1. Is anyone else using this GIT repo with this board?
>
please use the mpc83xx custodian tree on denx.de:
{git-,cg-}{clone,pull} git://www.denx.de/git/u-boot-mpc83xx.git
> 2. Is there an example u-boot environment for starting the latest kernels
> on this board?
the nfsboot and ramboot commands found in that board's default
environment specify the fdt address with the new bootm syntax.
>
> 3. Am I using the right ARCH. (I chose ARCH=powerpc because there's
> no defconfig file for this board under arch/ppc!)
>
yup.
Kim
^ permalink raw reply
* Re: [PATCH 12/13] powerpc: Add bootwrapper support for Motorola PrPMC2800 platform
From: Mark A. Greer @ 2007-04-30 18:19 UTC (permalink / raw)
To: Milton Miller; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <35d250938c0c5d7dae6a8735343059b7@bga.com>
On Mon, Apr 30, 2007 at 11:15:23AM -0500, Milton Miller wrote:
> On Thu Apr 26 10:02:27 EST 2007, Mark A. Greer wrote:
> >Add support for Motorola ECC PrPMC280/PrPMC2800 Platform.
> >The PrPMC280 sits on an F101 baseboard and the PrPMC2800 sits on a
> >F101e baseboard. Logic has been added to determine which board
> >(and variant thereof) the code is being run on.
>
> >
> >+ /* Update /mv64x60/device_type, if this is a mv64362 */
> >+ if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
> >+ devp = finddevice("/mv64x60");
> >+ if (devp == NULL)
> >+ fatal("Error: Missing /mv64x60 device tree
> >node\n\r");
> >+ setprop(devp, "device_type", "mv64362",
> >strlen("mv64362") + 1);
> >+ }
> >+
>
> That is not a device_type. It might be a model, Or even a
> compatable.
> but not a type.
How about "host-bridge" or is that too generic?
> >+ platform_ops.exit = prpmc2800_reset;
>
> No delay to let the user know see what is wrong?
I'll add a delay.
> >+
> >+/* Following code is put at very beginning of zImage (64KB into ELF
> >file) */
> >+asm (" .globl _zimage_start\n\
> >+ _zimage_start:\n\
> >+ mfmsr 10\n\
> >+ rlwinm 10,10,0,~(1<<15) /* Clear MSR_EE */\n\
> >+ sync\n\
> >+ mtmsr 10\n\
> >+ isync\n\
> >+ b _zimage_start_lib\n\
> >+");
> >
>
> That comment is very wrong. This object might be the first to be
> linked,
> and the text will be near the top. But there is nothing in that
> fragment
> to make it be the beginning of the image. Not even in the text section.
>
> That label will be the entrypoiint, so make the comment to that effect.
Yes, its a poorly worded comment.
> Also, the 1<<15 seems magic. I would like to see it as a constant in
> reg.h,
It probably makes sense to add some MSR definitions to reg.h.
> but to use that you would have to pass it as an i parameter, so
I don't follow. What's wrong with '#define MSR_EE (1<<15)'
in reg.h and 'rlwinm 10,10,0,~MSR_EE'?
Mark
^ permalink raw reply
* Re: [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
From: Mark A. Greer @ 2007-04-30 18:08 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1177951541.4616.4.camel@ld0161-tx32>
On Mon, Apr 30, 2007 at 11:45:41AM -0500, Jon Loeliger wrote:
> On Fri, 2007-04-27 at 15:41, Mark A. Greer wrote:
> > [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
> >
> > Signed-off-by: Mark A. Greer <mgreer@mvista.com>
> > ---
> >
> > prpmc2800.dts | 321 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 321 insertions(+)
> >
> > Index: powerpc/arch/powerpc/boot/dts/prpmc2800.dts
> > ===================================================================
> > --- /dev/null
> > +++ powerpc/arch/powerpc/boot/dts/prpmc2800.dts
> > @@ -0,0 +1,321 @@
> > +/* Device Tree Source for Motorola PrPMC2800
> > + *
> > + * Author: Mark A. Greer <mgreer@mvista.com>
> > + *
> > + * 2007 (c) MontaVista, Software, Inc. This file is licensed under
> > + * the terms of the GNU General Public License version 2. This program
> > + * is licensed "as is" without any warranty of any kind, whether express
> > + * or implied.
> > + *
> > + * To build:
> > + * dtc -I dts -O asm -o prpmc2800.S -V 16 -b 0 prpmc2800.dts
> > + * dtc -I dts -O dtb -o prpmc2800.dtb -V 16 -b 0 prpmc2800.dts
>
> Any real reason to keep the -V 16 in there?
> If not, please remove this advice!
Nope. It just got copied along...
Mark
^ permalink raw reply
* Revert "[POWERPC] <various>"
From: Simon Arlott @ 2007-04-30 17:44 UTC (permalink / raw)
To: Linux Kernel Mailing List, linuxppc-dev
There are a few powerpc patches plus reverts in the recent push to torvalds/linux-2.6 - shouldn't this be avoided whenever possible because it could cause problems for people trying to use git bisect?
--
Simon Arlott
^ permalink raw reply
* Re: [PATCH] powerpc: Add EDAC platform devices for 85xx
From: Dave Jiang @ 2007-04-30 17:37 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, bluesmoke-devel, david
In-Reply-To: <9903F55A-5E4E-42CE-8C27-6B7143B9FE25@kernel.crashing.org>
Kumar Gala wrote:
> On Apr 25, 2007, at 7:37 PM, Dave Jiang wrote:
>> +
>> +/* platform device setup for EDAC */
>
> Why not have the EDAC code for 85xx use of_device?
--
Kumar,
After doing some testing and looking around, it seems that for the 85xx only
the mds code calls the mpc85xx_publish_devices() which pulls in the soc devices
from the dts and creates them as of_devices. I do not see similar code for cds
and ads. Should that be added for ads and cds?
------------------------------------------------------
Dave Jiang
Software Engineer
MontaVista Software, Inc.
http://www.mvista.com
------------------------------------------------------
^ permalink raw reply
* Re: [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
From: Jon Loeliger @ 2007-04-30 16:45 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070427204148.GA14490@mag.az.mvista.com>
On Fri, 2007-04-27 at 15:41, Mark A. Greer wrote:
> [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
>
> Signed-off-by: Mark A. Greer <mgreer@mvista.com>
> ---
>
> prpmc2800.dts | 321 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 321 insertions(+)
>
> Index: powerpc/arch/powerpc/boot/dts/prpmc2800.dts
> ===================================================================
> --- /dev/null
> +++ powerpc/arch/powerpc/boot/dts/prpmc2800.dts
> @@ -0,0 +1,321 @@
> +/* Device Tree Source for Motorola PrPMC2800
> + *
> + * Author: Mark A. Greer <mgreer@mvista.com>
> + *
> + * 2007 (c) MontaVista, Software, Inc. This file is licensed under
> + * the terms of the GNU General Public License version 2. This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + *
> + * To build:
> + * dtc -I dts -O asm -o prpmc2800.S -V 16 -b 0 prpmc2800.dts
> + * dtc -I dts -O dtb -o prpmc2800.dtb -V 16 -b 0 prpmc2800.dts
Any real reason to keep the -V 16 in there?
If not, please remove this advice!
Thanks,
jdl
^ permalink raw reply
* I2C support for 8541
From: Charles Krinke @ 2007-04-30 16:25 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Randy Brown, Chris Carlson, Kevin Smith
In-Reply-To: <9F3F0A752CAEBE4FA7E906CC2FBFF57C06A1F4@MERCURY.inside.istor.com>
Assuming I have the external IRQ's understood, the next issue is the
hardware clock on our board with the linux-2.6.17.11 kernel. We are
using a "DS1338U", which is an I2C RTC.
I am trying to identify the relevant source for the 8541/8555 I2C
interface in the source base which reads/writes I2MOD, I2ADD, II2BRG,
I2COM, I2CER & I2CMR.
I can find a few references to MPC85xx_CPM_I2C in
../syslib/mpc85xx_devices.c, but nothing close in drivers/i2c/...
Can someone help me understand the completeness of the I2C source in the
2.6.17.11 kernel, please.
Charles Krinke
^ permalink raw reply
* RE: XILINX SPI IP core with INTC IP core.
From: Leonid @ 2007-04-30 16:19 UTC (permalink / raw)
To: Rick Moleres, Grant Likely, linuxppc-embedded
In-Reply-To: <20070430153149.E5489193005B@mail57-sin.bigfish.com>
Thanks a lot, Rick.
Do you happen to have also reference EDK design for Spartan-3e Starter
kit which has SPI core in it?
Thanks,
Leonid.
-----Original Message-----
From: Rick Moleres [mailto:Rick.Moleres@xilinx.com]=20
Sent: Monday, April 30, 2007 8:32 AM
To: Leonid; Grant Likely; linuxppc-embedded@ozlabs.org
Subject: RE: XILINX SPI IP core with INTC IP core.
Leonid,
Here's one that we've used (tested with Wind River's 2.6.14 and MV's
2.6.10 distributions).
-Rick
-----Original Message-----
From: Leonid [mailto:Leonid@a-k-a.net]=20
Sent: Friday, April 27, 2007 7:54 PM
To: Grant Likely; linuxppc-embedded@ozlabs.org
Cc: Rick Moleres
Subject: XILINX SPI IP core with INTC IP core.
Hi,
I'm trying to use SPI and INTC IP cores together. Does somebody have
adapter.c for SPI core, using interrupts?
Thanks,
Leonid.
^ permalink raw reply
* Re: [PATCH 12/13] powerpc: Add bootwrapper support for Motorola PrPMC2800 platform
From: Milton Miller @ 2007-04-30 16:15 UTC (permalink / raw)
To: Mark A. Greer; +Cc: ppcdev, Paul Mackerras
On Thu Apr 26 10:02:27 EST 2007, Mark A. Greer wrote:
> Add support for Motorola ECC PrPMC280/PrPMC2800 Platform.
> The PrPMC280 sits on an F101 baseboard and the PrPMC2800 sits on a
> F101e baseboard. Logic has been added to determine which board
> (and variant thereof) the code is being run on.
>
> + /* Update /mv64x60/device_type, if this is a mv64362 */
> + if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
> + devp = finddevice("/mv64x60");
> + if (devp == NULL)
> + fatal("Error: Missing /mv64x60 device tree
> node\n\r");
> + setprop(devp, "device_type", "mv64362",
> strlen("mv64362") + 1);
> + }
> +
That is not a device_type. It might be a model, Or even a
compatable.
but not a type.
> + platform_ops.exit = prpmc2800_reset;
No delay to let the user know see what is wrong?
> +
> +/* Following code is put at very beginning of zImage (64KB into ELF
> file) */
> +asm (" .globl _zimage_start\n\
> + _zimage_start:\n\
> + mfmsr 10\n\
> + rlwinm 10,10,0,~(1<<15) /* Clear MSR_EE */\n\
> + sync\n\
> + mtmsr 10\n\
> + isync\n\
> + b _zimage_start_lib\n\
> +");
>
That comment is very wrong. This object might be the first to be
linked,
and the text will be near the top. But there is nothing in that
fragment
to make it be the beginning of the image. Not even in the text section.
That label will be the entrypoiint, so make the comment to that effect.
Also, the 1<<15 seems magic. I would like to see it as a constant in
reg.h, but to use that you would have to pass it as an i parameter, so
I'm not sure it would improve.
milton
^ permalink raw reply
* Re: [PATCH 13/14] powerpc: add ps3 platform system bus support
From: Olaf Hering @ 2007-04-30 15:58 UTC (permalink / raw)
To: Geoff Levand; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <4636100C.7020006@am.sony.com>
On Mon, Apr 30, Geoff Levand wrote:
> > The generated modalias files do not match anything.
>
> Module support is still todo. I am just now started on it. David
> Woodhouse sent a few patches, but I just merged them in without
> testing.
This is my version, compile tested.
ps3fb calls into ps3av.
ps3av can be a module, but it does not force ps3fb to be a module as
well. Maybe this can be enforced via some Kconfig tweaks.
---
arch/powerpc/platforms/ps3/system-bus.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -167,6 +167,30 @@ static int ps3_system_bus_remove(struct
return 0;
}
+static const char *ps3_system_bus_modalias(enum ps3_match_id match_id)
+{
+ const char *p;
+ switch (match_id) {
+ case PS3_MATCH_ID_EHCI:
+ p = "ps3-ehci";
+ break;
+ case PS3_MATCH_ID_OHCI:
+ p = "ps3-ohci";
+ break;
+ case PS3_MATCH_ID_GELIC:
+ p = "gelic_net";
+ break;
+ case PS3_MATCH_ID_AV_SETTINGS:
+ p = "ps3av";
+ break;
+ case PS3_MATCH_ID_SYSTEM_MANAGER:
+ default:
+ p = "unknown";
+ break;
+ }
+ return p;
+}
+
static int ps3_system_bus_uevent(struct device *_dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
@@ -174,8 +198,8 @@ static int ps3_system_bus_uevent(struct
int i=0, length = 0;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "MODALIAS=ps3:%d",
- dev->match_id))
+ &length, "MODALIAS=%s",
+ ps3_system_bus_modalias(dev->match_id)))
return -ENOMEM;
envp[i] = NULL;
@@ -186,7 +210,7 @@ static ssize_t modalias_show(struct devi
char *buf)
{
struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
- int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+ int len = snprintf(buf, PAGE_SIZE, "%s\n", ps3_system_bus_modalias(dev->match_id));
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
^ permalink raw reply
* Re: [PATCH 13/14] powerpc: add ps3 platform system bus support
From: Geoff Levand @ 2007-04-30 15:49 UTC (permalink / raw)
To: Olaf Hering; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070430104714.GA25815@aepfle.de>
Olaf Hering wrote:
> On Tue, Nov 21, Geoff Levand wrote:
>
>> Adds a PS3 system bus driver. This system bus is a virtual bus used to present
>> the PS3 system devices in the LDM.
>
> What is the benefit of yet another bus?
We need a bus to abstract the MMIO, DMA and interrupt specifics of
the hypervisor.
> Can those 3 drivers be platform devices instead?
It is my understanding that the platform bus was made to
support legacy code.
We plan to put all the devices on the system bus. That work
is now in progress.
> The generated modalias files do not match anything.
Module support is still todo. I am just now started on it. David
Woodhouse sent a few patches, but I just merged them in without
testing.
-Geoff
^ permalink raw reply
* Anyone using mpc832x_mds & freescale's GIT repo?
From: Alex Zeffertt @ 2007-04-30 15:15 UTC (permalink / raw)
To: linuxppc-embedded
Hi list,
I've got an MPC8323E-MDS-PB development board, which is
running a year-old BSP from freescale. I wanted to track
the most current developments so I cloned
http://opensource.freescale.com/pub/scm/linux-2.6-83xx.git
and rebuilt with ARCH=powerpc and using the mpc832x_mds_defconfig.
I now don't get any serial console output after u-boot has
started the kernel.
My questions are:
1. Is anyone else using this GIT repo with this board?
2. Is there an example u-boot environment for starting the latest kernels
on this board?
3. Am I using the right ARCH. (I chose ARCH=powerpc because there's
no defconfig file for this board under arch/ppc!)
TIA,
Alex
^ permalink raw reply
* ram not at 0? anyone?
From: rvk @ 2007-04-30 15:40 UTC (permalink / raw)
To: linuxppc-embedded
I've learned a little more, looking at PPC_MEMSTART from
include/asm-ppc/page.h, and it seems there is some relevant infra. However
I'm still worried about the tophys() and tovirt() implementations used by
head_4xx.S. Can anyone comment who has experience with RAM not at physical
0? I don't have the board yet, but it will be Xilinx Virtex 4 ppc405.
--
View this message in context: http://www.nabble.com/ram-not-at-0--anyone--tf3670343.html#a10255622
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
^ permalink raw reply
* RE: XILINX SPI IP core with INTC IP core.
From: Rick Moleres @ 2007-04-30 15:31 UTC (permalink / raw)
To: Leonid, Grant Likely, linuxppc-embedded
In-Reply-To: <406A31B117F2734987636D6CCC93EE3CB0598B@ehost011-3.exch011.intermedia.net>
[-- Attachment #1: Type: text/plain, Size: 487 bytes --]
Leonid,
Here's one that we've used (tested with Wind River's 2.6.14 and MV's
2.6.10 distributions).
-Rick
-----Original Message-----
From: Leonid [mailto:Leonid@a-k-a.net]
Sent: Friday, April 27, 2007 7:54 PM
To: Grant Likely; linuxppc-embedded@ozlabs.org
Cc: Rick Moleres
Subject: XILINX SPI IP core with INTC IP core.
Hi,
I'm trying to use SPI and INTC IP cores together. Does somebody have
adapter.c for SPI core, using interrupts?
Thanks,
Leonid.
[-- Attachment #2: xspi_adapter.c --]
[-- Type: application/octet-stream, Size: 18284 bytes --]
/*
* xspi_adapter.c
*
* Xilinx Adapter component to interface SPI component to Linux
*
* Only master mode is supported. One or more slaves can be served.
*
* Author: MontaVista Software, Inc.
* akonovalov@ru.mvista.com, or source@mvista.com
*
* 2004-2006 (c) MontaVista, Software, Inc. This file is licensed under the
* terms of the GNU General Public License version 2. This program is licensed
* "as is" without any warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h> /* wait_event_interruptible */
#include <linux/bitops.h> /* ffs() */
#include <linux/slab.h> /* kmalloc() etc. */
#include <linux/moduleparam.h>
#include <linux/xilinx_devices.h>
#include <linux/device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/page.h> /* PAGE_SIZE */
#include "xspi.h"
#include "xspi_i.h"
#include "xspi_ioctl.h"
#define XSPI_DEFAULT_MAJOR 123
#define XSPI_DEFAULT_MINOR 0 /* The minors start from this value */
#define XSPI_MINORS 4 /* Allocate 4 minors for this driver */
static int xspi_major = XSPI_DEFAULT_MAJOR;
static int xspi_minor = XSPI_DEFAULT_MINOR;
static int xspi_no_minors = XSPI_MINORS;
module_param(xspi_major, int, S_IRUGO);
module_param(xspi_minor, int, S_IRUGO);
#define XSPI_NAME "xilinx_spi"
/*
* Debugging macros
*/
#define DEBUG_FLOW 0x0001
#define DEBUG_STAT 0x0002
#define DEBUG_MASK 0x0000
#if (DEBUG_MASK != 0)
#define d_printk(str...) printk(str)
#else
#define d_printk(str...) /* nothing */
#endif
#if ((DEBUG_MASK & DEBUG_FLOW) != 0)
#define func_enter() printk("xspi: enter %s\n", __FUNCTION__)
#define func_exit() printk("xspi: exit %s\n", __FUNCTION__)
#else
#define func_enter()
#define func_exit()
#endif
/* These options are always set by the driver. */
#define XSPI_DEFAULT_OPTIONS (XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION)
/* These options can be changed by the user. */
#define XSPI_CHANGEABLE_OPTIONS (XSP_CLK_ACTIVE_LOW_OPTION | XSP_CLK_PHASE_1_OPTION \
| XSP_LOOPBACK_OPTION)
/* Our private per interface data. */
struct xspi_instance {
u32 phys_addr; /* Saved physical base address */
ulong remap_size;
u32 device_id;
unsigned int irq; /* device IRQ number */
wait_queue_head_t waitq; /* For those waiting until SPI is busy */
struct semaphore sem;
int use_count;
struct cdev cdev; /* Char device structure */
/* The flag ISR uses to tell the transfer completion status
* (the values are defined in "xstatus.h"; set to 0 before the transfer) */
int completion_status;
/* The actual number of bytes transferred */
int tx_count;
/* The object used by Xilinx OS independent code */
XSpi Spi;
};
/*******************************************************************************
* This configuration stuff should become unnecessary after EDK version 8.x is
* released.
******************************************************************************/
static DECLARE_MUTEX(cfg_sem);
static int convert_status(XStatus status)
{
switch (status) {
case XST_SUCCESS:
return 0;
case XST_DEVICE_NOT_FOUND:
return -ENODEV;
case XST_DEVICE_BUSY:
return -EBUSY;
default:
return -EIO;
}
}
/*
* Simple function that hands an interrupt to the Xilinx code.
* dev_id contains a pointer to proper XSpi instance.
*/
static irqreturn_t xspi_isr(int irq, void *dev_id, struct pt_regs *regs)
{
XSpi_InterruptHandler((XSpi *) dev_id);
return IRQ_HANDLED;
}
/*
* This function is called back from the XSpi interrupt handler
* when one of the following status events occures:
* XST_SPI_TRANSFER_DONE - the requested data transfer is done,
* XST_SPI_RECEIVE_OVERRUN - Rx FIFO overrun, transmission continues,
* XST_SPI_MODE_FAULT - should not happen: the driver doesn't support multiple masters,
* XST_SPI_TRANSMIT_UNDERRUN,
* XST_SPI_SLAVE_MODE_FAULT - should not happen: the driver doesn't support slave mode.
*/
static void xspi_status_handler(void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount)
{
struct xspi_instance *dev = (struct xspi_instance *) CallBackRef;
dev->completion_status = StatusEvent;
if (StatusEvent == XST_SPI_TRANSFER_DONE) {
dev->tx_count = (int) ByteCount;
wake_up_interruptible(&dev->waitq);
} else if (StatusEvent == XST_SPI_RECEIVE_OVERRUN) {
/* As both Rx and Tx FIFO have the same sizes
this should not happen in master mode.
That is why we consider Rx overrun as severe error
and abort the transfer */
dev->tx_count = (int) ByteCount;
XSpi_Abort(&dev->Spi);
wake_up_interruptible(&dev->waitq);
printk(KERN_ERR XSPI_NAME " %d: Rx overrun!!!.\n",
dev->device_id);
} else if (StatusEvent == XST_SPI_MODE_FAULT) {
wake_up_interruptible(&dev->waitq);
} else {
printk(KERN_ERR XSPI_NAME " %d: Invalid status event %u.\n",
dev->device_id, StatusEvent);
}
}
/*
* To be called from xspi_ioctl(), xspi_read(), and xspi_write().
*
* xspi_ioctl() uses both wr_buf and rd_buf.
* xspi_read() doesn't care of what is sent, and sets wr_buf to NULL.
* xspi_write() doesn't care of what it receives, and sets rd_buf to NULL.
*
* Set slave_ind to negative value if the currently selected SPI slave
* device is to be used.
*
* Returns the number of bytes transferred (0 or positive value)
* or error code (negative value).
*/
static int xspi_transfer(struct xspi_instance *dev, const char *wr_buf,
char *rd_buf, int count, int slave_ind)
{
int retval;
unsigned char *tmp_buf;
if (count <= 0)
return 0;
/* Limit the count value to the small enough one.
This prevents a denial-of-service attack by using huge count values
thus making everything to be swapped out to free the space
for this huge buffer */
if (count > 8192)
count = 8192;
/* Allocate buffer in the kernel space (it is first filled with
the data to send, then these data are overwritten with the
received data) */
tmp_buf = kmalloc(count, GFP_KERNEL);
if (tmp_buf == NULL)
return -ENOMEM;
/* Fill the buffer with data to send */
if (wr_buf == NULL) {
/* zero the buffer not to expose the kernel data */
memset(tmp_buf, 0, count);
} else {
if (copy_from_user(tmp_buf, wr_buf, count) != 0) {
kfree(tmp_buf);
return -EFAULT;
}
}
/* Lock the device */
if (down_interruptible(&dev->sem)) {
kfree(tmp_buf);
return -ERESTARTSYS;
}
/* The while cycle below never loops - this is just a convenient
way to handle the errors */
while (TRUE) {
/* Select the proper slave if requested to do so */
if (slave_ind >= 0) {
retval =
convert_status(XSpi_SetSlaveSelect
(&dev->Spi,
0x00000001 << slave_ind));
if (retval != 0)
break;
}
/* Initiate transfer */
dev->completion_status = 0;
retval = convert_status(XSpi_Transfer(&dev->Spi, tmp_buf,
(rd_buf ==
NULL) ? NULL : tmp_buf,
count));
if (retval != 0)
break;
/* Put the process to sleep */
if (wait_event_interruptible(dev->waitq,
dev->completion_status != 0) !=
0) {
/* ... woken up by the signal */
retval = -ERESTARTSYS;
break;
}
/* ... woken up by the transfer completed interrupt */
if (dev->completion_status != XST_SPI_TRANSFER_DONE) {
retval = -EIO;
break;
}
/* Copy the received data to user if rd_buf != NULL */
if (rd_buf != NULL &&
copy_to_user(rd_buf, tmp_buf, dev->tx_count) != 0) {
retval = -EFAULT;
break;
}
retval = dev->tx_count;
break;
} /* while(TRUE) */
/* Unlock the device, free the buffer and return */
up(&dev->sem);
kfree(tmp_buf);
return retval;
}
static int
xspi_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct xspi_instance *dev = filp->private_data;
/* paranoia check */
if (!dev)
return -ENODEV;
switch (cmd) {
case XSPI_IOC_GETSLAVESELECT:
{
int i;
i = ffs(XSpi_GetSlaveSelect(&dev->Spi)) - 1;
return put_user(i, (int *) arg); /* -1 means nothing selected */
}
break;
case XSPI_IOC_SETSLAVESELECT:
{
int i;
int retval;
if (get_user(i, (int *) arg) != 0)
return -EFAULT;
if (i < -1 || i > 31)
return -EINVAL;
/* Lock the device. */
if (down_interruptible(&dev->sem))
return -ERESTARTSYS;
if (i == -1)
retval =
convert_status(XSpi_SetSlaveSelect
(&dev->Spi, 0));
else
retval =
convert_status(XSpi_SetSlaveSelect
(&dev->Spi, (u32) 1 << i));
/* Unlock the device. */
up(&dev->sem);
return retval;
}
break;
case XSPI_IOC_GETOPTS:
{
struct xspi_ioc_options xspi_opts;
u32 xspi_options;
xspi_options = XSpi_GetOptions(&dev->Spi);
memset(&xspi_opts, 0, sizeof (xspi_opts));
if (dev->Spi.HasFifos)
xspi_opts.has_fifo = 1;
if (xspi_options & XSP_CLK_ACTIVE_LOW_OPTION)
xspi_opts.clk_level = 1;
if (xspi_options & XSP_CLK_PHASE_1_OPTION)
xspi_opts.clk_phase = 1;
if (xspi_options & XSP_LOOPBACK_OPTION)
xspi_opts.loopback = 1;
xspi_opts.slave_selects = dev->Spi.NumSlaveBits;
return put_user(xspi_opts,
(struct xspi_ioc_options *) arg);
}
break;
case XSPI_IOC_SETOPTS:
{
struct xspi_ioc_options xspi_opts;
u32 xspi_options;
int retval;
if (copy_from_user(&xspi_opts,
(struct xspi_ioc_options *) arg,
sizeof (struct xspi_ioc_options)) !=
0)
return -EFAULT;
/* Lock the device. */
if (down_interruptible(&dev->sem))
return -ERESTARTSYS;
/* Read current settings and set the changeable ones. */
xspi_options = XSpi_GetOptions(&dev->Spi)
& ~XSPI_CHANGEABLE_OPTIONS;
if (xspi_opts.clk_level != 0)
xspi_options |= XSP_CLK_ACTIVE_LOW_OPTION;
if (xspi_opts.clk_phase != 0)
xspi_options |= XSP_CLK_PHASE_1_OPTION;
if (xspi_opts.loopback != 0)
xspi_options |= XSP_LOOPBACK_OPTION;
retval =
convert_status(XSpi_SetOptions
(&dev->Spi, xspi_options));
/* Unlock the device. */
up(&dev->sem);
return retval;
}
break;
case XSPI_IOC_TRANSFER:
{
struct xspi_ioc_transfer_data trans_data;
int retval;
if (copy_from_user(&trans_data,
(struct xspi_ioc_transfer_data *)
arg,
sizeof (struct
xspi_ioc_transfer_data)) !=
0)
return -EFAULT;
/* Transfer the data. */
retval = xspi_transfer(dev, trans_data.write_buf,
trans_data.read_buf,
trans_data.count,
trans_data.slave_index);
if (retval > 0)
return 0;
else
return retval;
}
break;
default:
return -ENOTTY; /* redundant */
} /* switch(cmd) */
return -ENOTTY;
}
static ssize_t
xspi_read(struct file *filp, char *buf, size_t count, loff_t * not_used)
{
struct xspi_instance *dev = filp->private_data;
/* Set the 2nd arg to NULL to indicate we don't care what to send;
set the last arg to -1 to talk to the currently selected SPI
slave */
return xspi_transfer(dev, NULL, buf, count, -1);
}
static ssize_t
xspi_write(struct file *filp, const char *buf, size_t count, loff_t * not_used)
{
struct xspi_instance *dev = filp->private_data;
/* Set the 3d arg to NULL to indicate we are not interested in
the data read; set the last arg to -1 to talk to the currently
selected SPI slave */
return xspi_transfer(dev, buf, NULL, count, -1);
}
static int
xspi_open(struct inode *inode, struct file *filp)
{
int retval = 0;
struct xspi_instance *dev;
func_enter();
dev = container_of(inode->i_cdev, struct xspi_instance, cdev);
filp->private_data = dev; /* for other methods */
if (dev == NULL)
return -ENODEV;
if (down_interruptible(&dev->sem))
return -EINTR;
while (dev->use_count++ == 0) {
/*
* This was the first opener; we need to get the IRQ,
* and to setup the device as master.
*/
retval = request_irq(dev->irq, xspi_isr, 0, XSPI_NAME,
&dev->Spi);
if (retval != 0) {
printk(KERN_ERR XSPI_NAME
"%d: Could not allocate interrupt %d.\n",
dev->device_id, dev->irq);
break;
}
if (XSpi_SetOptions(&dev->Spi, XSPI_DEFAULT_OPTIONS) !=
XST_SUCCESS) {
printk(KERN_ERR XSPI_NAME
"%d: Could not set device options.\n",
dev->device_id);
free_irq(dev->irq, &dev->Spi);
retval = -EIO;
break;
}
if (XSpi_Start(&dev->Spi) != XST_SUCCESS) {
printk(KERN_ERR XSPI_NAME
"%d: Could not start the device.\n",
dev->device_id);
free_irq(dev->irq, &dev->Spi);
retval = -EIO;
break;
}
break;
}
if (retval != 0)
--dev->use_count;
up(&dev->sem);
return retval;
}
static int
xspi_release(struct inode *inode, struct file *filp)
{
struct xspi_instance *dev = filp->private_data;
func_enter();
if (down_interruptible(&dev->sem))
return -EINTR;
if (--dev->use_count == 0) {
/* This was the last closer: stop the device and free the IRQ */
if (wait_event_interruptible(dev->waitq,
XSpi_Stop(&dev->Spi) !=
XST_DEVICE_BUSY) != 0) {
/* Abort transfer by brute force */
XSpi_Abort(&dev->Spi);
}
disable_irq(dev->irq);
free_irq(dev->irq, &dev->Spi);
}
up(&dev->sem);
return 0;
}
struct file_operations xspi_fops = {
.open = xspi_open,
.release = xspi_release,
.read = xspi_read,
.write = xspi_write,
.ioctl = xspi_ioctl,
};
static int __init check_spi_config(XSpi_Config * cfg)
{
if (cfg->SlaveOnly || cfg->NumSlaveBits == 0)
return -1;
else
return 0; /* the configuration is supported by this driver */
}
/******************************
* The platform device driver *
******************************/
static int xspi_probe(struct device *dev)
{
dev_t devt;
XSpi_Config xspi_cfg;
struct platform_device *pdev = to_platform_device(dev);
struct xspi_platform_data *pdata;
struct xspi_instance *inst;
struct resource *irq_res, *regs_res;
unsigned long remap_size;
u32 virtaddr;
int retval;
if (!dev)
return -EINVAL;
pdata = (struct xspi_platform_data *) pdev->dev.platform_data;
if (!pdata) {
printk(KERN_ERR XSPI_NAME " %d: Couldn't find platform data.\n",
pdev->id);
return -ENODEV;
}
devt = MKDEV(xspi_major, xspi_minor + pdev->id);
inst = kmalloc(sizeof(struct xspi_instance), GFP_KERNEL);
memset(inst, 0, sizeof(*inst));
if (!inst) {
printk(KERN_ERR XSPI_NAME " #%d: Could not allocate device.\n",
pdev->id);
return -ENOMEM;
}
dev_set_drvdata(dev, (void *)inst);
init_MUTEX(&inst->sem);
init_waitqueue_head(&inst->waitq);
/* Find irq number, map the control registers in */
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs_res || !irq_res) {
printk(KERN_ERR XSPI_NAME" #%d: IO resource(s) not found\n",
pdev->id);
retval = -EFAULT;
goto failed1;
}
inst->irq = irq_res->start;
remap_size = regs_res->end - regs_res->start + 1;
if (!request_mem_region(regs_res->start, remap_size, XSPI_NAME)) {
printk(KERN_ERR XSPI_NAME
" #%d: Couldn't lock memory region at 0x%08lX\n",
pdev->id, regs_res->start);
retval = -EBUSY;
goto failed1;
}
inst->remap_size = remap_size;
inst->phys_addr = regs_res->start;
inst->device_id = pdev->id;
xspi_cfg.DeviceId = pdev->id;
xspi_cfg.HasFifos = (pdata->device_flags & XSPI_HAS_FIFOS) ? 1 : 0;
xspi_cfg.SlaveOnly = (pdata->device_flags & XSPI_SLAVE_ONLY) ? 1 : 0;
xspi_cfg.NumSlaveBits = pdata->num_slave_bits;
if(check_spi_config(&xspi_cfg)) {
printk(KERN_ERR XSPI_NAME
" #%d: Unsupported hardware configuration\n", pdev->id);
retval = -ENODEV;
goto failed1;
}
virtaddr = (u32) ioremap(regs_res->start, remap_size);
if (virtaddr == 0) {
printk(KERN_ERR XSPI_NAME
" #%d: Couldn't ioremap memory at 0x%08lX\n",
pdev->id, regs_res->start);
retval = -EFAULT;
goto failed2;
}
/* Tell the Xilinx code to bring this SPI interface up. */
if (XSpi_CfgInitialize(&inst->Spi, &xspi_cfg, virtaddr) != XST_SUCCESS) {
printk(KERN_ERR XSPI_NAME " #%d: Could not initialize device.\n",
pdev->id);
retval = -ENODEV;
goto failed3;
}
/* Set interrupt callback */
XSpi_SetStatusHandler(&inst->Spi, inst, xspi_status_handler);
/* request_irq() is done in open() */
cdev_init(&inst->cdev, &xspi_fops);
inst->cdev.owner = THIS_MODULE;
retval = cdev_add(&inst->cdev, devt, 1);
if (retval) {
printk(KERN_ERR XSPI_NAME " #%d: cdev_add() failed\n",
pdev->id);
goto failed3;
}
printk(KERN_INFO XSPI_NAME
" %d: at 0x%08X mapped to 0x%08X, irq=%d\n",
pdev->id, inst->phys_addr, inst->Spi.BaseAddr, inst->irq);
return 0; /* success */
failed3:
iounmap((void *) (xspi_cfg.BaseAddress));
failed2:
release_mem_region(regs_res->start, remap_size);
failed1:
kfree(inst);
return retval;
}
static int xspi_remove(struct device *dev)
{
struct xspi_instance *inst;
if (!dev)
return -EINVAL;
inst = (struct xspi_instance *) dev_get_drvdata(dev);
cdev_del(&inst->cdev);
iounmap((void *) (inst->Spi.BaseAddr));
release_mem_region(inst->phys_addr, inst->remap_size);
kfree(inst);
dev_set_drvdata(dev, NULL);
return 0; /* success */
}
static struct device_driver xspi_driver = {
.name = XSPI_NAME,
.bus = &platform_bus_type,
.probe = xspi_probe,
.remove = xspi_remove
};
static int __init xspi_init(void)
{
dev_t devt;
int retval;
if (xspi_major) {
devt = MKDEV(xspi_major, xspi_minor);
retval = register_chrdev_region(devt, xspi_no_minors,
XSPI_NAME);
} else {
retval = alloc_chrdev_region(&devt, xspi_minor, xspi_no_minors,
XSPI_NAME);
xspi_major = MAJOR(devt);
}
if (retval < 0) {
xspi_major = 0;
return retval;
}
retval = driver_register(&xspi_driver);
if (retval) {
unregister_chrdev_region(devt, xspi_no_minors);
}
return retval;
}
static void __exit xspi_cleanup(void)
{
dev_t devt = MKDEV(xspi_major, xspi_minor);
driver_unregister(&xspi_driver);
unregister_chrdev_region(devt, xspi_no_minors);
}
module_init(xspi_init);
module_exit(xspi_cleanup);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");
MODULE_LICENSE("GPL");
^ 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