LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices

Reply
 
Search this Thread
Old 04-19-2010, 12:48 PM   #1
DamOTclese
LQ Newbie
 
Registered: Aug 2009
Posts: 2

Rep: Reputation: 0
Power PC PSC UART Kernel Object just not working


This has got me stumped to the point where I have spent 5 days with little sleep trying to find what I did wrong. It should be simple yet it doesn't work.

All I want to do is create a test /dev/fred device driver that will allow me to test my hardware, all I want to do is transmit some bytes out PSC5. It *should* be a simple matter:

1) Make sure PSC5's PADs are configured for Function 0, DS of 1
2) Make sure SCCR1 has PSC4, 5, and 6 ENABLED
3) Configure the PSC's registers for UART mode, transmit/receive enable, all that happy stuff.
4) Have an open, close, read, write, ioctl function

What happens is that everything hangs together just fine, when I open(/dev/fred) my open_iproc_psc6_uart2() gets called and everything gets configured -- I request memory, remap it, release memory as needed.

When write(/dev/fred) is called, my driver's ech_write() is called and when read(/dev/fred) is called, my ech_read() driver function gets called -- great stuff, it should be *easy*.

The problem is, I get nothing out the transmit pin of the PSC.

I must be missing a step.

Can anyone tell me if I missed a configuration register some where? A clock I need to set? I'll have to sleep on this and maybe inpiration will come but this is such a simple thing I'm trying to do, it should work. In fact I compare my code against three examples on the Internet and it looks functionally the same.

Code with debugging / un-needed stuff added to try to figure out whyt nothing comes out the serial transmit pin:

// ----------------------------------------------------------------------
// This is a device driver that creates /dev/fred and is used to send
// and receive serial data on PSC6. It's just a test driver, something
// to verify that the hardware works.
//
// make CROSS_COMPILE=powerpc-e300c3-linux-gnu- ARCH=powerpc
//
// ----------------------------------------------------------------------

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/param.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <asm/mpc512x.h>
#include <asm/mpc52xx_psc.h>
#include "fdriver.h"

#define DEBUG_PRN(...) if (1) printk(__VA_ARGS__)

// ----------------------------------------------------------------------
// This is the PSC that we will be working with
//
// ----------------------------------------------------------------------

#define THIS_PSC PSC5

// ----------------------------------------------------------------------
// Local data storage
//
// ----------------------------------------------------------------------

static void __iomem * test_base_p;
static void __iomem * sccr1_base_p;
static void * mem_held_p;
static void * sccr1_held_p;
static ulong sccr1_value;

static struct mpc52xx_psc __iomem * psc_p =
(struct mpc52xx_psc __iomem *)NULL;

static void report_pads(void)
{
ulong * pads_p = (ulong *)NULL;
void __iomem * pad_base_p = (void __iomem *)NULL;
int mode1 = 0;

mode1 = check_mem_region(0x8000A000UL, 0x1000);

if (mode1 < 0)
{
DEBUG_PRN("<1>Check of PAD address space %lx failed\n", 0x8000A000UL);

return;
}

// See if we can get the address space we want

if (! request_mem_region(0x8000A000UL, 0x1000, "test"))
{
DEBUG_PRN("<1>Unable to get PAD address space %lx\n", 0x8000A000UL);

return;
}

DEBUG_PRN("<1>Got PAD address space %lx\n", 0x8000A000UL);

// Remap the CPU registers' physical IO to a local block

pad_base_p = ioremap(0x8000A000UL, 0x1000);

if ((void __iomem *)NULL == pad_base_p)
{
DEBUG_PRN("<1>Unable to map PAD address space\n");

// Make sure to release held blocks

release_mem_region(0x8000A000UL, 0x1000);

return;
}

DEBUG_PRN("<1>PAD Registers remapped %lx\n", (ulong)pad_base_p);

// See what PSC3 is set to

pads_p = (pad_base_p + 0x0248);
DEBUG_PRN("<1> 0x0248 is %lx\n", *pads_p);
pads_p = (pad_base_p + 0x024c);
DEBUG_PRN("<1> 0x024C is %lx\n", *pads_p);
pads_p = (pad_base_p + 0x0250);
DEBUG_PRN("<1> 0x0250 is %lx\n", *pads_p);
pads_p = (pad_base_p + 0x0254);
DEBUG_PRN("<1> 0x0254 is %lx\n", *pads_p);
pads_p = (pad_base_p + 0x0258);
DEBUG_PRN("<1> 0x0258 is %lx\n", *pads_p);

// PSC4

pads_p = (pad_base_p + 0x025C);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0260);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0264);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0268);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x026C);
*pads_p = 0x03UL;

