162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * MPC5200 PSC serial console support.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Grant Likely <grant.likely@secretlab.ca>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2007 Secret Lab Technologies Ltd.
862306a36Sopenharmony_ci * Copyright (c) 2007 Freescale Semiconductor, Inc.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * It is assumed that the firmware (or the platform file) has already set
1162306a36Sopenharmony_ci * up the port.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "types.h"
1562306a36Sopenharmony_ci#include "io.h"
1662306a36Sopenharmony_ci#include "ops.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Programmable Serial Controller (PSC) status register bits */
1962306a36Sopenharmony_ci#define MPC52xx_PSC_SR		0x04
2062306a36Sopenharmony_ci#define MPC52xx_PSC_SR_RXRDY		0x0100
2162306a36Sopenharmony_ci#define MPC52xx_PSC_SR_RXFULL		0x0200
2262306a36Sopenharmony_ci#define MPC52xx_PSC_SR_TXRDY		0x0400
2362306a36Sopenharmony_ci#define MPC52xx_PSC_SR_TXEMP		0x0800
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define MPC52xx_PSC_BUFFER	0x0C
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic void *psc;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic int psc_open(void)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	/* Assume the firmware has already configured the PSC into
3262306a36Sopenharmony_ci	 * uart mode */
3362306a36Sopenharmony_ci	return 0;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic void psc_putc(unsigned char c)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	while (!(in_be16(psc + MPC52xx_PSC_SR) & MPC52xx_PSC_SR_TXRDY)) ;
3962306a36Sopenharmony_ci	out_8(psc + MPC52xx_PSC_BUFFER, c);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic unsigned char psc_tstc(void)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	return (in_be16(psc + MPC52xx_PSC_SR) & MPC52xx_PSC_SR_RXRDY) != 0;
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic unsigned char psc_getc(void)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	while (!(in_be16(psc + MPC52xx_PSC_SR) & MPC52xx_PSC_SR_RXRDY)) ;
5062306a36Sopenharmony_ci	return in_8(psc + MPC52xx_PSC_BUFFER);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciint mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	/* Get the base address of the psc registers */
5662306a36Sopenharmony_ci	if (dt_get_virtual_reg(devp, &psc, 1) < 1)
5762306a36Sopenharmony_ci		return -1;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	scdp->open = psc_open;
6062306a36Sopenharmony_ci	scdp->putc = psc_putc;
6162306a36Sopenharmony_ci	scdp->getc = psc_getc;
6262306a36Sopenharmony_ci	scdp->tstc = psc_tstc;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	return 0;
6562306a36Sopenharmony_ci}
66