Linux Audio

Check our new training course

Loading...
v4.17
  1/*
  2 * MPSC/UART driver for the Marvell mv64360, mv64460, ...
  3 *
  4 * Author: Mark A. Greer <mgreer@mvista.com>
  5 *
  6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
  7 * the terms of the GNU General Public License version 2. This program
  8 * is licensed "as is" without any warranty of any kind, whether express
  9 * or implied.
 10 */
 11
 12#include <stdarg.h>
 13#include <stddef.h>
 14#include "types.h"
 15#include "string.h"
 16#include "stdio.h"
 17#include "io.h"
 18#include "ops.h"
 19
 20
 21#define MPSC_CHR_1		0x000c
 22
 23#define MPSC_CHR_2		0x0010
 24#define MPSC_CHR_2_TA		(1<<7)
 25#define MPSC_CHR_2_TCS		(1<<9)
 26#define MPSC_CHR_2_RA		(1<<23)
 27#define MPSC_CHR_2_CRD		(1<<25)
 28#define MPSC_CHR_2_EH		(1<<31)
 29
 30#define MPSC_CHR_4		0x0018
 31#define MPSC_CHR_4_Z		(1<<29)
 32
 33#define MPSC_CHR_5		0x001c
 34#define MPSC_CHR_5_CTL1_INTR	(1<<12)
 35#define MPSC_CHR_5_CTL1_VALID	(1<<15)
 36
 37#define MPSC_CHR_10		0x0030
 38
 39#define MPSC_INTR_CAUSE		0x0000
 40#define MPSC_INTR_CAUSE_RCC	(1<<6)
 41#define MPSC_INTR_MASK		0x0080
 42
 43#define SDMA_SDCM		0x0008
 44#define SDMA_SDCM_AR		(1<<15)
 45#define SDMA_SDCM_AT		(1<<31)
 46
 47static volatile char *mpsc_base;
 48static volatile char *mpscintr_base;
 49static u32 chr1, chr2;
 50
 51static int mpsc_open(void)
 52{
 53	chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000;
 54	chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA
 55			| MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD
 56			| MPSC_CHR_2_EH);
 57	out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z);
 58	out_le32((u32 *)(mpsc_base + MPSC_CHR_5),
 59			MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID);
 60	out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH);
 61	return 0;
 62}
 63
 64static void mpsc_putc(unsigned char c)
 65{
 66	while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);
 67
 68	out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c);
 69	out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS);
 70}
 71
 72static unsigned char mpsc_getc(void)
 73{
 74	u32 cause = 0;
 75	unsigned char c;
 76
 77	while (!(cause & MPSC_INTR_CAUSE_RCC))
 78		cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));
 79
 80	c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2));
 81	out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c);
 82	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE),
 83			cause & ~MPSC_INTR_CAUSE_RCC);
 84
 85	return c;
 86}
 87
 88static u8 mpsc_tstc(void)
 89{
 90	return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
 91				& MPSC_INTR_CAUSE_RCC) != 0);
 92}
 93
 94static void mpsc_stop_dma(volatile char *sdma_base)
 95{
 96	out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA);
 97	out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT);
 98
 99	while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