// PSC5

pads_p = (pad_base_p + 0x0270);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0274);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0278);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x027C);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0280);
*pads_p = 0x03UL;

// PSC6

pads_p = (pad_base_p + 0x0284);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0288);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x028C);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0290);
*pads_p = 0x03UL;
pads_p = (pad_base_p + 0x0294);
*pads_p = 0x03UL;

// We're done with that block

iounmap((void *)pad_base_p);

release_mem_region(0x8000A000UL, 0x1000);
}

static uchar open_iproc_psc6_uart2(void)
{
int mode1 = 0;
int mode2 = 0;

// See if we can get the address spaces we want

mode1 = check_mem_region(CPU_REG_BASE, 0x1000);

if (mode1 < 0)
{
DEBUG_PRN("<1>Check of CPU address space %lx failed\n", CPU_REG_BASE);
}

mode2 = check_mem_region(UART_BASE_ADD + THIS_PSC, 0x1000);

if (mode2 < 0)
{
DEBUG_PRN("<1>Check of UART address space %lx failed\n",
UART_BASE_ADD + THIS_PSC);
}

// Are we banned from utilizing either blocks?

if (mode1 < 0 || mode2 < 0)
{
// Don't bother to request them, then.

return(10);
}

// See if we can get the address space we want

if (! (sccr1_held_p = request_mem_region(CPU_REG_BASE, 0x1000, "test")))
{
DEBUG_PRN("<1>Unable to get CPU address space %lx\n", CPU_REG_BASE);

return(10);
}

DEBUG_PRN("<1>Got CPU address space %lx\n", CPU_REG_BASE);

if (! (mem_held_p = request_mem_region(UART_BASE_ADD + THIS_PSC,
0x1000, "test")))
{
DEBUG_PRN("<1>Unable to get UART address space %lx\n",
UART_BASE_ADD + THIS_PSC);

// Since we successfully held the CPU base, release it

release_mem_region(CPU_REG_BASE, 0x1000);

return(10);
}

DEBUG_PRN("<1>Got UART address space %lx\n", UART_BASE_ADD + THIS_PSC);

// Remap the CPU registers' physical IO to a local block

sccr1_base_p = ioremap(CPU_REG_BASE, 0x1000);

if ((void __iomem *)NULL == sccr1_base_p)
{
DEBUG_PRN("<1>Unable to map CPU address space\n");

// Make sure to release both held blocks

release_mem_region(CPU_REG_BASE, 0x1000);

release_mem_region(UART_BASE_ADD + THIS_PSC, 0x1000);

// report the fact that it failed

return(10);
}

DEBUG_PRN("<1>CPU Registers successfully remapped\n");

// Get the current value of the SCCR1 register

sccr1_value = ioread32be(sccr1_base_p + CLOCK_BLOCK + SCCR1);

DEBUG_PRN("<1>Read bef SCCR1: %lx\n", (ulong)sccr1_value);

// Set bit 21, the PSC6 enable bit

sccr1_value |= (1 << 21);

// Set bit 22, the PSC5 enable bit

sccr1_value |= (1 << 22);

// Set bit 23, the PSC4 enable bit

sccr1_value |= (1 << 23);

// Set those bits

iowrite32be(sccr1_value, sccr1_base_p + CLOCK_BLOCK + SCCR1);

DEBUG_PRN("<1>Read aft SCCR1: %lx\n",
(ulong)ioread32be(sccr1_base_p + CLOCK_BLOCK + SCCR1));

// get the value of CCCR

sccr1_value = ioread32be(sccr1_base_p + CLOCK_BLOCK + CCCR);

DEBUG_PRN("<1>Read bef CCCR: %lx\n", (ulong)sccr1_value);

// And set the Clock Control Registers

iowrite32be(0xFFFE0000UL, sccr1_base_p + CLOCK_BLOCK + P4SCCR);
iowrite32be(0xFFFE0000UL, sccr1_base_p + CLOCK_BLOCK + P5SCCR);
iowrite32be(0xFFFE0000UL, sccr1_base_p + CLOCK_BLOCK + P6SCCR);

DEBUG_PRN("<1>Read aft P4SCCR: %lx P5SCCR: %lx P6SCCR: %lx\n",
(ulong)ioread32be(sccr1_base_p + CLOCK_BLOCK + P4SCCR),
(ulong)ioread32be(sccr1_base_p + CLOCK_BLOCK + P5SCCR),
(ulong)ioread32be(sccr1_base_p + CLOCK_BLOCK + P6SCCR));

// We're done with that block

iounmap((void *)sccr1_base_p);

release_mem_region(CPU_REG_BASE, 0x1000);

// Remap the THIS_PSCs' physical IO to a local block

test_base_p = ioremap(UART_BASE_ADD + THIS_PSC, 0x1000);

if ((void __iomem *)NULL == test_base_p)
{
DEBUG_PRN("<1>Unable to map UART address space %lx\n",
UART_BASE_ADD + THIS_PSC);

// Be sure to release that

release_mem_region(UART_BASE_ADD + THIS_PSC, 0x1000);

// Be sure to mark the fact

mem_held_p = 0;

return(10);
}

DEBUG_PRN("<1>Base PSC from %lx to %lx\n",
(UART_BASE_ADD + THIS_PSC), (ulong)test_base_p);

// Point to the PSC 6

psc_p = (struct mpc52xx_psc __iomem *)test_base_p;

psc_p->command = MPC52xx_PSC_SEL_MODE_REG_1;

psc_p->command = MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_DISABLE;

psc_p->mpc52xx_psc_clock_select = 0xdd00;

psc_p->sicr = 0UL;

psc_p->mode = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE;

psc_p->mode = MPC52xx_PSC_MODE_ONE_STOP;

// Baud rate

psc_p->ctur = 0;

psc_p->ctlr = 6;

psc_p->isr_imr.imr = 0;

psc_p->command = MPC52xx_PSC_RST_RX;

psc_p->command = MPC52xx_PSC_RST_TX;

psc_p->command = MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_ENABLE;

// Report success

return(0);
}

static void serial_putc(const char c)
{
if (test_base_p == (void __iomem *)NULL)
{
DEBUG_PRN("<1>Can not put\n");
return;
}

while ((psc_p->mpc52xx_psc_status & MPC52xx_PSC_SR_TXEMP) == 0x00)
{
}

psc_p->mpc52xx_psc_buffer_8 = c;
}

static char serial_getc(void)
{
if (test_base_p == (void __iomem *)NULL)
{
DEBUG_PRN("<1>Can not get\n");
return(0);
}

while ((psc_p->mpc52xx_psc_status & MPC52xx_PSC_SR_RXRDY) == 0x00)
{
}

return(psc_p->mpc52xx_psc_buffer_8);
}

static int serial_testc(void)
{
if (test_base_p == (void __iomem *)NULL)
{
DEBUG_PRN("<1>Can not test\n");
return(0);
}

__asm__ volatile("sync");

return((psc_p->mpc52xx_psc_status & MPC52xx_PSC_SR_RXRDY) != 0);
}

static int ech_ioctl(struct inode *inode_p,
struct file *file_p,
unsigned int cmd,
unsigned long arg)
{
DEBUG_PRN("<1>Test driver ioctl.\n");

return(0);
}

static int ech_write(struct file *fp,
const char *buffp,
size_t sz,
loff_t *fpos)
{
int original_size = sz;

while(sz-- > 0)
{
serial_putc(*buffp++);
}

return(original_size);
}