100				& (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
101		udelay(100);
102}
103
104static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
105{
106	void *v;
107	int n;
108
109	n = getprop(devp, prop, &v, sizeof(v));
110	if (n != sizeof(v))
111		goto err_out;
112
113	devp = find_node_by_linuxphandle((u32)v);
114	if (devp == NULL)
115		goto err_out;
116
117	n = getprop(devp, "virtual-reg", &v, sizeof(v));
118	if (n == sizeof(v))
119		return v;
120
121err_out:
122	return NULL;
123}
124
125int mpsc_console_init(void *devp, struct serial_console_data *scdp)
126{
127	void *v;
128	int n, reg_set;
129	volatile char *sdma_base;
130
131	n = getprop(devp, "virtual-reg", &v, sizeof(v));
132	if (n != sizeof(v))
133		goto err_out;
134	mpsc_base = v;
135
136	sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
137	if (sdma_base == NULL)
138		goto err_out;
139
140	mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
141	if (mpscintr_base == NULL)
142		goto err_out;
143
144	n = getprop(devp, "cell-index", &v, sizeof(v));
145	if (n != sizeof(v))
146		goto err_out;
147	reg_set = (int)v;
148
149	mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;
150
151	/* Make sure the mpsc ctlrs are shutdown */
152	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
153	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
154	out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
155	out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
156
157	mpsc_stop_dma(sdma_base);
158
159	scdp->open = mpsc_open;
160	scdp->putc = mpsc_putc;
161	scdp->getc = mpsc_getc;
162	scdp->tstc = mpsc_tstc;
163	scdp->close = NULL;
164
165	return 0;
166
167err_out:
168	return -1;
169}
v4.10.11
  1/*
  2 * MPSC/UART driver for the Marvell mv64360, mv64460, ...
  3 *
  4 * Author: Mark A. Greer <mgreer@mvista.com>
  5 *
  6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
  7 * the terms of the GNU General Public License version 2. This program
  8 * is licensed "as is" without any warranty of any kind, whether express
  9 * or implied.
 10 */
 11
 12#include <stdarg.h>
 13#include <stddef.h>
 14#include "types.h"
 15#include "string.h"
 16#include "stdio.h"
 17#include "io.h"
 18#include "ops.h"
 19
 20
 21#define MPSC_CHR_1		0x000c
 22
 23#define MPSC_CHR_2		0x0010
 24#define MPSC_CHR_2_TA		(1<<7)
 25#define MPSC_CHR_2_TCS		(1<<9)
 26#define MPSC_CHR_2_RA		(1<<23)
 27#define MPSC_CHR_2_CRD		(1<<25)
 28#define MPSC_CHR_2_EH		(1<<31)
 29
 30#define MPSC_CHR_4		0x0018
 31#define MPSC_CHR_4_Z		(1<<29)
 32
 33#define MPSC_CHR_5		0x001c
 34#define MPSC_CHR_5_CTL1_INTR	(1<<12)
 35#define MPSC_CHR_5_CTL1_VALID	(1<<15)
 36
 37#define MPSC_CHR_10		0x0030
 38
 39#define MPSC_INTR_CAUSE		0x0000
 40#define MPSC_INTR_CAUSE_RCC	(1<<6)
 41#define MPSC_INTR_MASK		0x0080
 42
 43#define SDMA_SDCM		0x0008
 44#define SDMA_SDCM_AR		(1<<15)
 45#define SDMA_SDCM_AT		(1<<31)
 46
 47static volatile char *mpsc_base;
 48static volatile char *mpscintr_base;
 49static u32 chr1, chr2;
 50
 51static int mpsc_open(void)
 52{
 53	chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000;
 54	chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA
 55			| MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD
 56			| MPSC_CHR_2_EH);
 57	out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z);
 58	out_le32((u32 *)(mpsc_base + MPSC_CHR_5),
 59			MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID);
 60	out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH);
 61	return 0;
 62}
 63
 64static void mpsc_putc(unsigned char c)
 65{
 66	while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);
 67
 68	out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c);
 69	out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS);
 70}
 71
 72static unsigned char mpsc_getc(void)
 73{
 74	u32 cause = 0;
 75	unsigned char c;
 76
 77	while (!(cause & MPSC_INTR_CAUSE_RCC))
 78		cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));
 79
 80	c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2));
 81	out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c);
 82	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE),
 83			cause & ~MPSC_INTR_CAUSE_RCC);
 84
 85	return c;
 86}
 87
 88static u8 mpsc_tstc(void)
 89{
 90	return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
 91				& MPSC_INTR_CAUSE_RCC) != 0);
 92}
 93
 94static void mpsc_stop_dma(volatile char *sdma_base)
 95{
 96	out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA);
 97	out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT);
 98
 99	while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
100				& (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
101		udelay(100);
102}
103
104static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
105{
106	void *v;
107	int n;
108
109	n = getprop(devp, prop, &v, sizeof(v));
110	if (n != sizeof(v))
111		goto err_out;
112
113	devp = find_node_by_linuxphandle((u32)v);
114	if (devp == NULL)
115		goto err_out;
116
117	n = getprop(devp, "virtual-reg", &v, sizeof(v));
118	if (n == sizeof(v))
119		return v;
120
121err_out:
122	return NULL;
123}
124
125int mpsc_console_init(void *devp, struct serial_console_data *scdp)
126{
127	void *v;
128	int n, reg_set;
129	volatile char *sdma_base;
130
131	n = getprop(devp, "virtual-reg", &v, sizeof(v));
132	if (n != sizeof(v))
133		goto err_out;
134	mpsc_base = v;
135
136	sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
137	if (sdma_base == NULL)
138		goto err_out;
139
140	mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
141	if (mpscintr_base == NULL)
142		goto err_out;
143
144	n = getprop(devp, "cell-index", &v, sizeof(v));
145	if (n != sizeof(v))
146		goto err_out;
147	reg_set = (int)v;
148
149	mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;
150
151	/* Make sure the mpsc ctlrs are shutdown */
152	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
153	out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
154	out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
155	out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
156
157	mpsc_stop_dma(sdma_base);
158
159	scdp->open = mpsc_open;
160	scdp->putc = mpsc_putc;
161	scdp->getc = mpsc_getc;
162	scdp->tstc = mpsc_tstc;
163	scdp->close = NULL;
164
165	return 0;
166
167err_out:
168	return -1;
169}