static int ech_read(struct file *fp,
char *buffp,
size_t sz,
loff_t *fpos)
{
ssize_t result = 0;

if (test_base_p == (void __iomem *)NULL)
{
return(0);
}

while (serial_testc() && result < sz)
{
*buffp++ = serial_getc();

result++;
}

if (result > 0)
{
DEBUG_PRN("<1>Read of %u bytes\n", result);
}
else
{
DEBUG_PRN("<1>Read status %x - %x\n",
psc_p->mpc52xx_psc_status,
psc_p->mpc52xx_psc_buffer_8);
}

return(result);
}

static int ech_open(struct inode *inode, struct file *file_p)
{
DEBUG_PRN("<1>Test driver open.\n");

report_pads();

open_iproc_psc6_uart2();

return(0);
}

static int ech_release(struct inode *inode, struct file *file)
{
DEBUG_PRN("<1>Test driver released.\n");

if (test_base_p != (void __iomem *)NULL)
{
// We're done with the IO block

iounmap((void *)test_base_p);

test_base_p = (void __iomem *)NULL;
}

if (0 != mem_held_p)
{
release_mem_region(UART_BASE_ADD + THIS_PSC, 0x1000);

mem_held_p = 0;
}

return(0);
}

// ----------------------------------------------------------------------
// Define the file structure, the pointers to the operations that
// the device driver will support.
//
// ----------------------------------------------------------------------

struct file_operations ech_fops =
{
.owner = THIS_MODULE,
.read = ech_read,
.write = ech_write,
.ioctl = ech_ioctl,
.open = ech_open,
.release = ech_release
} ;

int ech_init_module(void)
{
int stat = 0;

test_base_p = (void __iomem *)NULL;
sccr1_base_p = (void __iomem *)NULL;
mem_held_p = (void *)NULL;
sccr1_held_p = (void *)NULL;

// Register the device

stat = register_chrdev(DEV_MAJOR, DEV_NAME, &ech_fops);

// Was that successful?

if (stat < 0)
{
DEBUG_PRN("<1>Error registering test driver\n");
}
else
{
DEBUG_PRN("<1>Successfully registered %s with %u\n", DEV_NAME, stat);
}

// Return the result of the registration effort

return(stat);
}

void __exit ech_cleanup_module (void)
{
// Unregister the device

unregister_chrdev(DEV_MAJOR, DEV_NAME);

// Report the fact that the registration was removed

DEBUG_PRN("<1>Test driver removed.\n");
}

module_init(ech_init_module);
module_exit(ech_cleanup_module);

MODULE_LICENSE("Proprietary");
MODULE_DESCRIPTION("Fred Testing");
 
Old 05-03-2010, 06:16 AM   #2
smoker
Senior Member
 
Registered: Oct 2004
Distribution: Fedora Core 4, 12, 13, 14, 15, 17
Posts: 2,279

Rep: Reputation: 248Reputation: 248Reputation: 248
This thread is marked Solved, but I see no explanation here.
Why is that ?
 
  


Reply

Tags
pc, power, psc, uart


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] HP PSC 1315 - Printer detected under CUPs but not working (hplip/hpijs driver) vharishankar Linux - Hardware 19 09-01-2009 02:26 PM
Need an XP hp psc 1300 series driver to print to a psc 1350 connected to Fiesty Fawn Eycks Linux - Networking 4 11-10-2007 06:46 PM
how to modified 16c550 uart driver from kernel 2.4 to 2.6 first1113 Programming 3 03-02-2007 01:24 PM
HP PSC 2175 stopped working... nbcohen Linux - Hardware 6 02-20-2007 02:09 PM
New kernel doesn't recognize my modem's UART Kanaflloric Linux - Hardware 0 09-28-2004 10:54 PM


All times are GMT -5. The time now is 09:06 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration